Full Code of tornadoweb/tornado for AI

master 31b3d09dcfc3 cached
317 files
2.0 MB
533.0k tokens
3471 symbols
1 requests
Download .txt
Showing preview only (2,125K chars total). Download the full file or copy to clipboard to get everything.
Repository: tornadoweb/tornado
Branch: master
Commit: 31b3d09dcfc3
Files: 317
Total size: 2.0 MB

Directory structure:
gitextract_4dy2dktj/

├── .coveragerc
├── .flake8
├── .gitattributes
├── .github/
│   ├── workflows/
│   │   ├── build.yml
│   │   └── test.yml
│   └── zizmor.yml
├── .gitignore
├── .readthedocs.yaml
├── CONTRIBUTING.md
├── LICENSE
├── MANIFEST.in
├── README.rst
├── SECURITY.md
├── codecov.yml
├── demos/
│   ├── README.rst
│   ├── blog/
│   │   ├── Dockerfile
│   │   ├── README
│   │   ├── blog.py
│   │   ├── docker-compose.yml
│   │   ├── requirements.txt
│   │   ├── schema.sql
│   │   ├── static/
│   │   │   └── blog.css
│   │   └── templates/
│   │       ├── archive.html
│   │       ├── base.html
│   │       ├── compose.html
│   │       ├── create_author.html
│   │       ├── entry.html
│   │       ├── feed.xml
│   │       ├── home.html
│   │       ├── login.html
│   │       └── modules/
│   │           └── entry.html
│   ├── chat/
│   │   ├── chatdemo.py
│   │   ├── static/
│   │   │   ├── chat.css
│   │   │   └── chat.js
│   │   └── templates/
│   │       ├── index.html
│   │       └── message.html
│   ├── facebook/
│   │   ├── README
│   │   ├── facebook.py
│   │   ├── static/
│   │   │   ├── facebook.css
│   │   │   └── facebook.js
│   │   └── templates/
│   │       ├── modules/
│   │       │   └── post.html
│   │       └── stream.html
│   ├── file_upload/
│   │   ├── file_receiver.py
│   │   └── file_uploader.py
│   ├── google_auth/
│   │   ├── .gitignore
│   │   └── main.py
│   ├── helloworld/
│   │   └── helloworld.py
│   ├── tcpecho/
│   │   ├── README.md
│   │   ├── client.py
│   │   └── server.py
│   ├── websocket/
│   │   ├── chatdemo.py
│   │   ├── static/
│   │   │   ├── chat.css
│   │   │   └── chat.js
│   │   └── templates/
│   │       ├── index.html
│   │       └── message.html
│   └── webspider/
│       └── webspider.py
├── docs/
│   ├── Makefile
│   ├── asyncio.rst
│   ├── auth.rst
│   ├── autoreload.rst
│   ├── caresresolver.rst
│   ├── concurrent.rst
│   ├── conf.py
│   ├── coroutine.rst
│   ├── escape.rst
│   ├── faq.rst
│   ├── gen.rst
│   ├── guide/
│   │   ├── async.rst
│   │   ├── coroutines.rst
│   │   ├── intro.rst
│   │   ├── queues.rst
│   │   ├── running.rst
│   │   ├── security.rst
│   │   ├── structure.rst
│   │   └── templates.rst
│   ├── guide.rst
│   ├── http.rst
│   ├── http1connection.rst
│   ├── httpclient.rst
│   ├── httpserver.rst
│   ├── httputil.rst
│   ├── index.rst
│   ├── integration.rst
│   ├── ioloop.rst
│   ├── iostream.rst
│   ├── locale.rst
│   ├── locks.rst
│   ├── log.rst
│   ├── netutil.rst
│   ├── networking.rst
│   ├── options.rst
│   ├── process.rst
│   ├── queues.rst
│   ├── releases/
│   │   ├── v1.0.0.rst
│   │   ├── v1.0.1.rst
│   │   ├── v1.1.0.rst
│   │   ├── v1.1.1.rst
│   │   ├── v1.2.0.rst
│   │   ├── v1.2.1.rst
│   │   ├── v2.0.0.rst
│   │   ├── v2.1.0.rst
│   │   ├── v2.1.1.rst
│   │   ├── v2.2.0.rst
│   │   ├── v2.2.1.rst
│   │   ├── v2.3.0.rst
│   │   ├── v2.4.0.rst
│   │   ├── v2.4.1.rst
│   │   ├── v3.0.0.rst
│   │   ├── v3.0.1.rst
│   │   ├── v3.0.2.rst
│   │   ├── v3.1.0.rst
│   │   ├── v3.1.1.rst
│   │   ├── v3.2.0.rst
│   │   ├── v3.2.1.rst
│   │   ├── v3.2.2.rst
│   │   ├── v4.0.0.rst
│   │   ├── v4.0.1.rst
│   │   ├── v4.0.2.rst
│   │   ├── v4.1.0.rst
│   │   ├── v4.2.0.rst
│   │   ├── v4.2.1.rst
│   │   ├── v4.3.0.rst
│   │   ├── v4.4.0.rst
│   │   ├── v4.4.1.rst
│   │   ├── v4.4.2.rst
│   │   ├── v4.4.3.rst
│   │   ├── v4.5.0.rst
│   │   ├── v4.5.1.rst
│   │   ├── v4.5.2.rst
│   │   ├── v4.5.3.rst
│   │   ├── v5.0.0.rst
│   │   ├── v5.0.1.rst
│   │   ├── v5.0.2.rst
│   │   ├── v5.1.0.rst
│   │   ├── v5.1.1.rst
│   │   ├── v6.0.0.rst
│   │   ├── v6.0.1.rst
│   │   ├── v6.0.2.rst
│   │   ├── v6.0.3.rst
│   │   ├── v6.0.4.rst
│   │   ├── v6.1.0.rst
│   │   ├── v6.2.0.rst
│   │   ├── v6.3.0.rst
│   │   ├── v6.3.1.rst
│   │   ├── v6.3.2.rst
│   │   ├── v6.3.3.rst
│   │   ├── v6.4.0.rst
│   │   ├── v6.4.1.rst
│   │   ├── v6.4.2.rst
│   │   ├── v6.5.0.rst
│   │   ├── v6.5.1.rst
│   │   ├── v6.5.2.rst
│   │   ├── v6.5.3.rst
│   │   ├── v6.5.4.rst
│   │   └── v6.5.5.rst
│   ├── releases.rst
│   ├── routing.rst
│   ├── tcpclient.rst
│   ├── tcpserver.rst
│   ├── template.rst
│   ├── testing.rst
│   ├── twisted.rst
│   ├── util.rst
│   ├── utilities.rst
│   ├── web.rst
│   ├── webframework.rst
│   ├── websocket.rst
│   └── wsgi.rst
├── maint/
│   ├── README
│   ├── benchmark/
│   │   ├── benchmark.py
│   │   ├── chunk_benchmark.py
│   │   ├── gen_benchmark.py
│   │   ├── parsing_benchmark.py
│   │   └── template_benchmark.py
│   ├── scripts/
│   │   ├── custom_fixers/
│   │   │   ├── __init__.py
│   │   │   ├── fix_future_imports.py
│   │   │   └── fix_unicode_literal.py
│   │   ├── run_autopep8.sh
│   │   ├── run_fixers.py
│   │   ├── runcog.sh
│   │   └── test_resolvers.py
│   ├── test/
│   │   ├── README
│   │   ├── cython/
│   │   │   ├── .gitignore
│   │   │   ├── MANIFEST.in
│   │   │   ├── cythonapp.pyx
│   │   │   ├── cythonapp_test.py
│   │   │   ├── pythonmodule.py
│   │   │   ├── setup.py
│   │   │   └── tox.ini
│   │   ├── mypy/
│   │   │   ├── .gitignore
│   │   │   ├── bad.py
│   │   │   ├── good.py
│   │   │   ├── setup.py
│   │   │   └── tox.ini
│   │   ├── redbot/
│   │   │   ├── README
│   │   │   ├── red_test.py
│   │   │   └── tox.ini
│   │   └── websocket/
│   │       ├── .gitignore
│   │       ├── client.py
│   │       ├── fuzzingclient.json
│   │       ├── fuzzingserver.json
│   │       ├── run-client.sh
│   │       ├── run-server.sh
│   │       ├── server.py
│   │       └── tox.ini
│   └── vm/
│       ├── README
│       ├── freebsd/
│       │   ├── Vagrantfile
│       │   ├── setup.sh
│       │   └── tox.ini
│       ├── shared-setup.sh
│       ├── ubuntu12.04/
│       │   ├── Vagrantfile
│       │   ├── setup.sh
│       │   └── tox.ini
│       ├── ubuntu14.04/
│       │   ├── Vagrantfile
│       │   ├── setup.sh
│       │   └── tox.ini
│       └── windows/
│           ├── bootstrap.py
│           └── tox.ini
├── pyproject.toml
├── requirements.in
├── requirements.txt
├── runtests.sh
├── setup.cfg
├── setup.py
├── tornado/
│   ├── __init__.py
│   ├── __init__.pyi
│   ├── _locale_data.py
│   ├── auth.py
│   ├── autoreload.py
│   ├── concurrent.py
│   ├── curl_httpclient.py
│   ├── escape.py
│   ├── gen.py
│   ├── http1connection.py
│   ├── httpclient.py
│   ├── httpserver.py
│   ├── httputil.py
│   ├── ioloop.py
│   ├── iostream.py
│   ├── locale.py
│   ├── locks.py
│   ├── log.py
│   ├── netutil.py
│   ├── options.py
│   ├── platform/
│   │   ├── __init__.py
│   │   ├── asyncio.py
│   │   ├── caresresolver.py
│   │   └── twisted.py
│   ├── process.py
│   ├── py.typed
│   ├── queues.py
│   ├── routing.py
│   ├── simple_httpclient.py
│   ├── speedups.c
│   ├── speedups.pyi
│   ├── tcpclient.py
│   ├── tcpserver.py
│   ├── template.py
│   ├── test/
│   │   ├── __init__.py
│   │   ├── __main__.py
│   │   ├── asyncio_test.py
│   │   ├── auth_test.py
│   │   ├── autoreload_test.py
│   │   ├── circlerefs_test.py
│   │   ├── concurrent_test.py
│   │   ├── csv_translations/
│   │   │   └── fr_FR.csv
│   │   ├── curl_httpclient_test.py
│   │   ├── escape_test.py
│   │   ├── gen_test.py
│   │   ├── gettext_translations/
│   │   │   ├── extract_me.py
│   │   │   └── fr_FR/
│   │   │       └── LC_MESSAGES/
│   │   │           ├── tornado_test.mo
│   │   │           └── tornado_test.po
│   │   ├── http1connection_test.py
│   │   ├── httpclient_test.py
│   │   ├── httpserver_test.py
│   │   ├── httputil_test.py
│   │   ├── import_test.py
│   │   ├── ioloop_test.py
│   │   ├── iostream_test.py
│   │   ├── locale_test.py
│   │   ├── locks_test.py
│   │   ├── log_test.py
│   │   ├── netutil_test.py
│   │   ├── options_test.cfg
│   │   ├── options_test.py
│   │   ├── options_test_types.cfg
│   │   ├── options_test_types_str.cfg
│   │   ├── process_test.py
│   │   ├── queues_test.py
│   │   ├── resolve_test_helper.py
│   │   ├── routing_test.py
│   │   ├── runtests.py
│   │   ├── simple_httpclient_test.py
│   │   ├── static/
│   │   │   ├── dir/
│   │   │   │   └── index.html
│   │   │   ├── robots.txt
│   │   │   ├── sample.xml
│   │   │   └── sample.xml.bz2
│   │   ├── static_foo.txt
│   │   ├── tcpclient_test.py
│   │   ├── tcpserver_test.py
│   │   ├── template_test.py
│   │   ├── templates/
│   │   │   └── utf8.html
│   │   ├── test.crt
│   │   ├── test.key
│   │   ├── testing_test.py
│   │   ├── twisted_test.py
│   │   ├── util.py
│   │   ├── util_test.py
│   │   ├── web_test.py
│   │   ├── websocket_test.py
│   │   └── wsgi_test.py
│   ├── testing.py
│   ├── util.py
│   ├── web.py
│   ├── websocket.py
│   └── wsgi.py
└── tox.ini

================================================
FILE CONTENTS
================================================

================================================
FILE: .coveragerc
================================================
# Test coverage configuration.
# Usage:
#   pip install coverage
#   coverage erase  # clears previous data if any
#   coverage run -m tornado.test.runtests
#   coverage report  # prints to stdout
#   coverage html  # creates ./htmlcov/*.html including annotated source
[run]
branch = true
source = tornado
omit = 
    tornado/platform/*
    tornado/test/*
    */_auto2to3*

[report]
# Ignore missing source files, i.e. fake template-generated "files"
ignore_errors = true


================================================
FILE: .flake8
================================================
[flake8]
exclude = .git,.tox,__pycache__,.eggs,build
max-line-length = 100
ignore =
    # E265 block comment should start with '# '
    E265,
    # E266 too many leading '#' for block comment
    E266,
    # E402 module level import not at top of file
    E402,
    # E722 do not use bare except
    E722,
    # flake8 and black disagree about
    # W503 line break before binary operator
    # E203 whitespace before ':'
    # E701/E704 multiple statements on one line
    # https://black.readthedocs.io/en/latest/guides/using_black_with_other_tools.html#labels-why-pycodestyle-warnings
    W503,E203,E701,E704
doctests = true


================================================
FILE: .gitattributes
================================================
# Tests of static file handling assume unix-style line endings.
tornado/test/static/*.txt text eol=lf
tornado/test/static/dir/*.html text eol=lf
tornado/test/templates/*.html text eol=lf


================================================
FILE: .github/workflows/build.yml
================================================
# The "build" workflow produces wheels (and the sdist) for all python
# versions/platforms. Where possible (i.e. the build is not a cross-compile),
# the test suite is also run for the wheel (this test covers fewer
# configurations than the "test" workflow and tox.ini).
name: Build

on:
  push:
    branches:
      # Run on release branches. This gives us a chance to detect rot in this
      # configuration before pushing a tag (which we'd rather not have to undo).
      - "branch[0-9]*"
    tags:
      # The main purpose of this workflow is to build wheels for release tags.
      # It runs automatically on tags matching this pattern and pushes to pypi.
      - "v*"
  workflow_dispatch:
    # Allow this workflow to be run manually (pushing to testpypi instead of pypi)

permissions: {}

env:
  # [[[cog cog.outl(f"python-version: '3.{default_python_minor}'")]]]
  python-version: '3.13'
  # [[[end]]]

jobs:
  build_sdist:
    name: Build sdist
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@v4
        with:
          persist-credentials: false
      - uses: actions/setup-python@v5
        name: Install Python
        with:
          python-version: ${{ env.python-version }}

      - name: Install dependencies
        run: python -m pip install setuptools
      - name: Check metadata
        run: "python setup.py check"
      - name: Build sdist
        run: "python setup.py sdist && ls -l dist"

      - uses: actions/upload-artifact@v4
        with:
          name: artifacts-sdist
          path: ./dist/tornado-*.tar.gz

  build_wheels:
    name: Build wheels on ${{ matrix.os }}${{ matrix.name_suffix || '' }}
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-24.04, ubuntu-24.04-arm, windows-2025, windows-11-arm, macos-15]
        arch: [auto]
        include:
          - os: ubuntu-24.04
            arch: "riscv64"
            name_suffix: "-riscv64"

    steps:
      - uses: actions/checkout@v4
        with:
          persist-credentials: false
      - uses: actions/setup-python@v5
        name: Install Python
        with:
          python-version: ${{ env.python-version }}

      - name: Set up QEMU
        if: matrix.arch != 'auto'
        uses: docker/setup-qemu-action@v3
        with:
          platforms: ${{ matrix.arch }}

      - name: Build wheels
        uses: pypa/cibuildwheel@v3.4.0
        env:
          CIBW_ARCHS: ${{ matrix.arch }}
          # Increase timeouts for emulated archs
          CIBW_ENVIRONMENT: ${{ matrix.arch != 'auto' && 'ASYNC_TEST_TIMEOUT=30 EMULATION=1' || '' }}

      - name: Audit ABI3 compliance
        # This may be moved into cibuildwheel itself in the future. See
        # https://github.com/pypa/cibuildwheel/issues/1342
        run: python -m pip install abi3audit && abi3audit --verbose --summary ./wheelhouse/*abi3*.whl

      - uses: actions/upload-artifact@v4
        with:
          name: artifacts-${{ matrix.os }}${{ matrix.name_suffix || '' }}
          path: ./wheelhouse/*.whl

  upload_pypi_test:
    name: Upload to PyPI (test)
    needs: [build_wheels, build_sdist]
    runs-on: ubuntu-24.04
    if: github.repository == 'tornadoweb/tornado' && github.event_name == 'workflow_dispatch'
    permissions:
      # This permission is required for pypi's "trusted publisher" feature
      id-token: write
    steps:
      - uses: actions/download-artifact@v4
        with:
          pattern: artifacts-*
          path: dist
          merge-multiple: true

      - uses: pypa/gh-action-pypi-publish@release/v1
        with:
          repository-url: https://test.pypi.org/legacy/
          skip-existing: true

  upload_pypi:
    name: Upload to PyPI (prod)
    needs: [build_wheels, build_sdist]
    runs-on: ubuntu-24.04
    if: github.repository == 'tornadoweb/tornado' && github.event_name == 'push' && github.ref_type == 'tag' && startsWith(github.ref_name, 'v')
    permissions:
      # This permission is required for pypi's "trusted publisher" feature
      id-token: write
    steps:
      - uses: actions/download-artifact@v4
        with:
          pattern: artifacts-*
          path: dist
          merge-multiple: true

      - uses: pypa/gh-action-pypi-publish@release/v1


================================================
FILE: .github/workflows/test.yml
================================================
# The "test" workflow is run on every PR and runs tests across all
# supported python versions and a range of configurations
# specified in tox.ini. Also see the "build" workflow which is only
# run for release branches and covers platforms other than linux-amd64
# (Platform-specific issues are rare these days so we don't want to
# take that time on every build).

name: Test

on: pull_request

permissions: {}

jobs:
  # Before starting the full build matrix, run one test configuration
  # and the linter (the `black` linter is especially likely to catch
  # first-time contributors).
  test_quick:
    name: Run quick tests
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@v4
        with:
          persist-credentials: false
      - uses: actions/setup-python@v5
        name: Install Python
        with:
          # [[[cog cog.outl(f"python-version: '3.{default_python_minor}'")]]]
          python-version: '3.13'
          # [[[end]]]
      - name: Install tox
        run: python -m pip install tox -c requirements.txt

      - name: Run test suite
        # [[[cog cog.outl(f"run: python -m tox -e py3{default_python_minor},lint")]]]
        run: python -m tox -e py313,lint
        # [[[end]]]

  test_tox:
    name: Run full tests
    needs: test_quick
    runs-on: ubuntu-24.04
    strategy:
      matrix:
        include:
          # [[[cog
          #    configs  = []
          #    for minor in range(int(min_python_minor), int(max_python_minor) + 1):
          #      if minor == int(dev_python_minor):
          #          # For python versions in development, specify a range so we install
          #          # a final version if available, otherwise a prerelease.
          #          # The .0 is necessary here for unclear reasons.
          #          configs.append((f"3.{minor}.0-dev - 3.{minor}", f"py3{minor}"))
          #      else:
          #          configs.append((f"3.{minor}", f"py3{minor}-full"))
          #      if int(min_python_threaded_minor) <= minor <= int(max_python_threaded_minor):
          #          if minor == int(dev_python_minor):
          #              # The range trick above doesn't work for threaded builds, so we'll
          #              # just be stuck with last prerelease until we update dev_python_minor.
          #              configs.append((f"3.{minor}t-dev", f"py3{minor}"))
          #          else:
          #              configs.append((f"3.{minor}t", f"py3{minor}"))
          #    # Early versions of 3.10 and 3.11 had different deprecation
          #    # warnings in asyncio. Test with them too to make sure everything
          #    # works the same way.
          #    configs.append(("3.10.8", "py310-full"))
          #    configs.append(("3.11.0", "py311-full"))
          #    # Pypy is a lot slower due to jit warmup costs, so don't run the
          #    # "full" test config there.
          #    configs.append(("pypy-3.10", "pypy3"))
          #    # Docs python version must be synced with tox.ini
          #    configs.append((f"3.{default_python_minor}", "docs"))
          #    for version, tox_env in configs:
          #      cog.outl(f"  - python: '{version}'")
          #      cog.outl(f"    tox_env: {tox_env}")
          #    ]]]
          - python: '3.10'
            tox_env: py310-full
          - python: '3.11'
            tox_env: py311-full
          - python: '3.12'
            tox_env: py312-full
          - python: '3.13'
            tox_env: py313-full
          - python: '3.14'
            tox_env: py314
          - python: '3.14t-dev'
            tox_env: py314
          - python: '3.15-dev'
            tox_env: py315
          - python: '3.10.8'
            tox_env: py310-full
          - python: '3.11.0'
            tox_env: py311-full
          - python: 'pypy-3.10'
            tox_env: pypy3
          - python: '3.13'
            tox_env: docs
          # [[[end]]]

    steps:
      - uses: actions/checkout@v4
        with:
          persist-credentials: false
      - uses: actions/setup-python@v5
        name: Install Python
        with:
          python-version: ${{ matrix.python}}
      - name: Install apt packages
        run: sudo apt-get update && sudo apt-get install libcurl4-openssl-dev
      - name: Install tox
        run: python -m pip install tox -c requirements.txt

      - name: Run test suite
        run: python -m tox -e ${{ matrix.tox_env }}

  test_win:
    # Windows tests are fairly slow, so only run one configuration here.
    # We test on windows but not mac because even though mac is a more
    # fully-supported platform, it's similar enough to linux that we
    # don't generally need to test it separately. Windows is different
    # enough that we'll break it if we don't test it in CI.
    name: Run windows tests
    needs: test_quick
    runs-on: windows-2025
    steps:
      - uses: actions/checkout@v4
        with:
          persist-credentials: false
      - uses: actions/setup-python@v5
        name: Install Python
        with:
          # [[[cog cog.outl(f"python-version: '3.{default_python_minor}'")]]]
          python-version: '3.13'
          # [[[end]]]
      - name: Run test suite
        # TODO: figure out what's up with these log messages
        run: py -m tornado.test --fail-if-logs=false

  zizmor:
    name: Analyze action configs with zizmor
    runs-on: ubuntu-24.04
    needs: test_quick
    steps:
      - uses: actions/checkout@v4
        with:
          persist-credentials: false
      - uses: astral-sh/setup-uv@v6
        name: Install uv
      - name: Run zizmor
        run: uvx zizmor .github/workflows

  test_cibw:
    # cibuildwheel is the tool that we use for release builds in build.yml.
    # Run it in the every-PR workflow because it's slightly different from our
    # regular build and this gives us easier ways to test freethreading changes.
    #
    # Note that test_cibw and test_tox both take about a minute to run, but test_tox runs
    # more tests; test_cibw spends a lot of its time installing dependencies. Replacing
    # test_tox with test_cibw would entail either increasing test runtime or reducing
    # test coverage.
    name: Test with cibuildwheel
    runs-on: ubuntu-24.04
    needs: test_quick
    steps:
      - uses: actions/checkout@v4
        with:
          persist-credentials: false
      - name: Run cibuildwheel
        uses: pypa/cibuildwheel@v2.23
        env:
          # For speed, we only build one python version and one arch. We throw away the wheels
          # built here; the real build is defined in build.yml.
          CIBW_ARCHS: native
          # [[[cog cog.outl(f"CIBW_BUILD: cp3{default_python_minor}-manylinux*")]]]
          CIBW_BUILD: cp313-manylinux*
          # [[[end]]]


================================================
FILE: .github/zizmor.yml
================================================
rules:
  unpinned-uses:
    config:
      policies:
        # Allow trusted repositories to use ref-pinning instead of hash-pinning.
        #
        # Defaults, from 
        # https://github.com/woodruffw/zizmor/blob/7b4e76e94be2f4d7b455664ba5252b2b4458b91d/src/audit/unpinned_uses.rs#L172-L193
        actions/*: ref-pin
        github/*: ref-pin
        dependabot/*: ref-pin
        # Additional trusted repositories
        pypa/*: ref-pin
        astral-sh/setup-uv: ref-pin
        docker/setup-qemu-action: ref-pin


================================================
FILE: .gitignore
================================================
*.pyc
*.pyo
*.so
*.class
*~
build/
/dist/
MANIFEST
/tornado.egg-info/
.tox/
.vagrant
/.coverage
/htmlcov/
/env/
# Used in demo apps
secrets.cfg
.mypy_cache/


================================================
FILE: .readthedocs.yaml
================================================
version: 2

build:
  os: ubuntu-22.04
  tools:
    python: "3.11"

sphinx:
  configuration: docs/conf.py

formats:
  - pdf
  - epub

python:
  install:
    - requirements: requirements.txt


================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to Tornado

## The basics

* We use `black` as code formatter and recommend configuring your editor to run this automatically
  (using the version specified in `requirements.txt`). Commits that are not properly formatted
  by `black` will be rejected in CI.
* Before committing, it is recommended to run `tox -e lint,docs,py3`. This will verify that the
  code is formatted correctly, type checking with `mypy` passes, the `sphinx` build for docs has
  no errors, and the main test suite passes with the current version of python.
* Nearly all code changes should have new or updated tests covering the changed behavior.
  Red/green TDD is encouraged.

## Testing

* We use `tox` as a test runner to run tests in various configurations with the correct
  dependencies. `tox -e py3` runs most of the tests, while `tox -e py3-full` can be used
  to run a more extensive version of the test suite which as extra dependencies. The
  `-full` configurations are necessary when working on certain modules, including
  `curl_httpclient.py`, `twisted.py`, or `pycares.py`.
* The fastest way to run the tests is to bypass `tox` and run `python3 -m tornado.test`.
  To run a subset of tests, add a module, class, or method name to the command line:
  `python3 -m tornado.test.httputil_test`.
* Tests can also be run with the standard library's `unittest` package CLI. This is useful
  for integration with some editors.
* Tornado does not use `pytest`. Some effort has been made to make the tests work with 
  the `pytest` runner, but this is not maintained.

## Documentation

We use Sphinx with the `autodoc` extension to build our docs. To build the docs run
`tox -e docs` and find the output in `./.tox/docs/tmp/html/index.html`

## AI policy

Tornado has a neutral stance towards AI-generated code. All pull requests, whether human
or machine-generated, are subject to strict code review standards. However, PRs that appear
to be AI-generated *and* contain clear flaws (such as failing CI) may be closed without
detailed review. 

================================================
FILE: LICENSE
================================================

                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright [yyyy] [name of copyright owner]

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.


================================================
FILE: MANIFEST.in
================================================
recursive-include docs *
prune docs/build
include tornado/py.typed
include tornado/speedups.c
include tornado/test/README
include tornado/test/csv_translations/fr_FR.csv
include tornado/test/gettext_translations/fr_FR/LC_MESSAGES/tornado_test.mo
include tornado/test/gettext_translations/fr_FR/LC_MESSAGES/tornado_test.po
include tornado/test/options_test.cfg
include tornado/test/static/robots.txt
include tornado/test/static/sample.xml
include tornado/test/static/sample.xml.gz
include tornado/test/static/sample.xml.bz2
include tornado/test/static/dir/index.html
include tornado/test/static_foo.txt
include tornado/test/templates/utf8.html
include tornado/test/test.crt
include tornado/test/test.key
include LICENSE
include README.rst
include requirements.in
include requirements.txt
include runtests.sh
include tox.ini


================================================
FILE: README.rst
================================================
Tornado Web Server
==================

.. image:: https://badges.gitter.im/Join%20Chat.svg
   :alt: Join the chat at https://gitter.im/tornadoweb/tornado
   :target: https://gitter.im/tornadoweb/tornado?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge

`Tornado <http://www.tornadoweb.org>`_ is a Python web framework and
asynchronous networking library, originally developed at `FriendFeed
<http://friendfeed.com>`_.  By using non-blocking network I/O, Tornado
can scale to tens of thousands of open connections, making it ideal for
`long polling <http://en.wikipedia.org/wiki/Push_technology#Long_Polling>`_,
`WebSockets <http://en.wikipedia.org/wiki/WebSocket>`_, and other
applications that require a long-lived connection to each user.

Hello, world
------------

Here is a simple "Hello, world" example web app for Tornado:

.. code-block:: python

    import asyncio
    import tornado

    class MainHandler(tornado.web.RequestHandler):
        def get(self):
            self.write("Hello, world")

    def make_app():
        return tornado.web.Application([
            (r"/", MainHandler),
        ])

    async def main():
        app = make_app()
        app.listen(8888)
        await asyncio.Event().wait()

    if __name__ == "__main__":
        asyncio.run(main())

This example does not use any of Tornado's asynchronous features; for
that see this `simple chat room
<https://github.com/tornadoweb/tornado/tree/stable/demos/chat>`_.

Documentation
-------------

Documentation and links to additional resources are available at
https://www.tornadoweb.org


================================================
FILE: SECURITY.md
================================================
# Security Policy

## Supported Versions

In general, due to limited maintainer bandwidth, only the latest version of
Tornado is supported with patch releases. Exceptions may be made depending
on the severity of the bug and the feasibility of backporting a fix to
older releases. 

## Reporting a Vulnerability

Tornado uses GitHub's security advisory functionality for private vulnerability
reports. To make a private report, use the "Report a vulnerability" button on
https://github.com/tornadoweb/tornado/security/advisories


================================================
FILE: codecov.yml
================================================
comment: off
coverage:
  status: off


================================================
FILE: demos/README.rst
================================================
Tornado Demo Apps
-----------------

This directory contains several example apps that illustrate the usage of
various Tornado features. If you're not sure where to start, try the ``chat``,
``blog``, or ``websocket`` demos.

Web Applications
~~~~~~~~~~~~~~~~

- ``blog``: A simple database-backed blogging platform, including
  HTML templates and authentication.
- ``chat``: A chat room demonstrating live updates via long polling.
- ``websocket``: Similar to ``chat`` but with WebSockets instead of
  long polling.
- ``helloworld``: The simplest possible Tornado web page.

Feature demos
~~~~~~~~~~~~~

- ``facebook``: Authentication with the Facebook Graph API.
- ``file_upload``: Client and server support for streaming HTTP request 
  payloads.
- ``tcpecho``: Using the lower-level ``IOStream`` interfaces for non-HTTP
  networking.
- ``webspider``: Concurrent usage of ``AsyncHTTPClient``, using queues and
  semaphores.



================================================
FILE: demos/blog/Dockerfile
================================================
FROM python:3.7

EXPOSE 8888

RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

COPY requirements.txt /usr/src/app/
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

ENTRYPOINT ["python3", "blog.py"]


================================================
FILE: demos/blog/README
================================================
Running the Tornado Blog example app
====================================

This demo is a simple blogging engine that uses a database to store posts.
You must have PostgreSQL or CockroachDB installed to run this demo.

If you have `docker` and `docker-compose` installed, the demo and all
its prerequisites can be installed with `docker-compose up`.

1. Install a database if needed

   Consult the documentation at either https://www.postgresql.org or
   https://www.cockroachlabs.com to install one of these databases for
   your platform.

2. Install Python prerequisites

   This demo requires Python 3.6 or newer, and the packages listed in
   requirements.txt. Install them with `pip -r requirements.txt`

3. Create a database and user for the blog.

   Connect to the database with `psql -U postgres` (for PostgreSQL) or
   `cockroach sql` (for CockroachDB).

   Create a database and user, and grant permissions:

   CREATE DATABASE blog;
   CREATE USER blog WITH PASSWORD 'blog';
   GRANT ALL ON DATABASE blog TO blog;

   (If using CockroachDB in insecure mode, omit the `WITH PASSWORD 'blog'`)

4. Create the tables in your new database (optional):

   The blog application will create its tables automatically when starting up.
   It's also possible to create them separately.

   You can use the provided schema.sql file by running this command for PostgreSQL:

   psql -U blog -d blog < schema.sql

   Or this one for CockcroachDB:

   cockroach sql -u blog -d blog < schema.sql

   You can run the above command again later if you want to delete the
   contents of the blog and start over after testing.

5. Run the blog example

   For PostgreSQL, you can just run
   ./blog.py

   For CockroachDB, run
   ./blog.py --db_port=26257

   If you've changed anything from the defaults, use the other `--db_*` flags.

6. Visit your new blog

   Open http://localhost:8888/ in your web browser.

   Currently the first user to connect will automatically be given the
   ability to create and edit posts.

   Once you've created one blog post, subsequent users will not be
   prompted to sign in.


================================================
FILE: demos/blog/blog.py
================================================
#!/usr/bin/env python3
#
# Copyright 2009 Facebook
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

import aiopg
import asyncio
import bcrypt
import markdown
import os.path
import psycopg2
import re
import tornado
import unicodedata

from tornado.options import define, options

define("port", default=8888, help="run on the given port", type=int)
define("db_host", default="127.0.0.1", help="blog database host")
define("db_port", default=5432, help="blog database port")
define("db_database", default="blog", help="blog database name")
define("db_user", default="blog", help="blog database user")
define("db_password", default="blog", help="blog database password")


class NoResultError(Exception):
    pass


async def maybe_create_tables(db):
    try:
        with await db.cursor() as cur:
            await cur.execute("SELECT COUNT(*) FROM entries LIMIT 1")
            await cur.fetchone()
    except psycopg2.ProgrammingError:
        with open("schema.sql") as f:
            schema = f.read()
        with await db.cursor() as cur:
            await cur.execute(schema)


class Application(tornado.web.Application):
    def __init__(self, db):
        self.db = db
        handlers = [
            (r"/", HomeHandler),
            (r"/archive", ArchiveHandler),
            (r"/feed", FeedHandler),
            (r"/entry/([^/]+)", EntryHandler),
            (r"/compose", ComposeHandler),
            (r"/auth/create", AuthCreateHandler),
            (r"/auth/login", AuthLoginHandler),
            (r"/auth/logout", AuthLogoutHandler),
        ]
        settings = dict(
            blog_title="Tornado Blog",
            template_path=os.path.join(os.path.dirname(__file__), "templates"),
            static_path=os.path.join(os.path.dirname(__file__), "static"),
            ui_modules={"Entry": EntryModule},
            xsrf_cookies=True,
            cookie_secret="__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__",
            login_url="/auth/login",
            debug=True,
        )
        super().__init__(handlers, **settings)


class BaseHandler(tornado.web.RequestHandler):
    def row_to_obj(self, row, cur):
        """Convert a SQL row to an object supporting dict and attribute access."""
        obj = tornado.util.ObjectDict()
        for val, desc in zip(row, cur.description):
            obj[desc.name] = val
        return obj

    async def execute(self, stmt, *args):
        """Execute a SQL statement.

        Must be called with ``await self.execute(...)``
        """
        with await self.application.db.cursor() as cur:
            await cur.execute(stmt, args)

    async def query(self, stmt, *args):
        """Query for a list of results.

        Typical usage::

            results = await self.query(...)

        Or::

            for row in await self.query(...)
        """
        with await self.application.db.cursor() as cur:
            await cur.execute(stmt, args)
            return [self.row_to_obj(row, cur) for row in await cur.fetchall()]

    async def queryone(self, stmt, *args):
        """Query for exactly one result.

        Raises NoResultError if there are no results, or ValueError if
        there are more than one.
        """
        results = await self.query(stmt, *args)
        if len(results) == 0:
            raise NoResultError()
        elif len(results) > 1:
            raise ValueError("Expected 1 result, got %d" % len(results))
        return results[0]

    async def prepare(self):
        # get_current_user cannot be a coroutine, so set
        # self.current_user in prepare instead.
        user_id = self.get_signed_cookie("blogdemo_user")
        if user_id:
            self.current_user = await self.queryone(
                "SELECT * FROM authors WHERE id = %s", int(user_id)
            )

    async def any_author_exists(self):
        return bool(await self.query("SELECT * FROM authors LIMIT 1"))

    def redirect_to_next(self):
        next = self.get_argument("next", "/")
        if next.startswith("//") or not next.startswith("/"):
            # Absolute URLs are not allowed because this would be an open redirect
            # vulnerability (https://cwe.mitre.org/data/definitions/601.html).
            raise tornado.web.HTTPError(400)
        self.redirect(next)


class HomeHandler(BaseHandler):
    async def get(self):
        entries = await self.query(
            "SELECT * FROM entries ORDER BY published DESC LIMIT 5"
        )
        if not entries:
            self.redirect("/compose")
            return
        self.render("home.html", entries=entries)


class EntryHandler(BaseHandler):
    async def get(self, slug):
        entry = await self.queryone("SELECT * FROM entries WHERE slug = %s", slug)
        if not entry:
            raise tornado.web.HTTPError(404)
        self.render("entry.html", entry=entry)


class ArchiveHandler(BaseHandler):
    async def get(self):
        entries = await self.query("SELECT * FROM entries ORDER BY published DESC")
        self.render("archive.html", entries=entries)


class FeedHandler(BaseHandler):
    async def get(self):
        entries = await self.query(
            "SELECT * FROM entries ORDER BY published DESC LIMIT 10"
        )
        self.set_header("Content-Type", "application/atom+xml")
        self.render("feed.xml", entries=entries)


class ComposeHandler(BaseHandler):
    @tornado.web.authenticated
    async def get(self):
        id = self.get_argument("id", None)
        entry = None
        if id:
            entry = await self.queryone("SELECT * FROM entries WHERE id = %s", int(id))
        self.render("compose.html", entry=entry)

    @tornado.web.authenticated
    async def post(self):
        id = self.get_argument("id", None)
        title = self.get_argument("title")
        text = self.get_argument("markdown")
        html = markdown.markdown(text)
        if id:
            try:
                entry = await self.queryone(
                    "SELECT * FROM entries WHERE id = %s", int(id)
                )
            except NoResultError:
                raise tornado.web.HTTPError(404)
            slug = entry.slug
            await self.execute(
                "UPDATE entries SET title = %s, markdown = %s, html = %s "
                "WHERE id = %s",
                title,
                text,
                html,
                int(id),
            )
        else:
            slug = unicodedata.normalize("NFKD", title)
            slug = re.sub(r"[^\w]+", " ", slug)
            slug = "-".join(slug.lower().strip().split())
            slug = slug.encode("ascii", "ignore").decode("ascii")
            if not slug:
                slug = "entry"
            while True:
                e = await self.query("SELECT * FROM entries WHERE slug = %s", slug)
                if not e:
                    break
                slug += "-2"
            await self.execute(
                "INSERT INTO entries (author_id,title,slug,markdown,html,published,updated)"
                "VALUES (%s,%s,%s,%s,%s,CURRENT_TIMESTAMP,CURRENT_TIMESTAMP)",
                self.current_user.id,
                title,
                slug,
                text,
                html,
            )
        self.redirect("/entry/" + slug)


class AuthCreateHandler(BaseHandler):
    def get(self):
        self.render("create_author.html")

    async def post(self):
        if await self.any_author_exists():
            raise tornado.web.HTTPError(400, "author already created")
        hashed_password = await tornado.ioloop.IOLoop.current().run_in_executor(
            None,
            bcrypt.hashpw,
            tornado.escape.utf8(self.get_argument("password")),
            bcrypt.gensalt(),
        )
        author = await self.queryone(
            "INSERT INTO authors (email, name, hashed_password) "
            "VALUES (%s, %s, %s) RETURNING id",
            self.get_argument("email"),
            self.get_argument("name"),
            tornado.escape.to_unicode(hashed_password),
        )
        self.set_signed_cookie("blogdemo_user", str(author.id))
        self.redirect_to_next()


class AuthLoginHandler(BaseHandler):
    async def get(self):
        # If there are no authors, redirect to the account creation page.
        if not await self.any_author_exists():
            self.redirect("/auth/create")
        else:
            self.render("login.html", error=None)

    async def post(self):
        try:
            author = await self.queryone(
                "SELECT * FROM authors WHERE email = %s", self.get_argument("email")
            )
        except NoResultError:
            self.render("login.html", error="email not found")
            return
        password_equal = await tornado.ioloop.IOLoop.current().run_in_executor(
            None,
            bcrypt.checkpw,
            tornado.escape.utf8(self.get_argument("password")),
            tornado.escape.utf8(author.hashed_password),
        )
        if password_equal:
            self.set_signed_cookie("blogdemo_user", str(author.id))
            self.redirect_to_next()
        else:
            self.render("login.html", error="incorrect password")


class AuthLogoutHandler(BaseHandler):
    def get(self):
        self.clear_cookie("blogdemo_user")
        self.redirect_to_next()


class EntryModule(tornado.web.UIModule):
    def render(self, entry):
        return self.render_string("modules/entry.html", entry=entry)


async def main():
    tornado.options.parse_command_line()

    # Create the global connection pool.
    async with aiopg.create_pool(
        host=options.db_host,
        port=options.db_port,
        user=options.db_user,
        password=options.db_password,
        dbname=options.db_database,
    ) as db:
        await maybe_create_tables(db)
        app = Application(db)
        app.listen(options.port)

        # In this demo the server will simply run until interrupted
        # with Ctrl-C, but if you want to shut down more gracefully,
        # call shutdown_event.set().
        shutdown_event = tornado.locks.Event()
        await shutdown_event.wait()


if __name__ == "__main__":
    asyncio.run(main())


================================================
FILE: demos/blog/docker-compose.yml
================================================
postgres:
  image: postgres:10.3
  environment:
    POSTGRES_USER: blog
    POSTGRES_PASSWORD: blog
    POSTGRES_DB: blog
  ports:
    - "3306"
blog:
  build: .
  links:
    - postgres
  ports:
    - "8888:8888"
  command: --db_host=postgres


================================================
FILE: demos/blog/requirements.txt
================================================
aiopg
bcrypt
markdown
psycopg2
tornado


================================================
FILE: demos/blog/schema.sql
================================================
-- Copyright 2009 FriendFeed
--
-- Licensed under the Apache License, Version 2.0 (the "License"); you may
-- not use this file except in compliance with the License. You may obtain
-- a copy of the License at
--
--     http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-- WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-- License for the specific language governing permissions and limitations
-- under the License.

-- To create the database:
--   CREATE DATABASE blog;
--   CREATE USER blog WITH PASSWORD 'blog';
--   GRANT ALL ON DATABASE blog TO blog;
--
-- To reload the tables:
--   psql -U blog -d blog < schema.sql

DROP TABLE IF EXISTS authors;
CREATE TABLE authors (
    id SERIAL PRIMARY KEY,
    email VARCHAR(100) NOT NULL UNIQUE,
    name VARCHAR(100) NOT NULL,
    hashed_password VARCHAR(100) NOT NULL
);

DROP TABLE IF EXISTS entries;
CREATE TABLE entries (
    id SERIAL PRIMARY KEY,
    author_id INT NOT NULL REFERENCES authors(id),
    slug VARCHAR(100) NOT NULL UNIQUE,
    title VARCHAR(512) NOT NULL,
    markdown TEXT NOT NULL,
    html TEXT NOT NULL,
    published TIMESTAMP NOT NULL,
    updated TIMESTAMP NOT NULL
);

CREATE INDEX ON entries (published);


================================================
FILE: demos/blog/static/blog.css
================================================
/*
 * Copyright 2009 Facebook
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License. You may obtain
 * a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */

body {
  background: white;
  color: black;
  margin: 15px;
  margin-top: 0;
}

body,
input,
textarea {
  font-family: Georgia, serif;
  font-size: 12pt;
}

table {
  border-collapse: collapse;
  border: 0;
}

td {
  border: 0;
  padding: 0;
}

h1,
h2,
h3,
h4 {
  font-family: "Helvetica Nue", Helvetica, Arial, sans-serif;
  margin: 0;
}

h1 {
  font-size: 20pt;
}

pre,
code {
  font-family: monospace;
  color: #060;
}

pre {
  margin-left: 1em;
  padding-left: 1em;
  border-left: 1px solid silver;
  line-height: 14pt;
}

a,
a code {
  color: #00c;
}

#body {
  max-width: 800px;
  margin: auto;
}

#header {
  background-color: #3b5998;
  padding: 5px;
  padding-left: 10px;
  padding-right: 10px;
  margin-bottom: 1em;
}

#header,
#header a {
  color: white;
}

#header h1 a {
  text-decoration: none;
}

#footer,
#content {
  margin-left: 10px;
  margin-right: 10px;
}

#footer {
  margin-top: 3em;
}

.entry h1 a {
  color: black;
  text-decoration: none;
}

.entry {
  margin-bottom: 2em;
}

.entry .date {
  margin-top: 3px;
}

.entry p {
  margin: 0;
  margin-bottom: 1em;
}

.entry .body {
  margin-top: 1em;
  line-height: 16pt;
}

.compose td {
  vertical-align: middle;
  padding-bottom: 5px;
}

.compose td.field {
  padding-right: 10px;
}

.compose .title,
.compose .submit {
  font-family: "Helvetica Nue", Helvetica, Arial, sans-serif;
  font-weight: bold;
}

.compose .title {
  font-size: 20pt;
}

.compose .title,
.compose .markdown {
  width: 100%;
}

.compose .markdown {
  height: 500px;
  line-height: 16pt;
}


================================================
FILE: demos/blog/templates/archive.html
================================================
{% extends "base.html" %}

{% block head %}
  <style type="text/css">
    ul.archive {
      list-style-type: none;
      margin: 0;
      padding: 0;
    }

    ul.archive li {
      margin-bottom: 1em;
    }

    ul.archive .title {
      font-family: "Helvetica Nue", Helvetica, Arial, sans-serif;
      font-size: 14pt;
    }
  </style>
{% end %}

{% block body %}
  <ul class="archive">
    {% for entry in entries %}
      <li>
        <div class="title"><a href="/entry/{{ entry.slug }}">{{ entry.title }}</a></div>
        <div class="date">{{ locale.format_date(entry.published, full_format=True, shorter=True) }}</div>
      </li>
    {% end %}
  </ul>
{% end %}


================================================
FILE: demos/blog/templates/base.html
================================================
<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <title>{{ escape(handler.settings["blog_title"]) }}</title>
  <link rel="stylesheet" href="{{ static_url(" blog.css") }}" type="text/css">
  <link rel="alternate" href="/feed" type="application/atom+xml" title="{{ escape(handler.settings[" blog_title"]) }}">
  {% block head %}{% end %}
</head>

<body>
  <div id="body">
    <div id="header">
      <div style="float:right">
        {% if current_user %}
        <a href="/compose">{{ _("New post") }}</a> -
        <a href="/auth/logout?next={{ url_escape(request.path) }}">{{ _("Sign out") }}</a>
        {% else %}
        {% raw _('<a href="%(url)s">Sign in</a> to compose/edit') % {"url": "/auth/login?next=" +
        url_escape(request.path)} %}
        {% end %}
      </div>
      <h1><a href="/">{{ escape(handler.settings["blog_title"]) }}</a></h1>
    </div>
    <div id="content">{% block body %}{% end %}</div>
  </div>
  {% block bottom %}{% end %}
</body>

</html>

================================================
FILE: demos/blog/templates/compose.html
================================================
{% extends "base.html" %}

{% block body %}
  <form action="{{ request.path }}" method="post" class="compose">
    <div style="margin-bottom:5px"><input name="title" type="text" class="title" value="{{ entry.title if entry else "" }}"/></div>
    <div style="margin-bottom:5px"><textarea name="markdown" rows="30" cols="40" class="markdown">{{ entry.markdown if entry else "" }}</textarea></div>
    <div>
      <div style="float:right"><a href="http://daringfireball.net/projects/markdown/syntax">{{ _("Syntax documentation") }}</a></div>
      <input type="submit" value="{{ _("Save changes") if entry else _("Publish post") }}" class="submit"/>
      &nbsp;<a href="{{ "/entry/" + entry.slug if entry else "/" }}">{{ _("Cancel") }}</a>
    </div>
    {% if entry %}
      <input type="hidden" name="id" value="{{ entry.id }}"/>
    {% end %}
    {% module xsrf_form_html() %}
  </form>
{% end %}

{% block bottom %}
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js" type="text/javascript"></script>
  <script type="text/javascript">
  //<![CDATA[

    $(function() {
      $("input[name=title]").select();
      $("form.compose").submit(function() {
          var required = ["title", "markdown"];
          var form = $(this).get(0);
          for (var i = 0; i < required.length; i++) {
              if (!form[required[i]].value) {
                  $(form[required[i]]).select();
                  return false;
              }
          }
          return true;
      });
    });

  //]]>
  </script>
{% end %}


================================================
FILE: demos/blog/templates/create_author.html
================================================
{% extends "base.html" %}

{% block body %}
<form action="/auth/create" method="POST">
  Email: <input name="email" type="text"><br>
  Name: <input name="name" type="text"><br>
  Password: <input name="password" type="password"><br>
  {% module xsrf_form_html() %}
  <input type="submit">
</form>
{% end %}


================================================
FILE: demos/blog/templates/entry.html
================================================
{% extends "base.html" %}

{% block body %}
  {% module Entry(entry) %}
{% end %}


================================================
FILE: demos/blog/templates/feed.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  {% set date_format = "%Y-%m-%dT%H:%M:%SZ" %}
  <title>{{ handler.settings["blog_title"] }}</title>
  {% if len(entries) > 0 %}
    <updated>{{ max(e.updated for e in entries).strftime(date_format) }}</updated>
  {% else %}
    <updated>{{ datetime.datetime.now(datetime.timezone.utc).strftime(date_format) }}</updated>
  {% end %}
  <id>http://{{ request.host }}/</id>
  <link rel="alternate" href="http://{{ request.host }}/" title="{{ handler.settings["blog_title"] }}" type="text/html"/>
  <link rel="self" href="{{ request.full_url() }}" title="{{ handler.settings["blog_title"] }}" type="application/atom+xml"/>
  <author><name>{{ handler.settings["blog_title"] }}</name></author>
  {% for entry in entries %}
    <entry>
      <id>http://{{ request.host }}/entry/{{ entry.slug }}</id>
      <title type="text">{{ entry.title }}</title>
      <link href="http://{{ request.host }}/entry/{{ entry.slug }}" rel="alternate" type="text/html"/>
      <updated>{{ entry.updated.strftime(date_format) }}</updated>
      <published>{{ entry.published.strftime(date_format) }}</published>
      <content type="xhtml" xml:base="http://{{ request.host }}/">
        <div xmlns="http://www.w3.org/1999/xhtml">{% raw entry.html %}</div>
      </content>
    </entry>
  {% end %}
</feed>


================================================
FILE: demos/blog/templates/home.html
================================================
{% extends "base.html" %}

{% block body %}
  {% for entry in entries %}
    {% module Entry(entry) %}
  {% end %}
  <div><a href="/archive">{{ _("Archive") }}</a></div>
{% end %}


================================================
FILE: demos/blog/templates/login.html
================================================
{% extends "base.html" %}

{% block body %}
{% if error %}
<span style="color: red">Error: {{ error }}</span><p>
{% end %}

<form action="/auth/login" method="POST">
  Email: <input name="email" type="text"><br>
  Password: <input name="password" type="password"><br>
  {% module xsrf_form_html() %}
  <input type="submit">
</form>
{% end %}


================================================
FILE: demos/blog/templates/modules/entry.html
================================================
<div class="entry">
  <h1><a href="/entry/{{ entry.slug }}">{{ entry.title }}</a></h1>
  <div class="date">{{ locale.format_date(entry.published, full_format=True, shorter=True) }}</div>
  <div class="body">{% raw entry.html %}</div>
  {% if current_user %}
    <div class="admin"><a href="/compose?id={{ entry.id }}">{{ _("Edit this post") }}</a></div>
  {% end %}
</div>


================================================
FILE: demos/chat/chatdemo.py
================================================
#!/usr/bin/env python3
#
# Copyright 2009 Facebook
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

import asyncio
import tornado
import os.path
import uuid

from tornado.options import define, options, parse_command_line

define("port", default=8888, help="run on the given port", type=int)
define("debug", default=True, help="run in debug mode")


class MessageBuffer:
    def __init__(self):
        # cond is notified whenever the message cache is updated
        self.cond = tornado.locks.Condition()
        self.cache = []
        self.cache_size = 200

    def get_messages_since(self, cursor):
        """Returns a list of messages newer than the given cursor.

        ``cursor`` should be the ``id`` of the last message received.
        """
        results = []
        for msg in reversed(self.cache):
            if msg["id"] == cursor:
                break
            results.append(msg)
        results.reverse()
        return results

    def add_message(self, message):
        self.cache.append(message)
        if len(self.cache) > self.cache_size:
            self.cache = self.cache[-self.cache_size :]
        self.cond.notify_all()


# Making this a non-singleton is left as an exercise for the reader.
global_message_buffer = MessageBuffer()


class MainHandler(tornado.web.RequestHandler):
    def get(self):
        self.render("index.html", messages=global_message_buffer.cache)


class MessageNewHandler(tornado.web.RequestHandler):
    """Post a new message to the chat room."""

    def post(self):
        message = {"id": str(uuid.uuid4()), "body": self.get_argument("body")}
        # render_string() returns a byte string, which is not supported
        # in json, so we must convert it to a character string.
        message["html"] = tornado.escape.to_unicode(
            self.render_string("message.html", message=message)
        )
        if next := self.get_argument("next", None):
            if next.startswith("//") or not next.startswith("/"):
                # Absolute URLs are not allowed because this would be an open redirect
                # vulnerability (https://cwe.mitre.org/data/definitions/601.html).
                raise tornado.web.HTTPError(400)
            self.redirect(next)
        else:
            self.write(message)
        global_message_buffer.add_message(message)


class MessageUpdatesHandler(tornado.web.RequestHandler):
    """Long-polling request for new messages.

    Waits until new messages are available before returning anything.
    """

    async def post(self):
        cursor = self.get_argument("cursor", None)
        messages = global_message_buffer.get_messages_since(cursor)
        while not messages:
            # Save the Future returned here so we can cancel it in
            # on_connection_close.
            self.wait_future = global_message_buffer.cond.wait()
            try:
                await self.wait_future
            except asyncio.CancelledError:
                return
            messages = global_message_buffer.get_messages_since(cursor)
        if self.request.connection.stream.closed():
            return
        self.write(dict(messages=messages))

    def on_connection_close(self):
        self.wait_future.cancel()


async def main():
    parse_command_line()
    app = tornado.web.Application(
        [
            (r"/", MainHandler),
            (r"/a/message/new", MessageNewHandler),
            (r"/a/message/updates", MessageUpdatesHandler),
        ],
        cookie_secret="__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__",
        template_path=os.path.join(os.path.dirname(__file__), "templates"),
        static_path=os.path.join(os.path.dirname(__file__), "static"),
        xsrf_cookies=True,
        debug=options.debug,
    )
    app.listen(options.port)
    await asyncio.Event().wait()


if __name__ == "__main__":
    asyncio.run(main())


================================================
FILE: demos/chat/static/chat.css
================================================
/*
 * Copyright 2009 FriendFeed
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License. You may obtain
 * a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */

body {
  background: white;
  margin: 10px;
}

body,
input {
  font-family: sans-serif;
  font-size: 10pt;
  color: black;
}

table {
  border-collapse: collapse;
  border: 0;
}

td {
  border: 0;
  padding: 0;
}

#body {
  position: absolute;
  bottom: 10px;
  left: 10px;
}

#input {
  margin-top: 0.5em;
}

#inbox .message {
  padding-top: 0.25em;
}

#nav {
  float: right;
  z-index: 99;
}


================================================
FILE: demos/chat/static/chat.js
================================================
// Copyright 2009 FriendFeed
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.

$(document).ready(function() {
    if (!window.console) window.console = {};
    if (!window.console.log) window.console.log = function() {};

    $("#messageform").on("submit", function() {
        newMessage($(this));
        return false;
    });
    $("#messageform").on("keypress", function(e) {
        if (e.keyCode == 13) {
            newMessage($(this));
            return false;
        }
        return true;
    });
    $("#message").select();
    updater.poll();
});

function newMessage(form) {
    var message = form.formToDict();
    var disabled = form.find("input[type=submit]");
    disabled.disable();
    $.postJSON("/a/message/new", message, function(response) {
        updater.showMessage(response);
        if (message.id) {
            form.parent().remove();
        } else {
            form.find("input[type=text]").val("").select();
            disabled.enable();
        }
    });
}

function getCookie(name) {
    var r = document.cookie.match("\\b" + name + "=([^;]*)\\b");
    return r ? r[1] : undefined;
}

jQuery.postJSON = function(url, args, callback) {
    args._xsrf = getCookie("_xsrf");
    $.ajax({url: url, data: $.param(args), dataType: "text", type: "POST",
            success: function(response) {
        if (callback) callback(eval("(" + response + ")"));
    }, error: function(response) {
        console.log("ERROR:", response);
    }});
};

jQuery.fn.formToDict = function() {
    var fields = this.serializeArray();
    var json = {};
    for (var i = 0; i < fields.length; i++) {
        json[fields[i].name] = fields[i].value;
    }
    if (json.next) delete json.next;
    return json;
};

jQuery.fn.disable = function() {
    this.enable(false);
    return this;
};

jQuery.fn.enable = function(opt_enable) {
    if (arguments.length && !opt_enable) {
        this.attr("disabled", "disabled");
    } else {
        this.removeAttr("disabled");
    }
    return this;
};

var updater = {
    errorSleepTime: 500,
    cursor: null,

    poll: function() {
        var args = {"_xsrf": getCookie("_xsrf")};
        if (updater.cursor) args.cursor = updater.cursor;
        $.ajax({url: "/a/message/updates", type: "POST", dataType: "text",
                data: $.param(args), success: updater.onSuccess,
                error: updater.onError});
    },

    onSuccess: function(response) {
        try {
            updater.newMessages(eval("(" + response + ")"));
        } catch (e) {
            updater.onError();
            return;
        }
        updater.errorSleepTime = 500;
        window.setTimeout(updater.poll, 0);
    },

    onError: function(response) {
        updater.errorSleepTime *= 2;
        console.log("Poll error; sleeping for", updater.errorSleepTime, "ms");
        window.setTimeout(updater.poll, updater.errorSleepTime);
    },

    newMessages: function(response) {
        if (!response.messages) return;
        var messages = response.messages;
        updater.cursor = messages[messages.length - 1].id;
        console.log(messages.length, "new messages, cursor:", updater.cursor);
        for (var i = 0; i < messages.length; i++) {
            updater.showMessage(messages[i]);
        }
    },

    showMessage: function(message) {
        var existing = $("#m" + message.id);
        if (existing.length > 0) return;
        var node = $(message.html);
        node.hide();
        $("#inbox").append(node);
        node.slideDown();
    }
};


================================================
FILE: demos/chat/templates/index.html
================================================
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Tornado Chat Demo</title>
    <link rel="stylesheet" href="{{ static_url("chat.css") }}" type="text/css">
  </head>
  <body>
    <div id="body">
      <div id="inbox">
        {% for message in messages %}
          {% module Template("message.html", message=message) %}
        {% end %}
      </div>
      <div id="input">
        <form action="/a/message/new" method="post" id="messageform">
          <table>
            <tr>
              <td><input type="text" name="body" id="message" style="width:500px"></td>
              <td style="padding-left:5px">
                <input type="submit" value="{{ _("Post") }}">
                <input type="hidden" name="next" value="{{ request.path }}">
                {% module xsrf_form_html() %}
              </td>
            </tr>
          </table>
        </form>
      </div>
    </div>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js" type="text/javascript"></script>
    <script src="{{ static_url("chat.js") }}" type="text/javascript"></script>
  </body>
</html>


================================================
FILE: demos/chat/templates/message.html
================================================
<div class="message" id="m{{ message["id"] }}">{% module linkify(message["body"]) %}</div>


================================================
FILE: demos/facebook/README
================================================
Running the Tornado Facebook example
====================================

To run this example, you must register a Facebook application with a
Connect URL set to the domain the this demo will be running on
(i.e. http://localhost:8888/ by default).  The API key and secret
for this application must be passed on the command line:

    python facebook.py --facebook_api_key=ABC --facebook_secret=XYZ


================================================
FILE: demos/facebook/facebook.py
================================================
#!/usr/bin/env python3
#
# Copyright 2009 Facebook
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

import asyncio
import os.path
import tornado

from tornado.options import define, options

define("port", default=8888, help="run on the given port", type=int)
define("facebook_api_key", help="your Facebook application API key", type=str)
define("facebook_secret", help="your Facebook application secret", type=str)


class Application(tornado.web.Application):
    def __init__(self):
        handlers = [
            (r"/", MainHandler),
            (r"/auth/login", AuthLoginHandler),
            (r"/auth/logout", AuthLogoutHandler),
        ]
        settings = dict(
            cookie_secret="__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__",
            login_url="/auth/login",
            template_path=os.path.join(os.path.dirname(__file__), "templates"),
            static_path=os.path.join(os.path.dirname(__file__), "static"),
            xsrf_cookies=True,
            facebook_api_key=options.facebook_api_key,
            facebook_secret=options.facebook_secret,
            ui_modules={"Post": PostModule},
            debug=True,
            autoescape=None,
        )
        tornado.web.Application.__init__(self, handlers, **settings)


class BaseHandler(tornado.web.RequestHandler):
    def get_current_user(self):
        user_json = self.get_signed_cookie("fbdemo_user")
        if not user_json:
            return None
        return tornado.escape.json_decode(user_json)


class MainHandler(BaseHandler, tornado.auth.FacebookGraphMixin):
    @tornado.web.authenticated
    async def get(self):
        stream = await self.facebook_request(
            "/me/home", self._on_stream, access_token=self.current_user["access_token"]
        )
        if stream is None:
            # Session may have expired
            self.redirect("/auth/login")
            return
        self.render("stream.html", stream=stream)


class AuthLoginHandler(BaseHandler, tornado.auth.FacebookGraphMixin):
    async def get(self):
        my_url = self.request.protocol + "://" + self.request.host + "/auth/login"
        if self.get_argument("code", False):
            user = await self.get_authenticated_user(
                redirect_uri=my_url,
                client_id=self.settings["facebook_api_key"],
                client_secret=self.settings["facebook_secret"],
                code=self.get_argument("code"),
            )
            self.set_signed_cookie("fbdemo_user", tornado.escape.json_encode(user))
            self.redirect("/")
            return
        self.authorize_redirect(
            redirect_uri=my_url,
            client_id=self.settings["facebook_api_key"],
            extra_params={"scope": "user_posts"},
        )


class AuthLogoutHandler(BaseHandler, tornado.auth.FacebookGraphMixin):
    def get(self):
        self.clear_cookie("fbdemo_user")
        self.redirect("/")


class PostModule(tornado.web.UIModule):
    def render(self, post):
        return self.render_string("modules/post.html", post=post)


async def main():
    tornado.options.parse_command_line()
    if not (options.facebook_api_key and options.facebook_secret):
        print("--facebook_api_key and --facebook_secret must be set")
        return
    http_server = tornado.httpserver.HTTPServer(Application())
    http_server.listen(options.port)
    await asyncio.Event().wait()


if __name__ == "__main__":
    asyncio.run(main())


================================================
FILE: demos/facebook/static/facebook.css
================================================
/*
 * Copyright 2009 Facebook
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License. You may obtain
 * a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */

body {
  background: white;
  color: black;
  margin: 15px;
}

body,
input,
textarea {
  font-family: "Lucida Grande", Tahoma, Verdana, sans-serif;
  font-size: 10pt;
}

table {
  border-collapse: collapse;
  border: 0;
}

td {
  border: 0;
  padding: 0;
}

img {
  border: 0;
}

a {
  text-decoration: none;
  color: #3b5998;
}

a:hover {
  text-decoration: underline;
}

.post {
  border-bottom: 1px solid #eeeeee;
  min-height: 50px;
  padding-bottom: 10px;
  margin-top: 10px;
}

.post .picture {
  float: left;
}

.post .picture img {
  height: 50px;
  width: 50px;
}

.post .body {
  margin-left: 60px;
}

.post .media img {
  border: 1px solid #cccccc;
  padding: 3px;
}

.post .media:hover img {
  border: 1px solid #3b5998;
}

.post a.actor {
  font-weight: bold;
}

.post .meta {
  font-size: 11px;
}

.post a.permalink {
  color: #777777;
}

#body {
  max-width: 700px;
  margin: auto;
}


================================================
FILE: demos/facebook/static/facebook.js
================================================


================================================
FILE: demos/facebook/templates/modules/post.html
================================================
<div class="post">
  <div class="picture">
    {% set author_url="http://www.facebook.com/profile.php?id=" + escape(post["from"]["id"]) %}
    <a href="{{ author_url }}"><img src="//graph.facebook.com/{{ escape(post["from"]["id"]) }}/picture?type=square"/></a>
  </div>
  <div class="body">
    <a href="{{ author_url }}" class="actor">{{ escape(post["from"]["name"]) }}</a>
    {% if "message" in post %}
      <span class="message">{{ escape(post["message"]) }}</span>
    {% end %}
    <div class="meta">
      {% if "actions" in post %}
        <a href="{{ escape(post["actions"][0]["link"]) }}" class="permalink">{{ locale.format_date(datetime.datetime.strptime(post["created_time"], "%Y-%m-%dT%H:%M:%S+0000")) }}</a>
      {% end %}
    </div>
  </div>
</div>


================================================
FILE: demos/facebook/templates/stream.html
================================================
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Tornado Facebook Stream Demo</title>
    <link rel="stylesheet" href="{{ static_url("facebook.css") }}" type="text/css">
  </head>
  <body>
    <div id="body">
      <div style="float:right">
        <b>{{ escape(current_user["name"]) }}</b> -
        <a href="/auth/logout">{{ _("Sign out") }}</a>
      </div>
      <div style="margin-bottom:1em"><a href="/">{{ _("Refresh stream") }}</a></div>
      <div id="stream">
        {% for post in stream["data"] %}
          {{ modules.Post(post) }}
        {% end %}
      </div>
    </div>
  </body>
</html>


================================================
FILE: demos/file_upload/file_receiver.py
================================================
#!/usr/bin/env python

"""Usage: python file_receiver.py

Demonstrates a server that receives a multipart-form-encoded set of files in an
HTTP POST, or streams in the raw data of a single file in an HTTP PUT.

See file_uploader.py in this directory for code that uploads files in this format.
"""

import asyncio
import logging
from urllib.parse import unquote

import tornado
from tornado import options


class POSTHandler(tornado.web.RequestHandler):
    def post(self):
        for field_name, files in self.request.files.items():
            for info in files:
                filename, content_type = info["filename"], info["content_type"]
                body = info["body"]
                logging.info(
                    'POST "%s" "%s" %d bytes', filename, content_type, len(body)
                )

        self.write("OK")


@tornado.web.stream_request_body
class PUTHandler(tornado.web.RequestHandler):
    def initialize(self):
        self.bytes_read = 0

    def data_received(self, chunk):
        self.bytes_read += len(chunk)

    def put(self, filename):
        filename = unquote(filename)
        mtype = self.request.headers.get("Content-Type")
        logging.info('PUT "%s" "%s" %d bytes', filename, mtype, self.bytes_read)
        self.write("OK")


def make_app():
    return tornado.web.Application([(r"/post", POSTHandler), (r"/(.*)", PUTHandler)])


async def main():
    options.parse_command_line()
    app = make_app()
    app.listen(8888)
    await asyncio.Event().wait()


if __name__ == "__main__":
    asyncio.run(main())


================================================
FILE: demos/file_upload/file_uploader.py
================================================
#!/usr/bin/env python

"""Usage: python file_uploader.py [--put] file1.txt file2.png ...

Demonstrates uploading files to a server, without concurrency. It can either
POST a multipart-form-encoded request containing one or more files, or PUT a
single file without encoding.

See also file_receiver.py in this directory, a server that receives uploads.
"""

import asyncio
import mimetypes
import os
import sys
from functools import partial
from urllib.parse import quote
from uuid import uuid4

from tornado import httpclient
from tornado.options import define, options


# Using HTTP POST, upload one or more files in a single multipart-form-encoded
# request.
async def multipart_producer(boundary, filenames, write):
    boundary_bytes = boundary.encode()

    for filename in filenames:
        filename_bytes = filename.encode()
        mtype = mimetypes.guess_type(filename)[0] or "application/octet-stream"
        buf = (
            (b"--%s\r\n" % boundary_bytes)
            + (
                b'Content-Disposition: form-data; name="%s"; filename="%s"\r\n'
                % (filename_bytes, filename_bytes)
            )
            + (b"Content-Type: %s\r\n" % mtype.encode())
            + b"\r\n"
        )
        await write(buf)
        with open(filename, "rb") as f:
            while True:
                # 16k at a time.
                chunk = f.read(16 * 1024)
                if not chunk:
                    break
                await write(chunk)

        await write(b"\r\n")

    await write(b"--%s--\r\n" % (boundary_bytes,))


# Using HTTP PUT, upload one raw file. This is preferred for large files since
# the server can stream the data instead of buffering it entirely in memory.
async def post(filenames):
    client = httpclient.AsyncHTTPClient()
    boundary = uuid4().hex
    headers = {"Content-Type": "multipart/form-data; boundary=%s" % boundary}
    producer = partial(multipart_producer, boundary, filenames)
    response = await client.fetch(
        "http://localhost:8888/post",
        method="POST",
        headers=headers,
        body_producer=producer,
    )

    print(response)


async def raw_producer(filename, write):
    with open(filename, "rb") as f:
        while True:
            # 16K at a time.
            chunk = f.read(16 * 1024)
            if not chunk:
                # Complete.
                break

            await write(chunk)


async def put(filenames):
    client = httpclient.AsyncHTTPClient()
    for filename in filenames:
        mtype = mimetypes.guess_type(filename)[0] or "application/octet-stream"
        headers = {"Content-Type": mtype}
        producer = partial(raw_producer, filename)
        url_path = quote(os.path.basename(filename))
        response = await client.fetch(
            "http://localhost:8888/%s" % url_path,
            method="PUT",
            headers=headers,
            body_producer=producer,
        )
        print(response)


if __name__ == "__main__":
    define("put", type=bool, help="Use PUT instead of POST", group="file uploader")

    # Tornado configures logging from command line opts and returns remaining args.
    filenames = options.parse_command_line()
    if not filenames:
        print("Provide a list of filenames to upload.", file=sys.stderr)
        sys.exit(1)

    method = put if options.put else post
    asyncio.run(method(filenames))


================================================
FILE: demos/google_auth/.gitignore
================================================
main.cfg


================================================
FILE: demos/google_auth/main.py
================================================
"""Demo app for GoogleOAuth2Mixin

Recommended usage:
- Register an app with Google following the instructions at
  https://www.tornadoweb.org/en/stable/auth.html#tornado.auth.GoogleOAuth2Mixin
- Use "http://localhost:8888/auth/google" as the redirect URI.
- Create a file in this directory called main.cfg, containing two lines (python syntax):
    google_oauth_key="..."
    google_oauth_secret="..."
- Run this file with `python main.py --config_file=main.cfg`
- Visit "http://localhost:8888" in your browser.
"""

import asyncio
import json
import tornado
import urllib.parse

from tornado.options import define, options
from tornado.web import url

define("port", default=8888, help="run on the given port", type=int)
define("google_oauth_key", help="Google OAuth Key")
define("google_oauth_secret", help="Google OAuth Secret")
define(
    "config_file",
    help="tornado config file",
    callback=lambda path: tornado.options.parse_config_file(path, final=False),
)


class BaseHandler(tornado.web.RequestHandler):
    def get_current_user(self):
        user_cookie = self.get_signed_cookie("googledemo_user")
        if user_cookie:
            return json.loads(user_cookie)
        return None


class IndexHandler(BaseHandler, tornado.auth.GoogleOAuth2Mixin):
    @tornado.web.authenticated
    async def get(self):
        try:
            # This is redundant: we got the userinfo in the login handler.
            # But this demonstrates the usage of oauth2_request outside of
            # the login flow, and getting anything more than userinfo
            # leads to more approval prompts and complexity.
            user_info = await self.oauth2_request(
                "https://www.googleapis.com/oauth2/v1/userinfo",
                access_token=self.current_user["access_token"],
            )
        except tornado.httpclient.HTTPClientError as e:
            print(e.response.body)
            raise
        self.write(f"Hello {user_info['name']}")


class LoginHandler(BaseHandler, tornado.auth.GoogleOAuth2Mixin):
    async def get(self):
        redirect_uri = urllib.parse.urljoin(
            self.application.settings["redirect_base_uri"],
            self.reverse_url("google_oauth"),
        )
        if self.get_argument("code", False):
            access = await self.get_authenticated_user(
                redirect_uri=redirect_uri, code=self.get_argument("code")
            )
            user = await self.oauth2_request(
                "https://www.googleapis.com/oauth2/v1/userinfo",
                access_token=access["access_token"],
            )
            # Save the user and access token.
            user_cookie = dict(id=user["id"], access_token=access["access_token"])
            self.set_signed_cookie("googledemo_user", json.dumps(user_cookie))
            self.redirect("/")
        else:
            self.authorize_redirect(
                redirect_uri=redirect_uri,
                client_id=self.get_google_oauth_settings()["key"],
                scope=["profile", "email"],
                response_type="code",
                extra_params={"approval_prompt": "auto"},
            )


class LogoutHandler(BaseHandler):
    def get(self):
        self.clear_cookie("user")
        self.redirect("/")


async def main():
    tornado.options.parse_command_line()
    app = tornado.web.Application(
        [
            url(r"/", IndexHandler),
            url(r"/auth/google", LoginHandler, name="google_oauth"),
            url(r"/logout", LogoutHandler),
        ],
        redirect_base_uri=f"http://localhost:{options.port}",
        google_oauth=dict(
            key=options.google_oauth_key, secret=options.google_oauth_secret
        ),
        debug=True,
        cookie_secret="__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__",
        login_url="/auth/google",
    )
    app.listen(options.port)
    shutdown_event = asyncio.Event()
    await shutdown_event.wait()


if __name__ == "__main__":
    asyncio.run(main())


================================================
FILE: demos/helloworld/helloworld.py
================================================
#!/usr/bin/env python
#
# Copyright 2009 Facebook
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

import asyncio
import tornado

from tornado.options import define, options

define("port", default=8888, help="run on the given port", type=int)


class MainHandler(tornado.web.RequestHandler):
    def get(self):
        self.write("Hello, world")


async def main():
    tornado.options.parse_command_line()
    application = tornado.web.Application([(r"/", MainHandler)])
    http_server = tornado.httpserver.HTTPServer(application)
    http_server.listen(options.port)
    await asyncio.Event().wait()


if __name__ == "__main__":
    asyncio.run(main())


================================================
FILE: demos/tcpecho/README.md
================================================
TCP echo demo
=============

This demo shows how to use Tornado's asynchronous TCP client and
server by implementing `handle_stream` as a coroutine.

To run the server:

```
$ python server.py
```

The client will send the message given with the `--message` option
(which defaults to "ping"), wait for a response, then quit. To run:

```
$ python client.py --message="your message here"
```

Alternatively, you can interactively send messages to the echo server
with a telnet client. For example:

```
$ telnet localhost 9888
Trying ::1...
Connected to localhost.
Escape character is '^]'.
ping
ping
```


================================================
FILE: demos/tcpecho/client.py
================================================
#!/usr/bin/env python

import asyncio
from tornado.tcpclient import TCPClient
from tornado.options import options, define

define("host", default="localhost", help="TCP server host")
define("port", default=9888, help="TCP port to connect to")
define("message", default="ping", help="Message to send")


async def send_message():
    stream = await TCPClient().connect(options.host, options.port)
    await stream.write((options.message + "\n").encode())
    print("Sent to server:", options.message)
    reply = await stream.read_until(b"\n")
    print("Response from server:", reply.decode().strip())


if __name__ == "__main__":
    options.parse_command_line()
    asyncio.run(send_message())


================================================
FILE: demos/tcpecho/server.py
================================================
#!/usr/bin/env python

import asyncio
import logging
from tornado import gen
from tornado.iostream import StreamClosedError
from tornado.tcpserver import TCPServer
from tornado.options import options, define

define("port", default=9888, help="TCP port to listen on")
logger = logging.getLogger(__name__)


class EchoServer(TCPServer):
    @gen.coroutine
    def handle_stream(self, stream, address):
        while True:
            try:
                data = yield stream.read_until(b"\n")
                logger.info("Received bytes: %s", data)
                if not data.endswith(b"\n"):
                    data = data + b"\n"
                yield stream.write(data)
            except StreamClosedError:
                logger.warning("Lost client at host %s", address[0])
                break
            except Exception as e:
                print(e)


async def main():
    options.parse_command_line()
    logger.info("Listening on TCP port %d", options.port)
    server = EchoServer()
    server.listen(options.port)
    await asyncio.Event().wait()


if __name__ == "__main__":
    asyncio.run(main())


================================================
FILE: demos/websocket/chatdemo.py
================================================
#!/usr/bin/env python
#
# Copyright 2009 Facebook
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""Simplified chat demo for websockets.

Authentication, error handling, etc are left as an exercise for the reader :)
"""

import asyncio
import logging
import tornado
import os.path
import uuid

from tornado.options import define, options

define("port", default=8888, help="run on the given port", type=int)


class Application(tornado.web.Application):
    def __init__(self):
        handlers = [(r"/", MainHandler), (r"/chatsocket", ChatSocketHandler)]
        settings = dict(
            cookie_secret="__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__",
            template_path=os.path.join(os.path.dirname(__file__), "templates"),
            static_path=os.path.join(os.path.dirname(__file__), "static"),
            xsrf_cookies=True,
        )
        super().__init__(handlers, **settings)


class MainHandler(tornado.web.RequestHandler):
    def get(self):
        self.render("index.html", messages=ChatSocketHandler.cache)


class ChatSocketHandler(tornado.websocket.WebSocketHandler):
    waiters = set()
    cache = []
    cache_size = 200

    def get_compression_options(self):
        # Non-None enables compression with default options.
        return {}

    def open(self):
        ChatSocketHandler.waiters.add(self)

    def on_close(self):
        ChatSocketHandler.waiters.remove(self)

    @classmethod
    def update_cache(cls, chat):
        cls.cache.append(chat)
        if len(cls.cache) > cls.cache_size:
            cls.cache = cls.cache[-cls.cache_size :]

    @classmethod
    def send_updates(cls, chat):
        logging.info("sending message to %d waiters", len(cls.waiters))
        for waiter in cls.waiters:
            try:
                waiter.write_message(chat)
            except:
                logging.error("Error sending message", exc_info=True)

    def on_message(self, message):
        logging.info("got message %r", message)
        parsed = tornado.escape.json_decode(message)
        chat = {"id": str(uuid.uuid4()), "body": parsed["body"]}
        chat["html"] = tornado.escape.to_basestring(
            self.render_string("message.html", message=chat)
        )

        ChatSocketHandler.update_cache(chat)
        ChatSocketHandler.send_updates(chat)


async def main():
    tornado.options.parse_command_line()
    app = Application()
    app.listen(options.port)
    await asyncio.Event().wait()


if __name__ == "__main__":
    asyncio.run(main())


================================================
FILE: demos/websocket/static/chat.css
================================================
/*
 * Copyright 2009 FriendFeed
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License. You may obtain
 * a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */

body {
  background: white;
  margin: 10px;
}

body,
input {
  font-family: sans-serif;
  font-size: 10pt;
  color: black;
}

table {
  border-collapse: collapse;
  border: 0;
}

td {
  border: 0;
  padding: 0;
}

#body {
  position: absolute;
  bottom: 10px;
  left: 10px;
}

#input {
  margin-top: 0.5em;
}

#inbox .message {
  padding-top: 0.25em;
}

#nav {
  float: right;
  z-index: 99;
}


================================================
FILE: demos/websocket/static/chat.js
================================================
// Copyright 2009 FriendFeed
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.

$(document).ready(function() {
    if (!window.console) window.console = {};
    if (!window.console.log) window.console.log = function() {};

    $("#messageform").on("submit", function() {
        newMessage($(this));
        return false;
    });
    $("#messageform").on("keypress", function(e) {
        if (e.keyCode == 13) {
            newMessage($(this));
            return false;
        }
    });
    $("#message").select();
    updater.start();
});

function newMessage(form) {
    var message = form.formToDict();
    updater.socket.send(JSON.stringify(message));
    form.find("input[type=text]").val("").select();
}

jQuery.fn.formToDict = function() {
    var fields = this.serializeArray();
    var json = {}
    for (var i = 0; i < fields.length; i++) {
        json[fields[i].name] = fields[i].value;
    }
    if (json.next) delete json.next;
    return json;
};

var updater = {
    socket: null,

    start: function() {
        var url = "ws://" + location.host + "/chatsocket";
        updater.socket = new WebSocket(url);
        updater.socket.onmessage = function(event) {
            updater.showMessage(JSON.parse(event.data));
        }
    },

    showMessage: function(message) {
        var existing = $("#m" + message.id);
        if (existing.length > 0) return;
        var node = $(message.html);
        node.hide();
        $("#inbox").append(node);
        node.slideDown();
    }
};


================================================
FILE: demos/websocket/templates/index.html
================================================
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Tornado Chat Demo</title>
    <link rel="stylesheet" href="{{ static_url("chat.css") }}" type="text/css">
  </head>
  <body>
    <div id="body">
      <div id="inbox">
        {% for message in messages %}
          {% include "message.html" %}
        {% end %}
      </div>
      <div id="input">
        <form action="/a/message/new" method="post" id="messageform">
          <table>
            <tr>
              <td><input type="text" name="body" id="message" style="width:500px"></td>
              <td style="padding-left:5px">
                <input type="submit" value="{{ _("Post") }}">
                <input type="hidden" name="next" value="{{ request.path }}">
                {% module xsrf_form_html() %}
              </td>
            </tr>
          </table>
        </form>
      </div>
    </div>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js" type="text/javascript"></script>
    <script src="{{ static_url("chat.js") }}" type="text/javascript"></script>
  </body>
</html>


================================================
FILE: demos/websocket/templates/message.html
================================================
<div class="message" id="m{{ message["id"] }}">{% module linkify(message["body"]) %}</div>


================================================
FILE: demos/webspider/webspider.py
================================================
#!/usr/bin/env python3

import asyncio
import time
from datetime import timedelta

from html.parser import HTMLParser
from urllib.parse import urljoin, urldefrag

from tornado import gen, httpclient, queues

base_url = "http://www.tornadoweb.org/en/stable/"
concurrency = 10


async def get_links_from_url(url):
    """Download the page at `url` and parse it for links.

    Returned links have had the fragment after `#` removed, and have been made
    absolute so, e.g. the URL 'gen.html#tornado.gen.coroutine' becomes
    'http://www.tornadoweb.org/en/stable/gen.html'.
    """
    response = await httpclient.AsyncHTTPClient().fetch(url)
    print("fetched %s" % url)

    html = response.body.decode(errors="ignore")
    return [urljoin(url, remove_fragment(new_url)) for new_url in get_links(html)]


def remove_fragment(url):
    pure_url, frag = urldefrag(url)
    return pure_url


def get_links(html):
    class URLSeeker(HTMLParser):
        def __init__(self):
            HTMLParser.__init__(self)
            self.urls = []

        def handle_starttag(self, tag, attrs):
            href = dict(attrs).get("href")
            if href and tag == "a":
                self.urls.append(href)

    url_seeker = URLSeeker()
    url_seeker.feed(html)
    return url_seeker.urls


async def main():
    q = queues.Queue()
    start = time.time()
    fetching, fetched, dead = set(), set(), set()

    async def fetch_url(current_url):
        if current_url in fetching:
            return

        print("fetching %s" % current_url)
        fetching.add(current_url)
        urls = await get_links_from_url(current_url)
        fetched.add(current_url)

        for new_url in urls:
            # Only follow links beneath the base URL
            if new_url.startswith(base_url):
                await q.put(new_url)

    async def worker():
        async for url in q:
            if url is None:
                return
            try:
                await fetch_url(url)
            except Exception as e:
                print(f"Exception: {e} {url}")
                dead.add(url)
            finally:
                q.task_done()

    await q.put(base_url)

    # Start workers, then wait for the work queue to be empty.
    workers = gen.multi([worker() for _ in range(concurrency)])
    await q.join(timeout=timedelta(seconds=300))
    assert fetching == (fetched | dead)
    print("Done in %d seconds, fetched %s URLs." % (time.time() - start, len(fetched)))
    print("Unable to fetch %s URLs." % len(dead))

    # Signal all the workers to exit.
    for _ in range(concurrency):
        await q.put(None)
    await workers


if __name__ == "__main__":
    asyncio.run(main())


================================================
FILE: docs/Makefile
================================================
.PHONY: all
all: sphinx

# No -W for doctests because that disallows tests with empty output.
SPHINX_DOCTEST_OPTS=-n -d build/doctress .
SPHINXOPTS=-n -W -d build/doctrees .

.PHONY: sphinx
sphinx:
	sphinx-build -b html $(SPHINXOPTS) build/html

.PHONY: coverage
coverage:
	sphinx-build -b coverage ${SPHINXOPTS} build/coverage
	cat build/coverage/python.txt

.PHONY: latex
latex:
	sphinx-build -b latex $(SPHINXOPTS) build/latex

# Building a pdf requires a latex installation.  For macports, the needed
# packages are texlive-latex-extra and texlive-fonts-recommended.
# The output is in build/latex/tornado.pdf
.PHONY: pdf
pdf: latex
	cd build/latex && pdflatex -interaction=nonstopmode tornado.tex

.PHONY: doctest
doctest:
	sphinx-build -b doctest $(SPHINX_DOCTEST_OPTS) build/doctest

clean:
	rm -rf build


================================================
FILE: docs/asyncio.rst
================================================
``tornado.platform.asyncio`` --- Bridge between ``asyncio`` and Tornado
=======================================================================

.. automodule:: tornado.platform.asyncio
   :members:


   ..
      AnyThreadEventLoopPolicy is created dynamically in getattr, so
      introspection won't find it automatically. This has the unfortunate
      side effect of moving it to the top of the page but it's better than
      having it missing entirely.

   .. autoclass:: AnyThreadEventLoopPolicy
      :members:

================================================
FILE: docs/auth.rst
================================================
``tornado.auth`` --- Third-party login with OpenID and OAuth
============================================================

.. testsetup::

   import tornado

.. automodule:: tornado.auth

   Common protocols
   ----------------

   These classes implement the OpenID and OAuth standards.  They will
   generally need to be subclassed to use them with any particular site.
   The degree of customization required will vary, but in most cases
   overriding the class attributes (which are named beginning with
   underscores for historical reasons) should be sufficient.

   .. autoclass:: OpenIdMixin
      :members:

   .. autoclass:: OAuthMixin

      .. automethod:: authorize_redirect
      .. automethod:: get_authenticated_user
      .. automethod:: _oauth_consumer_token
      .. automethod:: _oauth_get_user_future
      .. automethod:: get_auth_http_client

   .. autoclass:: OAuth2Mixin
      :members:

   Google
   ------

   .. autoclass:: GoogleOAuth2Mixin
      :members:

   Facebook
   --------

   .. autoclass:: FacebookGraphMixin
      :members:

   Twitter
   -------

   .. autoclass:: TwitterMixin
      :members:


================================================
FILE: docs/autoreload.rst
================================================
``tornado.autoreload`` --- Automatically detect code changes in development
===========================================================================

.. automodule:: tornado.autoreload
   :members:


================================================
FILE: docs/caresresolver.rst
================================================
``tornado.platform.caresresolver`` --- Asynchronous DNS Resolver using C-Ares
=============================================================================

.. module:: tornado.platform.caresresolver

This module contains a DNS resolver using the c-ares library (and its
wrapper ``pycares``).

.. py:class:: CaresResolver

    Name resolver based on the c-ares library.

    This is a non-blocking and non-threaded resolver.  It may not produce
    the same results as the system resolver, but can be used for non-blocking
    resolution when threads cannot be used.

    c-ares fails to resolve some names when ``family`` is ``AF_UNSPEC``,
    so it is only recommended for use in ``AF_INET`` (i.e. IPv4).  This is
    the default for ``tornado.simple_httpclient``, but other libraries
    may default to ``AF_UNSPEC``.

    This class requires ``pycares`` version 4. Since this class is deprecated, it will not be
    updated to support ``pycares`` version 5.

    .. deprecated:: 6.2
       This class is deprecated and will be removed in Tornado 7.0. Use the default
       thread-based resolver instead.


================================================
FILE: docs/concurrent.rst
================================================
``tornado.concurrent`` --- Work with ``Future`` objects
=======================================================

.. testsetup::

   from tornado.concurrent import *
   from tornado import gen

.. automodule:: tornado.concurrent
    :members:

     .. class:: Future

        ``tornado.concurrent.Future`` is an alias for `asyncio.Future`.

        In Tornado, the main way in which applications interact with
        ``Future`` objects is by ``awaiting`` or ``yielding`` them in
        coroutines, instead of calling methods on the ``Future`` objects
        themselves. For more information on the available methods, see
        the `asyncio.Future` docs.

        .. versionchanged:: 5.0

           Tornado's implementation of ``Future`` has been replaced by
           the version from `asyncio` when available.

           - ``Future`` objects can only be created while there is a
             current `.IOLoop`
           - The timing of callbacks scheduled with
             ``Future.add_done_callback`` has changed.
           - Cancellation is now partially supported (only on Python 3)
           - The ``exc_info`` and ``set_exc_info`` methods are no longer
             available on Python 3.


================================================
FILE: docs/conf.py
================================================
import os
import sphinx.errors
import sys

# Ensure we get the local copy of tornado instead of what's on the standard path
sys.path.insert(0, os.path.abspath(".."))
import tornado

master_doc = "index"

project = "Tornado"
copyright = "The Tornado Authors"

version = release = tornado.version

extensions = [
    "sphinx.ext.autodoc",
    "sphinx.ext.coverage",
    "sphinx.ext.doctest",
    "sphinx.ext.intersphinx",
    "sphinx.ext.viewcode",
]

primary_domain = "py"
default_role = "py:obj"

autodoc_member_order = "bysource"
autoclass_content = "both"
autodoc_inherit_docstrings = False

# Without this line sphinx includes a copy of object.__init__'s docstring
# on any class that doesn't define __init__.
# https://bitbucket.org/birkenfeld/sphinx/issue/1337/autoclass_content-both-uses-object__init__
autodoc_docstring_signature = False

coverage_skip_undoc_in_source = True
coverage_show_missing_items = True
coverage_ignore_modules = [
    "tornado.curl_httpclient",
    "tornado.platform.asyncio",
    "tornado.platform.caresresolver",
    "tornado.platform.twisted",
    "tornado.simple_httpclient",
]
# I wish this could go in a per-module file...
coverage_ignore_classes = [
    # tornado.gen
    "Runner",
    # tornado.web
    "ChunkedTransferEncoding",
    "GZipContentEncoding",
    "OutputTransform",
    "TemplateModule",
    "url",
    # tornado.websocket
    "WebSocketProtocol",
    "WebSocketProtocol13",
    "WebSocketProtocol76",
]

coverage_ignore_functions = [
    # various modules
    "doctests",
    "main",
    # tornado.escape
    # parse_qs_bytes should probably be documented but it's complicated by
    # having different implementations between py2 and py3.
    "parse_qs_bytes",
    # tornado.gen
    "Multi",
]

html_favicon = "favicon.ico"

latex_documents = [
    (
        "index",
        "tornado.tex",
        "Tornado Documentation",
        "The Tornado Authors",
        "manual",
        False,
    )
]

intersphinx_mapping = {"python": ("https://docs.python.org/3/", None)}

html_theme = "sphinx_rtd_theme"

# Suppress warnings about "class reference target not found" for these types.
# In most cases these types come from type annotations and are for mypy's use.
missing_references = {
    # Generic type variables; nothing to link to.
    "_IOStreamType",
    "_S",
    "_T",
    # Standard library types which are defined in one module and documented
    # in another. We could probably remap them to their proper location if
    # there's not an upstream fix in python and/or sphinx.
    "_asyncio.Future",
    "_io.BytesIO",
    "asyncio.AbstractEventLoop.run_forever",
    "asyncio.events.AbstractEventLoop",
    "concurrent.futures._base.Executor",
    "concurrent.futures._base.Future",
    "futures.Future",
    "socket.socket",
    "unittest.case.TestCase",
    "TextIO",
    # Other stuff. I'm not sure why some of these are showing up, but
    # I'm just listing everything here to avoid blocking the upgrade of sphinx.
    "Future",
    "httputil.HTTPServerConnectionDelegate",
    "httputil.HTTPServerRequest",
    "OutputTransform",
    "Pattern",
    "RAISE",
    "Rule",
    "socket.AddressFamily",
    "tornado.concurrent._T",
    "tornado.gen._T",
    "tornado.ioloop._S",
    "tornado.ioloop._T",
    "tornado.ioloop._Selectable",
    "tornado.iostream._IOStreamType",
    "tornado.locks._ReleasingContextManager",
    "tornado.queues._T",
    "tornado.options._Mockable",
    "tornado.web._ArgDefaultMarker",
    "tornado.web._HandlerDelegate",
    "tornado.web._RequestHandlerType",
    "_RequestHandlerType",
    "traceback",
    "WSGIAppType",
    "Yieldable",
}


def missing_reference_handler(app, env, node, contnode):
    if node["reftarget"] in missing_references:
        raise sphinx.errors.NoUri


def setup(app):
    app.connect("missing-reference", missing_reference_handler)


# Read the Docs configuration updates from
# https://about.readthedocs.com/blog/2024/07/addons-by-default/

# Define the canonical URL if you are using a custom domain on Read the Docs
html_baseurl = os.environ.get("READTHEDOCS_CANONICAL_URL", "")

# Tell Jinja2 templates the build is running on Read the Docs
if os.environ.get("READTHEDOCS", "") == "True":
    if "html_context" not in globals():
        html_context = {}
    html_context["READTHEDOCS"] = True


================================================
FILE: docs/coroutine.rst
================================================
Coroutines and concurrency
==========================

.. toctree::

   gen
   locks
   queues
   process


================================================
FILE: docs/escape.rst
================================================
``tornado.escape`` --- Escaping and string manipulation
=======================================================

.. automodule:: tornado.escape

   Escaping functions
   ------------------

   .. autofunction:: xhtml_escape
   .. autofunction:: xhtml_unescape

   .. autofunction:: url_escape
   .. autofunction:: url_unescape

   .. autofunction:: json_encode
   .. autofunction:: json_decode

   Byte/unicode conversions
   ------------------------

   .. autofunction:: utf8
   .. autofunction:: to_unicode
   .. function:: native_str
   .. function:: to_basestring

      Converts a byte or unicode string into type `str`. These functions
      were used to help transition from Python 2 to Python 3 but are now
      deprecated aliases for `to_unicode`.

   .. autofunction:: recursive_unicode

   Miscellaneous functions
   -----------------------
   .. autofunction:: linkify
   .. autofunction:: squeeze


================================================
FILE: docs/faq.rst
================================================
Frequently Asked Questions
==========================

.. contents::
   :local:

Why isn't this example with ``time.sleep()`` running in parallel?
-----------------------------------------------------------------

Many people's first foray into Tornado's concurrency looks something like
this::

   class BadExampleHandler(RequestHandler):
       def get(self):
           for i in range(5):
               print(i)
               time.sleep(1)

Fetch this handler twice at the same time and you'll see that the second
five-second countdown doesn't start until the first one has completely
finished. The reason for this is that `time.sleep` is a **blocking**
function: it doesn't allow control to return to the `.IOLoop` so that other
handlers can be run.

Of course, `time.sleep` is really just a placeholder in these examples,
the point is to show what happens when something in a handler gets slow.
No matter what the real code is doing, to achieve concurrency blocking
code must be replaced with non-blocking equivalents. This means one of three things:

1. *Find a coroutine-friendly equivalent.* For `time.sleep`, use
   `tornado.gen.sleep` (or `asyncio.sleep`) instead::

    class CoroutineSleepHandler(RequestHandler):
        async def get(self):
            for i in range(5):
                print(i)
                await gen.sleep(1)

   When this option is available, it is usually the best approach.
   See the `Tornado wiki <https://github.com/tornadoweb/tornado/wiki/Links>`_
   for links to asynchronous libraries that may be useful.

2. *Find a callback-based equivalent.* Similar to the first option,
   callback-based libraries are available for many tasks, although they
   are slightly more complicated to use than a library designed for
   coroutines. Adapt the callback-based function into a future::

    class CoroutineTimeoutHandler(RequestHandler):
        async def get(self):
            io_loop = IOLoop.current()
            for i in range(5):
                print(i)
                f = tornado.concurrent.Future()
                do_something_with_callback(f.set_result)
                result = await f

   Again, the
   `Tornado wiki <https://github.com/tornadoweb/tornado/wiki/Links>`_
   can be useful to find suitable libraries.

3. *Run the blocking code on another thread.* When asynchronous libraries
   are not available, `concurrent.futures.ThreadPoolExecutor` can be used
   to run any blocking code on another thread. This is a universal solution
   that can be used for any blocking function whether an asynchronous
   counterpart exists or not::

    class ThreadPoolHandler(RequestHandler):
        async def get(self):
            for i in range(5):
                print(i)
                await IOLoop.current().run_in_executor(None, time.sleep, 1)

See the :doc:`Asynchronous I/O <guide/async>` chapter of the Tornado
user's guide for more on blocking and asynchronous functions.


My code is asynchronous. Why is it not running in parallel in two browser tabs?
-------------------------------------------------------------------------------

Even when a handler is asynchronous and non-blocking, it can be surprisingly
tricky to verify this. Browsers will recognize that you are trying to
load the same page in two different tabs and delay the second request
until the first has finished. To work around this and see that the server
is in fact working in parallel, do one of two things:

* Add something to your urls to make them unique. Instead of
  ``http://localhost:8888`` in both tabs, load
  ``http://localhost:8888/?x=1`` in one and
  ``http://localhost:8888/?x=2`` in the other.

* Use two different browsers. For example, Firefox will be able to load
  a url even while that same url is being loaded in a Chrome tab.


================================================
FILE: docs/gen.rst
================================================
``tornado.gen`` --- Generator-based coroutines
==============================================

.. testsetup::

   from tornado.web import *
   from tornado import gen

.. automodule:: tornado.gen

   Decorators
   ----------

   .. autofunction:: coroutine

   .. autoexception:: Return

   Utility functions
   -----------------

   .. autofunction:: with_timeout(timeout: Union[float, datetime.timedelta], future: Yieldable, quiet_exceptions: Union[Type[Exception], Tuple[Type[Exception], ...]] = ())

   .. autofunction:: sleep

   .. autoclass:: WaitIterator
      :members:

   .. autofunction:: multi(Union[List[Yieldable], Dict[Any, Yieldable]], quiet_exceptions: Union[Type[Exception], Tuple[Type[Exception], ...]] = ())

   .. autofunction:: multi_future(Union[List[Yieldable], Dict[Any, Yieldable]], quiet_exceptions: Union[Type[Exception], Tuple[Type[Exception], ...]] = ())

   .. autofunction:: convert_yielded

   .. autofunction:: maybe_future

   .. autofunction:: is_coroutine_function

   .. autodata:: moment
      :annotation:


================================================
FILE: docs/guide/async.rst
================================================
Asynchronous and non-Blocking I/O
---------------------------------

Real-time web features require a long-lived mostly-idle connection per
user.  In a traditional synchronous web server, this implies devoting
one thread to each user, which can be very expensive.

To minimize the cost of concurrent connections, Tornado uses a
single-threaded event loop.  This means that all application code
should aim to be asynchronous and non-blocking because only one
operation can be active at a time.

The terms asynchronous and non-blocking are closely related and are
often used interchangeably, but they are not quite the same thing.

Blocking
~~~~~~~~

A function **blocks** when it waits for something to happen before
returning.  A function may block for many reasons: network I/O, disk
I/O, mutexes, etc.  In fact, *every* function blocks, at least a
little bit, while it is running and using the CPU (for an extreme
example that demonstrates why CPU blocking must be taken as seriously
as other kinds of blocking, consider password hashing functions like
`bcrypt <http://bcrypt.sourceforge.net/>`_, which by design use
hundreds of milliseconds of CPU time, far more than a typical network
or disk access).

A function can be blocking in some respects and non-blocking in
others.  In the context of Tornado we generally talk about
blocking in the context of network I/O, although all kinds of blocking
are to be minimized.

Asynchronous
~~~~~~~~~~~~

An **asynchronous** function returns before it is finished, and
generally causes some work to happen in the background before
triggering some future action in the application (as opposed to normal
**synchronous** functions, which do everything they are going to do
before returning).  There are many styles of asynchronous interfaces:

* Callback argument
* Return a placeholder (`.Future`, ``Promise``, ``Deferred``)
* Deliver to a queue
* Callback registry (e.g. POSIX signals)

Regardless of which type of interface is used, asynchronous functions
*by definition* interact differently with their callers; there is no
free way to make a synchronous function asynchronous in a way that is
transparent to its callers (systems like `gevent
<http://www.gevent.org>`_ use lightweight threads to offer performance
comparable to asynchronous systems, but they do not actually make
things asynchronous).

Asynchronous operations in Tornado generally return placeholder
objects (``Futures``), with the exception of some low-level components
like the `.IOLoop` that use callbacks. ``Futures`` are usually
transformed into their result with the ``await`` or ``yield``
keywords.

Examples
~~~~~~~~

Here is a sample synchronous function:

.. testcode::

    from tornado.httpclient import HTTPClient

    def synchronous_fetch(url):
        http_client = HTTPClient()
        response = http_client.fetch(url)
        return response.body

And here is the same function rewritten asynchronously as a native coroutine:

.. testcode::

   from tornado.httpclient import AsyncHTTPClient

   async def asynchronous_fetch(url):
       http_client = AsyncHTTPClient()
       response = await http_client.fetch(url)
       return response.body

Or for compatibility with older versions of Python, using the `tornado.gen` module:

..  testcode::

    from tornado.httpclient import AsyncHTTPClient
    from tornado import gen

    @gen.coroutine
    def async_fetch_gen(url):
        http_client = AsyncHTTPClient()
        response = yield http_client.fetch(url)
        raise gen.Return(response.body)

Coroutines are a little magical, but what they do internally is something like this:

.. testcode::

    from tornado.concurrent import Future

    def async_fetch_manual(url):
        http_client = AsyncHTTPClient()
        my_future = Future()
        fetch_future = http_client.fetch(url)
        def on_fetch(f):
            my_future.set_result(f.result().body)
        fetch_future.add_done_callback(on_fetch)
        return my_future

Notice that the coroutine returns its `.Future` before the fetch is
done. This is what makes coroutines *asynchronous*.

Anything you can do with coroutines you can also do by passing
callback objects around, but coroutines provide an important
simplification by letting you organize your code in the same way you
would if it were synchronous. This is especially important for error
handling, since ``try``/``except`` blocks work as you would expect in
coroutines while this is difficult to achieve with callbacks.
Coroutines will be discussed in depth in the next section of this
guide.


================================================
FILE: docs/guide/coroutines.rst
================================================
Coroutines
==========

.. testsetup::

   from tornado import gen

**Coroutines** are the recommended way to write asynchronous code in
Tornado. Coroutines use the Python ``await`` keyword to
suspend and resume execution instead of a chain of callbacks
(cooperative lightweight threads as seen in frameworks like `gevent
<http://www.gevent.org>`_ are sometimes called coroutines as well, but
in Tornado all coroutines use explicit context switches and are called
as asynchronous functions).

Coroutines are almost as simple as synchronous code, but without the
expense of a thread.  They also `make concurrency easier
<https://glyph.twistedmatrix.com/2014/02/unyielding.html>`_ to reason
about by reducing the number of places where a context switch can
happen.

Example::

    async def fetch_coroutine(url):
        http_client = AsyncHTTPClient()
        response = await http_client.fetch(url)
        return response.body

.. _native_coroutines:

Native vs decorated coroutines
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Python 3.5 introduced the ``async`` and ``await`` keywords (functions
using these keywords are also called "native coroutines"). For
compatibility with older versions of Python, you can use "decorated"
or "yield-based" coroutines using the `tornado.gen.coroutine`
decorator.

Native coroutines are the recommended form whenever possible. Only use
decorated coroutines when compatibility with older versions of Python
is required. Examples in the Tornado documentation will generally use
the native form.

Translation between the two forms is generally straightforward::

    # Decorated:                    # Native:

    # Normal function declaration
    # with decorator                # "async def" keywords
    @gen.coroutine
    def a():                        async def a():
        # "yield" all async funcs       # "await" all async funcs
        b = yield c()                   b = await c()
        # "return" and "yield"
        # cannot be mixed in
        # Python 2, so raise a
        # special exception.            # Return normally
        raise gen.Return(b)             return b

Other differences between the two forms of coroutine are outlined below.

- Native coroutines:

  - are generally faster.
  - can use ``async for`` and ``async with``
    statements which make some patterns much simpler.
  - do not run at all unless you ``await`` or
    ``yield`` them. Decorated coroutines can start running "in the
    background" as soon as they are called. Note that for both kinds of
    coroutines it is important to use ``await`` or ``yield`` so that
    any exceptions have somewhere to go.

- Decorated coroutines:

  - have additional integration with the
    `concurrent.futures` package, allowing the result of
    ``executor.submit`` to be yielded directly. For native coroutines,
    use `.IOLoop.run_in_executor` instead.
  - support some shorthand for waiting on multiple
    objects by yielding a list or dict. Use `tornado.gen.multi` to do
    this in native coroutines.
  - can support integration with other packages
    including Twisted via a registry of conversion functions.
    To access this functionality in native coroutines, use
    `tornado.gen.convert_yielded`.
  - always return a `.Future` object. Native
    coroutines return an *awaitable* object that is not a `.Future`. In
    Tornado the two are mostly interchangeable.

How it works
~~~~~~~~~~~~

This section explains the operation of decorated coroutines. Native
coroutines are conceptually similar, but a little more complicated
because of the extra integration with the Python runtime.

A function containing ``yield`` is a **generator**.  All generators
are asynchronous; when called they return a generator object instead
of running to completion.  The ``@gen.coroutine`` decorator
communicates with the generator via the ``yield`` expressions, and
with the coroutine's caller by returning a `.Future`.

Here is a simplified version of the coroutine decorator's inner loop::

    # Simplified inner loop of tornado.gen.Runner
    def run(self):
        # send(x) makes the current yield return x.
        # It returns when the next yield is reached
        future = self.gen.send(self.next)
        def callback(f):
            self.next = f.result()
            self.run()
        future.add_done_callback(callback)

The decorator receives a `.Future` from the generator, waits (without
blocking) for that `.Future` to complete, then "unwraps" the `.Future`
and sends the result back into the generator as the result of the
``yield`` expression.  Most asynchronous code never touches the `.Future`
class directly except to immediately pass the `.Future` returned by
an asynchronous function to a ``yield`` expression.

How to call a coroutine
~~~~~~~~~~~~~~~~~~~~~~~

Coroutines do not raise exceptions in the normal way: any exception
they raise will be trapped in the awaitable object until it is
yielded. This means it is important to call coroutines in the right
way, or you may have errors that go unnoticed::

    async def divide(x, y):
        return x / y

    def bad_call():
        # This should raise a ZeroDivisionError, but it won't because
        # the coroutine is called incorrectly.
        divide(1, 0)

In nearly all cases, any function that calls a coroutine must be a
coroutine itself, and use the ``await`` or ``yield`` keyword in the
call. When you are overriding a method defined in a superclass,
consult the documentation to see if coroutines are allowed (the
documentation should say that the method "may be a coroutine" or "may
return a `.Future`")::

    async def good_call():
        # await will unwrap the object returned by divide() and raise
        # the exception.
        await divide(1, 0)

Sometimes you may want to "fire and forget" a coroutine without waiting
for its result. In this case it is recommended to use `.IOLoop.spawn_callback`,
which makes the `.IOLoop` responsible for the call. If it fails,
the `.IOLoop` will log a stack trace::

    # The IOLoop will catch the exception and print a stack trace in
    # the logs. Note that this doesn't look like a normal call, since
    # we pass the function object to be called by the IOLoop.
    IOLoop.current().spawn_callback(divide, 1, 0)

Using `.IOLoop.spawn_callback` in this way is *recommended* for
functions using ``@gen.coroutine``, but it is *required* for functions
using ``async def`` (otherwise the coroutine runner will not start).

Finally, at the top level of a program, *if the IOLoop is not yet
running,* you can start the `.IOLoop`, run the coroutine, and then
stop the `.IOLoop` with the `.IOLoop.run_sync` method. This is often
used to start the ``main`` function of a batch-oriented program::

    # run_sync() doesn't take arguments, so we must wrap the
    # call in a lambda.
    IOLoop.current().run_sync(lambda: divide(1, 0))

Coroutine patterns
~~~~~~~~~~~~~~~~~~

Calling blocking functions
^^^^^^^^^^^^^^^^^^^^^^^^^^

The simplest way to call a blocking function from a coroutine is to
use `.IOLoop.run_in_executor`, which returns
``Futures`` that are compatible with coroutines::

    async def call_blocking():
        await IOLoop.current().run_in_executor(None, blocking_func, args)

Parallelism
^^^^^^^^^^^

The `.multi` function accepts lists and dicts whose values are
``Futures``, and waits for all of those ``Futures`` in parallel:

.. testcode::

    from tornado.gen import multi

    async def parallel_fetch(url1, url2):
        resp1, resp2 = await multi([http_client.fetch(url1),
                                    http_client.fetch(url2)])

    async def parallel_fetch_many(urls):
        responses = await multi ([http_client.fetch(url) for url in urls])
        # responses is a list of HTTPResponses in the same order

    async def parallel_fetch_dict(urls):
        responses = await multi({url: http_client.fetch(url)
                                 for url in urls})
        # responses is a dict {url: HTTPResponse}

In decorated coroutines, it is possible to ``yield`` the list or dict directly::

    @gen.coroutine
    def parallel_fetch_decorated(url1, url2):
        resp1, resp2 = yield [http_client.fetch(url1),
                              http_client.fetch(url2)]

Interleaving
^^^^^^^^^^^^

Sometimes it is useful to save a `.Future` instead of yielding it
immediately, so you can start another operation before waiting.

.. testcode::

    from tornado.gen import convert_yielded

    async def get(self):
        # convert_yielded() starts the native coroutine in the background.
        # This is equivalent to asyncio.ensure_future() (both work in Tornado).
        fetch_future = convert_yielded(self.fetch_next_chunk())
        while True:
            chunk = await fetch_future
            if chunk is None: break
            self.write(chunk)
            fetch_future = convert_yielded(self.fetch_next_chunk())
            await self.flush()

This is a little easier to do with decorated coroutines, because they
start immediately when called:

.. testcode::

    @gen.coroutine
    def get(self):
        fetch_future = self.fetch_next_chunk()
        while True:
            chunk = yield fetch_future
            if chunk is None: break
            self.write(chunk)
            fetch_future = self.fetch_next_chunk()
            yield self.flush()

Looping
^^^^^^^

In native coroutines, ``async for`` can be used. In older versions of
Python, looping is tricky with coroutines since there is no way to
``yield`` on every iteration of a ``for`` or ``while`` loop and
capture the result of the yield. Instead, you'll need to separate the
loop condition from accessing the results, as in this example from
`Motor <https://motor.readthedocs.io/en/stable/>`_::

    import motor
    db = motor.MotorClient().test

    @gen.coroutine
    def loop_example(collection):
        cursor = db.collection.find()
        while (yield cursor.fetch_next):
            doc = cursor.next_object()

Running in the background
^^^^^^^^^^^^^^^^^^^^^^^^^

As an alternative to `.PeriodicCallback`, a
coroutine can contain a ``while True:`` loop and use
`tornado.gen.sleep`::

    async def minute_loop():
        while True:
            await do_something()
            await gen.sleep(60)

    # Coroutines that loop forever are generally started with
    # spawn_callback().
    IOLoop.current().spawn_callback(minute_loop)

Sometimes a more complicated loop may be desirable. For example, the
previous loop runs every ``60+N`` seconds, where ``N`` is the running
time of ``do_something()``. To run exactly every 60 seconds, use the
interleaving pattern from above::

    async def minute_loop2():
        while True:
            nxt = gen.sleep(60)   # Start the clock.
            await do_something()  # Run while the clock is ticking.
            await nxt             # Wait for the timer to run out.


================================================
FILE: docs/guide/intro.rst
================================================
Introduction
------------

`Tornado <http://www.tornadoweb.org>`_ is a Python web framework and
asynchronous networking library, originally developed at `FriendFeed
<https://en.wikipedia.org/wiki/FriendFeed>`_.  By using non-blocking network I/O, Tornado
can scale to tens of thousands of open connections, making it ideal for
`long polling <http://en.wikipedia.org/wiki/Push_technology#Long_polling>`_,
`WebSockets <http://en.wikipedia.org/wiki/WebSocket>`_, and other
applications that require a long-lived connection to each user.

Tornado can be roughly divided into three major components:

* A web framework (including `.RequestHandler` which is subclassed to
  create web applications, and various supporting classes).
* Client- and server-side implementions of HTTP (`.HTTPServer` and
  `.AsyncHTTPClient`).
* An asynchronous networking library including the classes `.IOLoop`
  and `.IOStream`, which serve as the building blocks for the HTTP
  components and can also be used to implement other protocols.

The Tornado web framework and HTTP server together offer a full-stack
alternative to `WSGI <http://www.python.org/dev/peps/pep-3333/>`_.
While it is possible to use the Tornado HTTP server as a container for
other WSGI frameworks (`.WSGIContainer`), this combination has
limitations and to take full advantage of Tornado you will need to use
Tornado's web framework and HTTP server together.


================================================
FILE: docs/guide/queues.rst
================================================
:class:`~tornado.queues.Queue` example - a concurrent web spider
================================================================

.. currentmodule:: tornado.queues

Tornado's `tornado.queues` module (and the very similar ``Queue`` classes in
`asyncio`) implements an asynchronous producer / consumer pattern for
coroutines, analogous to the pattern implemented for threads by the Python
standard library's `queue` module.

A coroutine that yields `Queue.get` pauses until there is an item in the queue.
If the queue has a maximum size set, a coroutine that yields `Queue.put` pauses
until there is room for another item.

A `~Queue` maintains a count of unfinished tasks, which begins at zero.
`~Queue.put` increments the count; `~Queue.task_done` decrements it.

In the web-spider example here, the queue begins containing only base_url. When
a worker fetches a page it parses the links and puts new ones in the queue,
then calls `~Queue.task_done` to decrement the counter once. Eventually, a
worker fetches a page whose URLs have all been seen before, and there is also
no work left in the queue. Thus that worker's call to `~Queue.task_done`
decrements the counter to zero. The main coroutine, which is waiting for
`~Queue.join`, is unpaused and finishes.

.. literalinclude:: ../../demos/webspider/webspider.py


================================================
FILE: docs/guide/running.rst
================================================
Running and deploying
=====================

Since Tornado supplies its own HTTPServer, running and deploying it is
a little different from other Python web frameworks.  Instead of
configuring a WSGI container to find your application, you write a
``main()`` function that starts the server:

.. testcode::

    import asyncio

    async def main():
        app = make_app()
        app.listen(8888)
        await asyncio.Event().wait()

    if __name__ == '__main__':
        asyncio.run(main())

Configure your operating system or process manager to run this program to
start the server. Please note that it may be necessary to increase the number 
of open files per process (to avoid "Too many open files"-Error). 
To raise this limit (setting it to 50000 for example)  you can use the
``ulimit`` command, modify ``/etc/security/limits.conf`` or set
``minfds`` in your `supervisord <http://www.supervisord.org>`_ config.

Processes and ports
~~~~~~~~~~~~~~~~~~~

Due to the Python GIL (Global Interpreter Lock), it is necessary to run
multiple Python processes to take full advantage of multi-CPU machines.
Typically it is best to run one process per CPU.

The simplest way to do this is to add ``reuse_port=True`` to your ``listen()``
calls and then simply run multiple copies of your application.

Tornado also has the ability to start multiple processes from a single parent
process (note that this does not work on Windows). This requires some
alterations to application startup.

.. testcode::

    def main():
        sockets = bind_sockets(8888)
        tornado.process.fork_processes(0)
        async def post_fork_main():
            server = TCPServer()
            server.add_sockets(sockets)
            await asyncio.Event().wait()
        asyncio.run(post_fork_main())

This is another way to start multiple processes and have them all
share the same port, although it has some limitations.  First, each
child process will have its own ``IOLoop``, so it is important that
nothing touches the global ``IOLoop`` instance (even indirectly) before the
fork.  Second, it is difficult to do zero-downtime updates in this model.
Finally, since all the processes share the same port it is more difficult
to monitor them individually.

For more sophisticated deployments, it is recommended to start the processes
independently, and have each one listen on a different port.
The "process groups" feature of `supervisord <http://www.supervisord.org>`_
is one good way to arrange this.  When each process uses a different port,
an external load balancer such as HAProxy or nginx is usually needed
to present a single address to outside visitors.


Running behind a load balancer
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

When running behind a load balancer like `nginx <http://nginx.net/>`_,
it is recommended to pass ``xheaders=True`` to the `.HTTPServer` constructor.
This will tell Tornado to use headers like ``X-Real-IP`` to get the user's
IP address instead of attributing all traffic to the balancer's IP address.

This is a barebones nginx config file that is structurally similar to
the one we use at FriendFeed. It assumes nginx and the Tornado servers
are running on the same machine, and the four Tornado servers are
running on ports 8000 - 8003::

    user nginx;
    worker_processes 1;

    error_log /var/log/nginx/error.log;
    pid /var/run/nginx.pid;

    events {
        worker_connections 1024;
        use epoll;
    }

    http {
        # Enumerate all the Tornado servers here
        upstream frontends {
            server 127.0.0.1:8000;
            server 127.0.0.1:8001;
            server 127.0.0.1:8002;
            server 127.0.0.1:8003;
        }

        include /etc/nginx/mime.types;
        default_type application/octet-stream;

        access_log /var/log/nginx/access.log;

        keepalive_timeout 65;
        proxy_read_timeout 200;
        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        gzip on;
        gzip_min_length 1000;
        gzip_proxied any;
        gzip_types text/plain text/html text/css text/xml
                   application/x-javascript application/xml
                   application/atom+xml text/javascript;

        # Only retry if there was a communication error, not a timeout
        # on the Tornado server (to avoid propagating "queries of death"
        # to all frontends)
        proxy_next_upstream error;

        server {
            listen 80;

            # Allow file uploads
            client_max_body_size 50M;

            location ^~ /static/ {
                root /var/www;
                if ($query_string) {
                    expires max;
                }
            }
            location = /favicon.ico {
                rewrite (.*) /static/favicon.ico;
            }
            location = /robots.txt {
                rewrite (.*) /static/robots.txt;
            }

            location / {
                proxy_pass_header Server;
                proxy_set_header Host $http_host;
                proxy_redirect off;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Scheme $scheme;
                proxy_pass http://frontends;
            }
        }
    }

Static files and aggressive file caching
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

You can serve static files from Tornado by specifying the
``static_path`` setting in your application::

    settings = {
        "static_path": os.path.join(os.path.dirname(__file__), "static"),
        "cookie_secret": "__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__",
        "login_url": "/login",
        "xsrf_cookies": True,
    }
    application = tornado.web.Application([
        (r"/", MainHandler),
        (r"/login", LoginHandler),
        (r"/(apple-touch-icon\.png)", tornado.web.StaticFileHandler,
         dict(path=settings['static_path'])),
    ], **settings)

This setting will automatically make all requests that start with
``/static/`` serve from that static directory, e.g.
``http://localhost:8888/static/foo.png`` will serve the file
``foo.png`` from the specified static directory. We also automatically
serve ``/robots.txt`` and ``/favicon.ico`` from the static directory
(even though they don't start with the ``/static/`` prefix).

In the above settings, we have explicitly configured Tornado to serve
``apple-touch-icon.png`` from the root with the `.StaticFileHandler`,
though it is physically in the static file directory. (The capturing
group in that regular expression is necessary to tell
`.StaticFileHandler` the requested filename; recall that capturing
groups are passed to handlers as method arguments.) You could do the
same thing to serve e.g. ``sitemap.xml`` from the site root. Of
course, you can also avoid faking a root ``apple-touch-icon.png`` by
using the appropriate ``<link />`` tag in your HTML.

To improve performance, it is generally a good idea for browsers to
cache static resources aggressively so browsers won't send unnecessary
``If-Modified-Since`` or ``Etag`` requests that might block the
rendering of the page. Tornado supports this out of the box with *static
content versioning*.

To use this feature, use the `~.RequestHandler.static_url` method in
your templates rather than typing the URL of the static file directly
in your HTML::

    <html>
       <head>
          <title>FriendFeed - {{ _("Home") }}</title>
       </head>
       <body>
         <div><img src="{{ static_url("images/logo.png") }}"/></div>
       </body>
     </html>

The ``static_url()`` function will translate that relative path to a URI
that looks like ``/static/images/logo.png?v=aae54``. The ``v`` argument
is a hash of the content in ``logo.png``, and its presence makes the
Tornado server send cache headers to the user's browser that will make
the browser cache the content indefinitely.

Since the ``v`` argument is based on the content of the file, if you
update a file and restart your server, it will start sending a new ``v``
value, so the user's browser will automatically fetch the new file. If
the file's contents don't change, the browser will continue to use a
locally cached copy without ever checking for updates on the server,
significantly improving rendering performance.

In production, you probably want to serve static files from a more
optimized static file server like `nginx <http://nginx.net/>`_. You
can configure almost any web server to recognize the version tags used
by ``static_url()`` and set caching headers accordingly.  Here is the
relevant portion of the nginx configuration we use at FriendFeed::

    location /static/ {
        root /var/friendfeed/static;
        if ($query_string) {
            expires max;
        }
     }

.. _debug-mode:

Debug mode and automatic reloading
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

If you pass ``debug=True`` to the ``Application`` constructor, the app
will be run in debug/development mode. In this mode, several features
intended for convenience while developing will be enabled (each of which
is also available as an individual flag; if both are specified the
individual flag takes precedence):

* ``autoreload=True``: The app will watch for changes to its source
  files and reload itself when anything changes. This reduces the need
  to manually restart the server during development. However, certain
  failures (such as syntax errors at import time) can still take the
  server down in a way that debug mode cannot currently recover from.
* ``compiled_template_cache=False``: Templates will not be cached.
* ``static_hash_cache=False``: Static file hashes (used by the
  ``static_url`` function) will not be cached.
* ``serve_traceback=True``: When an exception in a `.RequestHandler`
  is not caught, an error page including a stack trace will be
  generated.

Autoreload mode is not compatible with the multi-process mode of `.HTTPServer`.
You must not give `HTTPServer.start <.TCPServer.start>` an argument other than 1 (or
call `tornado.process.fork_processes`) if you are using autoreload mode.

The automatic reloading feature of debug mode is available as a
standalone module in `tornado.autoreload`.  The two can be used in
combination to provide extra robustness against syntax errors: set
``autoreload=True`` within the app to detect changes while it is running,
and start it with ``python -m tornado.autoreload myserver.py`` to catch
any syntax errors or other errors at startup.

Reloading loses any Python interpreter command-line arguments (e.g. ``-u``)
because it re-executes Python using `sys.executable` and `sys.argv`.
Additionally, modifying these variables will cause reloading to behave
incorrectly.

On some platforms (including Windows and Mac OSX prior to 10.6), the
process cannot be updated "in-place", so when a code change is
detected the old server exits and a new one starts.  This has been
known to confuse some IDEs.


================================================
FILE: docs/guide/security.rst
================================================
Authentication and security
===========================

.. testsetup::

   import tornado

Cookies and signed cookies
~~~~~~~~~~~~~~~~~~~~~~~~~~

You can set cookies in the user's browser with the ``set_cookie``
method:

.. testcode::

    class MainHandler(tornado.web.RequestHandler):
        def get(self):
            if not self.get_cookie("mycookie"):
                self.set_cookie("mycookie", "myvalue")
                self.write("Your cookie was not set yet!")
            else:
                self.write("Your cookie was set!")

Cookies are not secure and can easily be modified by clients.  If you
need to set cookies to, e.g., identify the currently logged in user,
you need to sign your cookies to prevent forgery. Tornado supports
signed cookies with the `~.RequestHandler.set_signed_cookie` and
`~.RequestHandler.get_signed_cookie` methods. To use these methods,
you need to specify a secret key named ``cookie_secret`` when you
create your application. You can pass in application settings as
keyword arguments to your application:

.. testcode::

    application = tornado.web.Application([
        (r"/", MainHandler),
    ], cookie_secret="__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__")

Signed cookies contain the encoded value of the cookie in addition to a
timestamp and an `HMAC <http://en.wikipedia.org/wiki/HMAC>`_ signature.
If the cookie is old or if the signature doesn't match,
``get_signed_cookie`` will return ``None`` just as if the cookie isn't
set. The secure version of the example above:

.. testcode::

    class MainHandler(tornado.web.RequestHandler):
        def get(self):
            if not self.get_signed_cookie("mycookie"):
                self.set_signed_cookie("mycookie", "myvalue")
                self.write("Your cookie was not set yet!")
            else:
                self.write("Your cookie was set!")

Tornado's signed cookies guarantee integrity but not confidentiality.
That is, the cookie cannot be modified but its contents can be seen by the
user.  The ``cookie_secret`` is a symmetric key and must be kept secret --
anyone who obtains the value of this key could produce their own signed
cookies.

By default, Tornado's signed cookies expire after 30 days.  To change this,
use the ``expires_days`` keyword argument to ``set_signed_cookie`` *and* the
``max_age_days`` argument to ``get_signed_cookie``.  These two values are
passed separately so that you may e.g. have a cookie that is valid for 30 days
for most purposes, but for certain sensitive actions (such as changing billing
information) you use a smaller ``max_age_days`` when reading the cookie.

Tornado also supports multiple signing keys to enable signing key
rotation. ``cookie_secret`` then must be a dict with integer key versions
as keys and the corresponding secrets as values. The currently used
signing key must then be set as ``key_version`` application setting
but all other keys in the dict are allowed for cookie signature validation,
if the correct key version is set in the cookie.
To implement cookie updates, the current signing key version can be
queried via `~.RequestHandler.get_signed_cookie_key_version`.

.. _user-authentication:

User authentication
~~~~~~~~~~~~~~~~~~~

The currently authenticated user is available in every request handler
as `self.current_user <.RequestHandler.current_user>`, and in every
template as ``current_user``. By default, ``current_user`` is
``None``.

To implement user authentication in your application, you need to
override the ``get_current_user()`` method in your request handlers to
determine the current user based on, e.g., the value of a cookie. Here
is an example that lets users log into the application simply by
specifying a nickname, which is then saved in a cookie:

.. testcode::

    class BaseHandler(tornado.web.RequestHandler):
        def get_current_user(self):
            return self.get_signed_cookie("user")

    class MainHandler(BaseHandler):
        def get(self):
            if not self.current_user:
                self.redirect("/login")
                return
            name = tornado.escape.xhtml_escape(self.current_user)
            self.write("Hello, " + name)

    class LoginHandler(BaseHandler):
        def get(self):
            self.write('<html><body><form action="/login" method="post">'
                       'Name: <input type="text" name="name">'
                       '<input type="submit" value="Sign in">'
                       '</form></body></html>')

        def post(self):
            self.set_signed_cookie("user", self.get_argument("name"))
            self.redirect("/")

    application = tornado.web.Application([
        (r"/", MainHandler),
        (r"/login", LoginHandler),
    ], cookie_secret="__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__")

You can require that the user be logged in using the `Python
decorator <http://www.python.org/dev/peps/pep-0318/>`_
`tornado.web.authenticated`. If a request goes to a method with this
decorator, and the user is not logged in, they will be redirected to
``login_url`` (another application setting). The example above could be
rewritten:

.. testcode::

    class MainHandler(BaseHandler):
        @tornado.web.authenticated
        def get(self):
            name = tornado.escape.xhtml_escape(self.current_user)
            self.write("Hello, " + name)

    settings = {
        "cookie_secret": "__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__",
        "login_url": "/login",
    }
    application = tornado.web.Application([
        (r"/", MainHandler),
        (r"/login", LoginHandler),
    ], **settings)

If you decorate ``post()`` methods with the ``authenticated``
decorator, and the user is not logged in, the server will send a
``403`` response.  The ``@authenticated`` decorator is simply
shorthand for ``if not self.current_user: self.redirect()`` and may
not be appropriate for non-browser-based login schemes.

Check out the `Tornado Blog example application
<https://github.com/tornadoweb/tornado/tree/stable/demos/blog>`_ for a
complete example that uses authentication (and stores user data in a
PostgreSQL database).

Third party authentication
~~~~~~~~~~~~~~~~~~~~~~~~~~

The `tornado.auth` module implements the authentication and
authorization protocols for a number of the most popular sites on the
web, including Google/Gmail, Facebook, Twitter, and FriendFeed.
The module includes methods to log users in via these sites and, where
applicable, methods to authorize access to the service so you can, e.g.,
download a user's address book or publish a Twitter message on their
behalf.

Here is an example handler that uses Google for authentication, saving
the Google credentials in a cookie for later access:

.. testcode::

    class GoogleOAuth2LoginHandler(tornado.web.RequestHandler,
                                   tornado.auth.GoogleOAuth2Mixin):
        async def get(self):
            if self.get_argument('code', False):
                user = await self.get_authenticated_user(
                    redirect_uri='http://your.site.com/auth/google',
                    code=self.get_argument('code'))
                # Save the user with e.g. set_signed_cookie
            else:
                await self.authorize_redirect(
                    redirect_uri='http://your.site.com/auth/google',
                    client_id=self.settings['google_oauth']['key'],
                    scope=['profile', 'email'],
                    response_type='code',
                    extra_params={'approval_prompt': 'auto'})

See the `tornado.auth` module documentation for more details.

.. _xsrf:

Cross-site request forgery protection
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

`Cross-site request
forgery <http://en.wikipedia.org/wiki/Cross-site_request_forgery>`_, or
XSRF, is a common problem for personalized web applications.

The generally accepted solution to prevent XSRF is to cookie every user
with an unpredictable value and include that value as an additional
argument with every form submission on your site. If the cookie and the
value in the form submission do not match, then the request is likely
forged.

Tornado comes with built-in XSRF protection. To include it in your site,
include the application setting ``xsrf_cookies``:

.. testcode::

    settings = {
        "cookie_secret": "__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__",
        "login_url": "/login",
        "xsrf_cookies": True,
    }
    application = tornado.web.Application([
        (r"/", MainHandler),
        (r"/login", LoginHandler),
    ], **settings)

If ``xsrf_cookies`` is set, the Tornado web application will set the
``_xsrf`` cookie for all users and reject all ``POST``, ``PUT``, and
``DELETE`` requests that do not contain a correct ``_xsrf`` value. If
you turn this setting on, you need to instrument all forms that submit
via ``POST`` to contain this field. You can do this with the special
`.UIModule` ``xsrf_form_html()``, available in all templates::

    <form action="/new_message" method="post">
      {% module xsrf_form_html() %}
      <input type="text" name="message"/>
      <input type="submit" value="Post"/>
    </form>

If you submit AJAX ``POST`` requests, you will also need to instrument
your JavaScript to include the ``_xsrf`` value with each request. This
is the `jQuery <http://jquery.com/>`_ function we use at FriendFeed for
AJAX ``POST`` requests that automatically adds the ``_xsrf`` value to
all requests::

    function getCookie(name) {
        var r = document.cookie.match("\\b" + name + "=([^;]*)\\b");
        return r ? r[1] : undefined;
    }

    jQuery.postJSON = function(url, args, callback) {
        args._xsrf = getCookie("_xsrf");
        $.ajax({url: url, data: $.param(args), dataType: "text", type: "POST",
            success: function(response) {
            callback(eval("(" + response + ")"));
        }});
    };

For ``PUT`` and ``DELETE`` requests (as well as ``POST`` requests that
do not use form-encoded arguments), the XSRF token may also be passed
via an HTTP header named ``X-XSRFToken``.  The XSRF cookie is normally
set when ``xsrf_form_html`` is used, but in a pure-JavaScript application
that does not use any regular forms you may need to access
``self.xsrf_token`` manually (just reading the property is enough to
set the cookie as a side effect).

If you need to customize XSRF behavior on a per-handler basis, you can
override `.RequestHandler.check_xsrf_cookie()`. For example, if you
have an API whose authentication does not use cookies, you may want to
disable XSRF protection by making ``check_xsrf_cookie()`` do nothing.
However, if you support both cookie and non-cookie-based authentication,
it is important that XSRF protection be used whenever the current
request is authenticated with a cookie.

.. _dnsrebinding:

DNS Rebinding
~~~~~~~~~~~~~

`DNS rebinding <https://en.wikipedia.org/wiki/DNS_rebinding>`_ is an
attack that can bypass the same-origin policy and allow external sites
to access resources on private networks. This attack involves a DNS
name (with a short TTL) that alternates between returning an IP
address controlled by the attacker and one controlled by the victim
(often a guessable private IP address such as ``127.0.0.1`` or
``192.168.1.1``).

Applications that use TLS are *not* vulnerable to this attack (because
the browser will display certificate mismatch warnings that block
automated access to the target site).

Applications that cannot use TLS and rely on network-level access
controls (for example, assuming that a server on ``127.0.0.1`` can
only be accessed by the local machine) should guard against DNS
rebinding by validating the ``Host`` HTTP header. This means passing a
restrictive hostname pattern to either a `.HostMatches` router or the
first argument of `.Application.add_handlers`::

    # BAD: uses a default host pattern of r'.*'
    app = Application([('/foo', FooHandler)])

    # GOOD: only matches localhost or its ip address.
    app = Application()
    app.add_handlers(r'(localhost|127\.0\.0\.1)',
                     [('/foo', FooHandler)])

    # GOOD: same as previous example using tornado.routing.
    app = Application([
        (HostMatches(r'(localhost|127\.0\.0\.1)'),
            [('/foo', FooHandler)]),
        ])

In addition, the ``default_host`` argument to `.Application` and the
`.DefaultHostMatches` router must not be used in applications that may
be vulnerable to DNS rebinding, because it has a similar effect to a
wildcard host pattern.


================================================
FILE: docs/guide/structure.rst
================================================
.. currentmodule:: tornado.web

.. testsetup::

   import tornado

Structure of a Tornado web application
======================================

A Tornado web application generally consists of one or more
`.RequestHandler` subclasses, an `.Application` object which
routes incoming requests to handlers, and a ``main()`` function
to start the server.

A minimal "hello world" example looks something like this:

.. testcode::

    import asyncio
    import tornado

    class MainHandler(tornado.web.RequestHandler):
        def get(self):
            self.write("Hello, world")

    def make_app():
        return tornado.web.Application([
            (r"/", MainHandler),
        ])

    async def main():
        app = make_app()
        app.listen(8888)
        shutdown_event = asyncio.Event()
        await shutdown_event.wait()

    if __name__ == "__main__":
        asyncio.run(main())

The ``main`` coroutine
~~~~~~~~~~~~~~~~~~~~~~

Beginning with Tornado 6.2 and Python 3.10, the recommended pattern for starting
a Tornado application is to create a ``main`` coroutine to be run with
`asyncio.run`. (In older versions, it was common to do initialization in a
regular function and then start the event loop with
``IOLoop.current().start()``. However, this pattern produces deprecation
warnings starting in Python 3.10 and will break in some future version of
Python.)

When the ``main`` function returns, the program exits, so most of the time for a
web server ``main`` should run forever. Waiting on an `asyncio.Event` whose
``set()`` method is never called is a convenient way to make an asynchronus
function run forever. (and if you wish to have ``main`` exit early as a part of
a graceful shutdown procedure, you can call ``shutdown_event.set()`` to make it
exit).

The ``Application`` object
~~~~~~~~~~~~~~~~~~~~~~~~~~

The `.Application` object is responsible for global configuration, including
the routing table that maps requests to handlers.

The routing table is a list of `.URLSpec` objects (or tuples), each of
which contains (at least) a regular expression and a handler class.
Order matters; the first matching rule is used.  If the regular
expression contains capturing groups, these groups are the *path
arguments* and will be passed to the handler's HTTP method.  If a
dictionary is passed as the third element of the `.URLSpec`, it
supplies the *initialization arguments* which will be passed to
`.RequestHandler.initialize`.  Finally, the `.URLSpec` may have a
name, which will allow it to be used with
`.RequestHandler.reverse_url`.

For example, in this fragment the root URL ``/`` is mapped to
``MainHandler`` and URLs of the form ``/story/`` followed by a number
are mapped to ``StoryHandler``.  That number is passed (as a string) to
``StoryHandler.get``.

::

    class MainHandler(RequestHandler):
        def get(self):
            self.write('<a href="%s">link to story 1</a>' %
                       self.reverse_url("story", "1"))

    class StoryHandler(RequestHandler):
        def initialize(self, db):
            self.db = db

        def get(self, story_id):
            self.write("this is story %s" % story_id)

    app = Application([
        url(r"/", MainHandler),
        url(r"/story/([0-9]+)", StoryHandler, dict(db=db), name="story")
        ])

The `.Application` constructor takes many keyword arguments that
can be used to customize the behavior of the application and enable
optional features; see `.Application.settings` for the complete list.

Subclassing ``RequestHandler``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Most of the work of a Tornado web application is done in subclasses
of `.RequestHandler`.  The main entry point for a handler subclass
is a method named after the HTTP method being handled: ``get()``,
``post()``, etc.  Each handler may define one or more of these methods
to handle different HTTP actions.  As described above, these methods
will be called with arguments corresponding to the capturing groups
of the routing rule that matched.

Within a handler, call methods such as `.RequestHandler.render` or
`.RequestHandler.write` to produce a response.  ``render()`` loads a
`.Template` by name and renders it with the given
arguments. ``write()`` is used for non-template-based output; it
accepts strings, bytes, and dictionaries (dicts will be encoded as
JSON).

Many methods in `.RequestHandler` are designed to be overridden in
subclasses and be used throughout the application.  It is common
to define a ``BaseHandler`` class that overrides methods such as
`~.RequestHandler.write_error` and `~.RequestHandler.get_current_user`
and then subclass your own ``BaseHandler`` instead of `.RequestHandler`
for all your specific handlers.

Handling request input
~~~~~~~~~~~~~~~~~~~~~~

The request handler can access the object representing the current
request with ``self.request``.  See the class definition for
`~tornado.httputil.HTTPServerRequest` for a complete list of
attributes.

Request data in the formats used by HTML forms will be parsed for you
and is made available in methods like `~.RequestHandler.get_query_argument`
and `~.RequestHandler.get_body_argument`.

.. testcode::

    class MyFormHandler(tornado.web.RequestHandler):
        def get(self):
            self.write('<html><body><form action="/myform" method="POST">'
                       '<input type="text" name="message">'
                       '<input type="submit" value="Submit">'
                       '</form></body></html>')

        def post(self):
            self.set_header("Content-Type", "text/plain")
            self.write("You wrote " + self.get_body_argument("message"))

Since the HTML form encoding is ambiguous as to whether an argument is
a single value or a list with one element, `.RequestHandler` has
distinct methods to allow the application to indicate whether or not
it expects a list.  For lists, use
`~.RequestHandler.get_query_arguments` and
`~.RequestHandler.get_body_arguments` instead of their singular
counterparts.

Files uploaded via a form are available in ``self.request.files``,
which maps names (the name of the HTML ``<input type="file">``
element) to a list of files. Each file is a dictionary of the form
``{"filename":..., "content_type":..., "body":...}``.  The ``files``
object is only present if the files were uploaded with a form wrapper
(i.e. a ``multipart/form-data`` Content-Type); if this format was not used
the raw uploaded data is available in ``self.request.body``.
By default uploaded files are fully buffered in memory; if you need to
handle files that are too large to comfortably keep in memory see the
`.stream_request_body` class decorator.

In the demos directory,
`file_receiver.py <https://github.com/tornadoweb/tornado/tree/stable/demos/file_upload/>`_
shows both methods of receiving file uploads.

Due to the quirks of the HTML form encoding (e.g. the ambiguity around
singular versus plural arguments), Tornado does not attempt to unify
form arguments with other types of input.  In particular, we do not
parse JSON request bodies.  Applications that wish to use JSON instead
of form-encoding may override `~.RequestHandler.prepare` to parse their
requests::

    def prepare(self):
        if self.request.headers.get("Content-Type", "").startswith("application/json"):
            self.json_args = json.loads(self.request.body)
        else:
            self.json_args = None

Overriding RequestHandler methods
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

In addition to ``get()``/``post()``/etc, certain other methods in
`.RequestHandler` are designed to be overridden by subclasses when
necessary. On every request, the following sequence of calls takes
place:

1. A new `.RequestHandler` object is created on each request.
2. `~.RequestHandler.initialize()` is called with the initialization
   arguments from the `.Application` configuration. ``initialize``
   should typically just save the arguments passed into member
   variables; it may not produce any output or call methods like
   `~.RequestHandler.send_error`.
3. `~.RequestHandler.prepare()` is called. This is most useful in a
   base class shared by all of your handler subclasses, as ``prepare``
   is called no matter which HTTP method is used. ``prepare`` may
   produce output; if it calls `~.RequestHandler.finish` (or
   ``redirect``, etc), processing stops here.
4. One of the HTTP methods is called: ``get()``, ``post()``, ``put()``,
   etc. If the URL regular expression contains capturing groups, they
   are passed as arguments to this method.
5. When the request is finished, `~.RequestHandler.on_finish()` is
   called. This is generally after ``get()`` or another HTTP method
   returns.

All methods designed to be overridden are noted as such in the
`.RequestHandler` documentation.  Some of the most commonly
overridden methods include:

- `~.RequestHandler.write_error` -
  outputs HTML for use on error pages.
- `~.RequestHandler.on_connection_close` - called when the client
  disconnects; applications may choose to detect this case and halt
  further processing.  Note that there is no guarantee that a closed
  connection can be detected promptly.
- `~.RequestHandler.get_current_user` - see :ref:`user-authentication`.
- `~.RequestHandler.get_user_locale` - returns `.Locale` object to use
  for the current user.
- `~.RequestHandler.set_default_headers` - may be used to set
  additional headers on the response (such as a custom ``Server``
  header).

Error Handling
~~~~~~~~~~~~~~

If a handler raises an exception, Tornado will call
`.RequestHandler.write_error` to generate an error page.
`tornado.web.HTTPError` can be used to generate a specified status
code; all other exceptions return a 500 status.

The default error page includes a stack trace in debug mode and a
one-line description of the error (e.g. "500: Internal Server Error")
otherwise.  To produce a custom error page, override
`RequestHandler.write_error` (probably in a base class shared by all
your handlers).  This method may produce output normally via
methods such as `~RequestHandler.write` and `~RequestHandler.render`.
If the error was caused by an exception, an ``exc_info`` triple will
be passed as a keyword argument (note that this exception is not
guaranteed to be the current exception in `sys.exc_info`, so
``write_error`` must use e.g.  `traceback.format_exception` instead of
`traceback.format_exc`).

It is also possible to generate an error page from regular handler
methods instead of ``write_error`` by calling
`~.RequestHandler.set_status`, writing a response, and returning.
The special exception `tornado.web.Finish` may be raised to terminate
the handler without calling ``write_error`` in situations where simply
returning is not convenient.

For 404 errors, use the ``default_handler_class`` `Application setting
<.Application.settings>`.  This handler should override
`~.RequestHandler.prepare` instead of a more specific method like
``get()`` so it works with any HTTP method.  It should produce its
error page as described above: either by raising a ``HTTPError(404)``
and overriding ``write_error``, or calling ``self.set_status(404)``
and producing the response directly in ``prepare()``.

Redirection
~~~~~~~~~~~

There are two main ways you can redirect requests in Tornado:
`.RequestHandler.redirect` and with the `.RedirectHandler`.

You can use ``self.redirect()`` within a `.RequestHandler` method to
redirect users elsewhere. There is also an optional parameter
``permanent`` which you can use to indicate that the redirection is
considered permanent.  The default value of ``permanent`` is
``False``, which generates a ``302 Found`` HTTP response code and is
appropriate for things like redirecting users after successful
``POST`` requests.  If ``permanent`` is ``True``, the ``301 Moved
Permanently`` HTTP response code is used, which is useful for
e.g. redirecting to a canonical URL for a page in an SEO-friendly
manner.

`.RedirectHandler` lets you configure redirects directly in your
`.Application` routing table.  For example, to configure a single
static redirect::

    app = tornado.web.Application([
        url(r"/app", tornado.web.RedirectHandler,
            dict(url="http://itunes.apple.com/my-app-id")),
        ])

`.RedirectHandler` also supports regular expression substitutions.
The following rule redirects all requests beginning with ``/pictures/``
to the prefix ``/photos/`` instead::

    app = tornado.web.Application([
        url(r"/photos/(.*)", MyPhotoHandler),
        url(r"/pictures/(.*)", tornado.web.RedirectHandler,
            dict(url=r"/photos/{0}")),
        ])

Unlike `.RequestHandler.redirect`, `.RedirectHandler` uses permanent
redirects by default.  This is because the routing table does not change
at runtime and is presumed to be permanent, while redirects found in
handlers are likely to be the result of other logic that may change.
To send a temporary redirect with a `.RedirectHandler`, add
``permanent=False`` to the `.RedirectHandler` initialization arguments.

Asynchronous handlers
~~~~~~~~~~~~~~~~~~~~~

Certain handler methods (including ``prepare()`` and the HTTP verb
methods ``get()``/``post()``/etc) may be overridden as coroutines to
make the handler asynchronous.

For example, here is a simple handler using a coroutine:

.. testcode::

    class MainHandler(tornado.web.RequestHandler):
        async def get(self):
            http = tornado.httpclient.AsyncHTTPClient()
            response = await http.fetch("http://friendfeed-api.com/v2/feed/bret")
            json = tornado.escape.json_decode(response.body)
            self.write("Fetched " + str(len(json["entries"])) + " entries "
                       "from the FriendFeed API")

For a more advanced asynchronous example, take a look at the `chat
example application
<https://github.com/tornadoweb/tornado/tree/stable/demos/chat>`_, which
implements an AJAX chat room using `long polling
<http://en.wikipedia.org/wiki/Push_technology#Long_polling>`_.  Users
of long polling may want to override ``on_connection_close()`` to
clean up after the client closes the connection (but see that method's
docstring for caveats).


================================================
FILE: docs/guide/templates.rst
================================================
Templates and UI
================

.. testsetup::

   import tornado

Tornado includes a simple, fast, and flexible templating language.
This section describes that language as well as related issues
such as internationalization.

Tornado can also be used with any other Python template language,
although there is no provision for integrating these systems into
`.RequestHandler.render`.  Simply render the template to a string
and pass it to `.RequestHandler.write`

Configuring templates
~~~~~~~~~~~~~~~~~~~~~

By default, Tornado looks for template files in the same directory as
the ``.py`` files that refer to them.  To put your template files in a
different directory, use the ``template_path`` `Application setting
<.Application.settings>` (or override `.RequestHandler.get_template_path`
if you have different template paths for different handlers).

To load templates from a non-filesystem location, subclass
`tornado.template.BaseLoader` and pass an instance as the
``template_loader`` application setting.

Compiled templates are cached by default; to turn off this caching
and reload templates so changes to the underlying files are always
visible, use the application settings ``compiled_template_cache=False``
or ``debug=True``.


Template syntax
~~~~~~~~~~~~~~~

A Tornado template is just HTML (or any other text-based format) with
Python control sequences and expressions embedded within the markup::

    <html>
       <head>
          <title>{{ title }}</title>
       </head>
       <body>
         <ul>
           {% for item in items %}
             <li>{{ escape(item) }}</li>
           {% end %}
         </ul>
       </body>
     </html>

If you saved this template as "template.html" and put it in the same
directory as your Python file, you could render this template with:

.. testcode::

    class MainHandler(tornado.web.RequestHandler):
        def get(self):
            items = ["Item 1", "Item 2", "Item 3"]
            self.render("template.html", title="My title", items=items)

Tornado templates support *control statements* and *expressions*.
Control statements are surrounded by ``{%`` and ``%}``, e.g.
``{% if len(items) > 2 %}``. Expressions are surrounded by ``{{`` and
``}}``, e.g. ``{{ items[0] }}``.

Control statements more or less map exactly to Python statements. We
support ``if``, ``for``, ``while``, and ``try``, all of which are
terminated with ``{% end %}``. We also support *template inheritance*
using the ``extends`` and ``block`` statements, which are described in
detail in the documentation for the `tornado.template`.

Expressions can be any Python expression, including function calls.
Template code is executed in a namespace that includes the following
objects and functions. (Note that this list applies to templates
rendered using `.RequestHandler.render` and
`~.RequestHandler.render_string`. If you're using the
`tornado.template` module directly outside of a `.RequestHandler` many
of these entries are not present).

- ``escape``: alias for `tornado.escape.xhtml_escape`
- ``xhtml_escape``: alias for `tornado.escape.xhtml_escape`
- ``url_escape``: alias for `tornado.escape.url_escape`
- ``json_encode``: alias for `tornado.escape.json_encode`
- ``squeeze``: alias for `tornado.escape.squeeze`
- ``linkify``: alias for `tornado.escape.linkify`
- ``datetime``: the Python `datetime` module
- ``handler``: the current `.RequestHandler` object
- ``request``: alias for `handler.request <.HTTPServerRequest>`
- ``current_user``: alias for `handler.current_user
  <.RequestHandler.current_user>`
- ``locale``: alias for `handler.locale <.Locale>`
- ``_``: alias for `handler.locale.translate <.Locale.translate>`
- ``static_url``: alias for `handler.static_url <.RequestHandler.static_url>`
- ``xsrf_form_html``: alias for `handler.xsrf_form_html
  <.RequestHandler.xsrf_form_html>`
- ``reverse_url``: alias for `.Application.reverse_url`
- All entries from the ``ui_methods`` and ``ui_modules``
  ``Application`` settings
- Any keyword arguments passed to `~.RequestHandler.render` or
  `~.RequestHandler.render_string`

When you are building a real application, you are going to want to use
all of the features of Tornado templates, especially template
inheritance. Read all about those features in the `tornado.template`
section (some features, including ``UIModules`` are implemented in the
`tornado.web` module)

Under the hood, Tornado templates are translated directly to Python. The
expressions you include in your template are copied verbatim into a
Python function representing your template. We don't try to prevent
anything in the template language; we created it explicitly to provide
the flexibility that other, stricter templating systems prevent.
Consequently, if you write random stuff inside of your template
expressions, you will get random Python errors when you execute the
template.

Security
~~~~~~~~

Inserting untrusted content into a web page can lead to security vulnerabilities such as cross-site
scripting (XSS). All data that is passed to a template should be *escaped* to prevent these
vulnerabilities. The correct form of escaping is context-dependent; Tornado's templates are not
aware of the syntax of HTML, JavaScript, etc, and so the template developer must sometimes
explicitly apply the correct escaping function.

The default escaping function is `tornado.escape.xhtml_escape`, which is appropriate for HTML body
content (but not attribute values). In other cases, other functions should be used. In JavaScript,
use the `.json_encode` function, e.g. ``<script>var x = {{ json_encode(some_object) }};</script>``.
`.json_encode` can be used to escape strings, numbers, lists, and dicts. In this example, the
JavaScript variable ``x`` will be the corresponding JavaScript type (string, number, array, or
object), and not the JSON-encoded string representation. Note that it is unsafe to use
`.json_encode` in the context of a JavaScript string literal (including template strings), only in
the top-level syntactic context.

The automatic escaping behavior can be disabled
globally by passing ``autoescape=None`` to the `.Application` or
`.tornado.template.Loader` constructors, for a template file with the
``{% autoescape None %}`` directive, or for a single expression by
replacing ``{{ ... }}`` with ``{% raw ...%}``. Additionally, in each of
these places the name of an alternative escaping function may be used
instead of ``None``.

Note that while Tornado's automatic escaping is helpful in avoiding
XSS vulnerabilities, it is not sufficient in all cases.  Expressions
that appear in certain locations, such as in JavaScript or CSS, may need
additional escaping.  Additionally, either care must be taken to always
use double quotes and `.xhtml_escape` in HTML attributes that may contain
untrusted content, or a separate escaping function must be used for
attributes (see e.g.
`this blog post <http://wonko.com/post/html-escaping>`_).

Internationalization
~~~~~~~~~~~~~~~~~~~~

The locale of the current user (whether they are logged in or not) is
always available as ``self.locale`` in the request handler and as
``locale`` in templates. The name of the locale (e.g., ``en_US``) is
available as ``locale.name``, and you can translate strings with the
`.Locale.translate` method. Templates also have the global function
call ``_()`` available for string translation. The translate function
has two forms::

    _("Translate this string")

which translates the string directly based on the current locale, and::

    _("A person liked this", "%(num)d people liked this",
      len(people)) % {"num": len(people)}

which translates a string that can be singular or plural based on the
value of the third argument. In the example above, a translation of the
first string will be returned if ``len(people)`` is ``1``, or a
translation of the second string will be returned otherwise.

The most common pattern for translations is to use Python named
placeholders for variables (the ``%(num)d`` in the example above) since
placeholders can move around on translation.

Here is a properly internationalized template::

    <html>
       <head>
          <title>FriendFeed - {{ _("Sign in") }}</title>
       </head>
       <body>
         <form action="{{ request.path }}" method="post">
           <div>{{ _("Username") }} <input type="text" name="username"/></div>
           <div>{{ _("Password") }} <input type="password" name="password"/></div>
           <div><input type="submit" value="{{ _("Sign in") }}"/></div>
           {% module xsrf_form_html() %}
         </form>
       </body>
     </html>

By default, we detect the user's locale using the ``Accept-Language``
header sent by the user's browser. We choose ``en_US`` if we can't find
an appropriate ``Accept-Language`` value. If you let user's set their
locale as a preference, you can override this default locale selection
by overriding `.RequestHandler.get_user_locale`:

.. testcode::

    class BaseHandler(tornado.web.RequestHandler):
        def get_current_user(self):
            user_id = self.get_signed_cookie("user")
            if not user_id: return None
            return self.backend.get_user_by_id(user_id)

        def get_user_locale(self):
            if "locale" not in self.current_user.prefs:
                # Use the Accept-Language header
                return None
            return self.current_user.prefs["locale"]

If ``get_user_locale`` returns ``None``, we fall back on the
``Accept-Language`` header.

The `tornado.locale` module supports loading translations in two
formats: the ``.mo`` format used by `gettext` and related tools, and a
simple ``.csv`` format.  An application will generally call either
`tornado.locale.load_translations` or
`tornado.locale.load_gettext_translations` once at startup; see those
methods for more details on the supported formats.

You can get the list of supported locales in your application with
`tornado.locale.get_supported_locales()`. The user's locale is chosen
to be the closest match based on the supported locales. For example, if
the user's locale is ``es_GT``, and the ``es`` locale is supported,
``self.locale`` will be ``es`` for that request. We fall back on
``en_US`` if no close match can be found.

.. _ui-modules:

UI modules
~~~~~~~~~~

Tornado supports *UI modules* to make it easy to support standard,
reusable UI widgets across your application. UI modules are like special
function calls to render components of your page, and they can come
packaged with their own CSS and JavaScript.

For example, if you are implementing a blog, and you want to have blog
entries appear on both the blog home page and on each blog entry page,
you can make an ``Entry`` module to render them on both pages. First,
create a Python module for your UI modules, e.g. ``uimodules.py``::

    class Entry(tornado.web.UIModule):
        def render(self, entry, show_comments=False):
            return self.render_string(
                "module-entry.html", entry=entry, show_comments=show_comments)

Tell Tornado to use ``uimodules.py`` using the ``ui_modules`` setting in
your application::

    from . import uimodules

    class HomeHandler(tornado.web.RequestHandler):
        def get(self):
            entries = self.db.query("SELECT * FROM entries ORDER BY date DESC")
            self.render("home.html", entries=entries)

    class EntryHandler(tornado.web.RequestHandler):
        def get(self, entry_id):
            entry = self.db.get("SELECT * FROM entries WHERE id = %s", entry_id)
            if not entry: raise tornado.web.HTTPError(404)
            self.render("entry.html", entry=entry)

    settings = {
        "ui_modules": uimodules,
    }
    application = tornado.web.Application([
        (r"/", HomeHandler),
        (r"/entry/([0-9]+)", EntryHandler),
    ], **settings)

Within a template, you can call a module with the ``{% module %}``
statement.  For example, you could call the ``Entry`` module from both
``home.html``::

    {% for entry in entries %}
      {% module Entry(entry) %}
    {% end %}

and ``entry.html``::

    {% module Entry(entry, show_comments=True) %}

Modules can include custom CSS and JavaScript functions by overriding
the ``embedded_css``, ``embedded_javascript``, ``javascript_files``, or
``css_files`` methods::

    class Entry(tornado.web.UIModule):
        def embedded_css(self):
            return ".entry { margin-bottom: 1em; }"

        def render(self, entry, show_comments=False):
            return self.render_string(
                "module-entry.html", show_comments=show_comments)

Module CSS and JavaScript will be included once no matter how many times
a module is used on a page. CSS is always included in the ``<head>`` of
the page, and JavaScript is always included just before the ``</body>``
tag at the end of the page.

When additional Python code is not required, a template file itself may
be used as a module. For example, the preceding example could be
rewritten to put the following in ``module-entry.html``::

    {{ set_resources(embedded_css=".entry { margin-bottom: 1em; }") }}
    <!-- more template html... -->

This revised template module would be invoked with::

    {% module Template("module-entry.html", show_comments=True) %}

The ``set_resources`` function is only available in templates invoked
via ``{% module Template(...) %}``. Unlike the ``{% include ... %}``
directive, template modules have a distinct namespace from their
containing template - they can only see the global template namespace
and their own keyword arguments.


================================================
FILE: docs/guide.rst
================================================
User's guide
============

.. toctree::

   guide/intro
   guide/async
   guide/coroutines
   guide/queues
   guide/structure
   guide/templates
   guide/security
   guide/running


================================================
FILE: docs/http.rst
================================================
HTTP servers and clients
========================

.. toctree::

   httpserver
   httpclient
   httputil
   http1connection


================================================
FILE: docs/http1connection.rst
================================================
``tornado.http1connection`` -- HTTP/1.x client/server implementation
====================================================================

.. automodule:: tornado.http1connection
   :members:


================================================
FILE: docs/httpclient.rst
================================================
``tornado.httpclient`` --- Asynchronous HTTP client
===================================================

.. automodule:: tornado.httpclient

   HTTP client interfaces
   ----------------------

   .. autoclass:: HTTPClient
      :members:

   .. autoclass:: AsyncHTTPClient
      :members:

   Request objects
   ---------------
   .. autoclass:: HTTPRequest
      :members:
   
   Response objects
   ----------------
   .. autoclass:: HTTPResponse
      :members:

   Exceptions
   ----------
   .. autoexception:: HTTPClientError
      :members:

   .. exception:: HTTPError

      Alias for `HTTPClientError`.

   Command-line interface
   ----------------------

   This module provides a simple command-line interface to fetch a url
   using Tornado's HTTP client.  Example usage::

      # Fetch the url and print its body
      python -m tornado.httpclient http://www.google.com

      # Just print the headers
      python -m tornado.httpclient --print_headers --print_body=false http://www.google.com

Implementations
~~~~~~~~~~~~~~~

.. automodule:: tornado.simple_httpclient
   
   .. autoclass:: SimpleAsyncHTTPClient
      :members:

.. module:: tornado.curl_httpclient

.. class:: CurlAsyncHTTPClient(max_clients=10, defaults=None)

   ``libcurl``-based HTTP client.

   This implementation supports the following arguments, which can be passed
   to ``configure()`` to control the global singleton, or to the constructor
   when ``force_instance=True``.

   ``max_clients`` is the number of concurrent requests that can be in progress;
   when this limit is reached additional requests will be queued.

   ``defaults`` is a dict of parameters that will be used as defaults on all
   `.HTTPRequest` objects submitted to this client.

Example Code
~~~~~~~~~~~~

* `A simple webspider <https://github.com/tornadoweb/tornado/blob/stable/demos/webspider/webspider.py>`_
  shows how to fetch URLs concurrently.
* `The file uploader demo <https://github.com/tornadoweb/tornado/tree/stable/demos/file_upload/>`_
  uses either HTTP POST or HTTP PUT to upload files to a server.


================================================
FILE: docs/httpserver.rst
================================================
``tornado.httpserver`` --- Non-blocking HTTP server
===================================================

.. automodule:: tornado.httpserver

   HTTP Server
   -----------
   .. autoclass:: HTTPServer(request_callback: Union[httputil.HTTPServerConnectionDelegate, Callable[[httputil.HTTPServerRequest], None]], no_keep_alive: bool = False, xheaders: bool = False, ssl_options: Union[Dict[str, Any], ssl.SSLContext] = None, protocol: Optional[str] = None, decompress_request: bool = False, chunk_size: Optional[int] = None, max_header_size: Optional[int] = None, idle_connection_timeout: Optional[float] = None, body_timeout: Optional[float] = None, max_body_size: Optional[int] = None, max_buffer_size: Optional[int] = None, trusted_downstream: Optional[List[str]] = None)
      :members:

      The public interface of this class is mostly inherited from
      `.TCPServer` and is documented under that class.


================================================
FILE: docs/httputil.rst
================================================
``tornado.httputil`` --- Manipulate HTTP headers and URLs
=========================================================

.. testsetup::

   from tornado.httputil import *

.. automodule:: tornado.httputil
   :members:


================================================
FILE: docs/index.rst
================================================
.. title:: Tornado Web Server

.. meta::
    :google-site-verification: g4bVhgwbVO1d9apCUsT-eKlApg31Cygbp8VGZY8Rf0g

|Tornado Web Server|
====================

.. |Tornado Web Server| image:: tornado.png
    :alt: Tornado Web Server

`Tornado <https://www.tornadoweb.org>`_ is a Python web framework and
asynchronous networking library, originally developed at `FriendFeed
<https://en.wikipedia.org/wiki/FriendFeed>`_.  By using non-blocking network I/O, Tornado
can scale to tens of thousands of open connections, making it ideal for
`long polling <https://en.wikipedia.org/wiki/Push_technology#Long_polling>`_,
`WebSockets <https://en.wikipedia.org/wiki/WebSocket>`_, and other
applications that require a long-lived connection to each user.

Quick links
-----------

* Current version: |version| (`download from PyPI <https://pypi.python.org/pypi/tornado>`_, :doc:`release notes <releases>`)
* `Source (GitHub) <https://github.com/tornadoweb/tornado>`_
* Mailing lists: `discussion <https://groups.google.com/forum/#!forum/python-tornado>`_ and `announcements <https://groups.google.com/forum/#!forum/python-tornado-announce>`_
* `Stack Overflow <https://stackoverflow.com/questions/tagged/tornado>`_
* `Wiki <https://github.com/tornadoweb/tornado/wiki/Links>`_

Hello, world
------------

Here is a simple "Hello, world" example web app for Tornado::

    import asyncio
    import tornado

    class MainHandler(tornado.web.RequestHandler):
        def get(self):
            self.write("Hello, world")

    def make_app():
        return tornado.web.Application([
            (r"/", MainHandler),
        ])

    async def main():
        app = make_app()
        app.listen(8888)
        await asyncio.Event().wait()

    if __name__ == "__main__":
        asyncio.run(main())

This example does not use any of Tornado's asynchronous features; for
that see this `simple chat room
<https://github.com/tornadoweb/tornado/tree/stable/demos/chat>`_.

Threads and WSGI
----------------

Tornado is different from most Python web frameworks. It is not based
on `WSGI <https://wsgi.readthedocs.io/en/latest/>`_, and it is
typically run with only one thread per process. See the :doc:`guide`
for more on Tornado's approach to asynchronous programming.

While some support of WSGI is available in the `tornado.wsgi` module,
it is not a focus of development and most applications should be
written to use Tornado's own interfaces (such as `tornado.web`)
directly instead of using WSGI.

In general, Tornado code is not thread-safe. The only method in
Tornado that is safe to call from other threads is
`.IOLoop.add_callback`. You can also use `.IOLoop.run_in_executor` to
asynchronously run a blocking function on another thread, but note
that the function passed to ``run_in_executor`` should avoid
referencing any Tornado objects. ``run_in_executor`` is the
recommended way to interact with blocking code.

``asyncio`` Integration
-----------------------

Tornado is integrated with the standard library `asyncio` module and
shares the same event loop (by default since Tornado 5.0). In general,
libraries designed for use with `asyncio` can be mixed freely with
Tornado.


Installation
------------

::

    pip install tornado

Tornado is listed in `PyPI <https://pypi.org/project/tornado/>`_ and
can be installed with ``pip``. Note that the source distribution
includes demo applications that are not present when Tornado is
installed in this way, so you may wish to download a copy of the
source tarball or clone the `git repository
<https://github.com/tornadoweb/tornado>`_ as well.

**Prerequisites**: Tornado requires Python 3. The following
optional packages may be useful:

* `pycurl <http://pycurl.io/>`_ is used by the optional
  ``tornado.curl_httpclient``.  Libcurl version 7.22 or higher is required.
* `pycares <https://pypi.org/project/pycares/>`_ is an alternative
  non-blocking DNS resolver that can be used when threads are not
  appropriate.

**Platforms**: Tornado is designed for Unix-like platforms, with best
performance and scalability on systems supporting ``epoll`` (Linux),
``kqueue`` (BSD/macOS), or ``/dev/poll`` (Solaris).

Tornado will also run on Windows, although this configuration is not
officially supported or recommended for production use. Some features
are missing on Windows (including multi-process mode) and scalability
is limited (Even though Tornado is built on ``asyncio``, which
supports Windows, Tornado does not use the APIs that are necessary for
scalable networking on Windows).

Documentation
-------------

This documentation is also available in `PDF and Epub formats
<https://readthedocs.org/projects/tornado/downloads/>`_.

.. toctree::
   :titlesonly:

   guide
   webframework
   http
   networking
   coroutine
   integration
   utilities
   faq
   releases

* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

Discussion and support
----------------------

You can discuss Tornado on `the Tornado developer mailing list
<https://groups.google.com/forum/#!forum/python-tornado>`_, and report bugs on
the `GitHub issue tracker
<https://github.com/tornadoweb/tornado/issues>`_.  Links to additional
resources can be found on the `Tornado wiki
<https://github.com/tornadoweb/tornado/wiki/Links>`_.  New releases are
announced on the `announcements mailing list
<https://groups.google.com/forum/#!forum/python-tornado-announce>`_.

Tornado is available under
the `Apache License, Version 2.0
<http://www.apache.org/licenses/LICENSE-2.0.html>`_.

This web site and all documentation is licensed under `Creative
Commons 3.0 <https://creativecommons.org/licenses/by/3.0/>`_.


================================================
FILE: docs/integration.rst
================================================
Integration with other services
===============================

.. toctree::

   auth
   wsgi
   caresresolver
   twisted
   asyncio


================================================
FILE: docs/ioloop.rst
================================================
``tornado.ioloop`` --- Main event loop
======================================

.. automodule:: tornado.ioloop

   IOLoop objects
   --------------

   .. autoclass:: IOLoop

   Running an IOLoop
   ^^^^^^^^^^^^^^^^^

   .. automethod:: IOLoop.current
   .. automethod:: IOLoop.make_current
   .. automethod:: IOLoop.clear_current
   .. automethod:: IOLoop.start
   .. automethod:: IOLoop.stop
   .. automethod:: IOLoop.run_sync
   .. automethod:: IOLoop.close
   .. automethod:: IOLoop.instance
   .. automethod:: IOLoop.install
   .. automethod:: IOLoop.clear_instance

   I/O events
   ^^^^^^^^^^

   .. automethod:: IOLoop.add_handler
   .. automethod:: IOLoop.update_handler
   .. automethod:: IOLoop.remove_handler

   Callbacks and timeouts
   ^^^^^^^^^^^^^^^^^^^^^^

   .. automethod:: IOLoop.add_callback
   .. automethod:: IOLoop.add_callback_from_signal
   .. automethod:: IOLoop.add_future
   .. automethod:: IOLoop.add_timeout
   .. automethod:: IOLoop.call_at
   .. automethod:: IOLoop.call_later
   .. automethod:: IOLoop.remove_timeout
   .. automethod:: IOLoop.spawn_callback
   .. automethod:: IOLoop.run_in_executor
   .. automethod:: IOLoop.set_default_executor
   .. automethod:: IOLoop.time
   .. autoclass:: PeriodicCallback
      :members:


================================================
FILE: docs/iostream.rst
================================================
``tornado.iostream`` --- Convenient wrappers for non-blocking sockets
=====================================================================

.. automodule:: tornado.iostream

   Base class
   ----------

   .. autoclass:: BaseIOStream

   Main interface
   ^^^^^^^^^^^^^^

   .. automethod:: BaseIOStream.write
   .. automethod:: BaseIOStream.read_b
Download .txt
gitextract_4dy2dktj/

├── .coveragerc
├── .flake8
├── .gitattributes
├── .github/
│   ├── workflows/
│   │   ├── build.yml
│   │   └── test.yml
│   └── zizmor.yml
├── .gitignore
├── .readthedocs.yaml
├── CONTRIBUTING.md
├── LICENSE
├── MANIFEST.in
├── README.rst
├── SECURITY.md
├── codecov.yml
├── demos/
│   ├── README.rst
│   ├── blog/
│   │   ├── Dockerfile
│   │   ├── README
│   │   ├── blog.py
│   │   ├── docker-compose.yml
│   │   ├── requirements.txt
│   │   ├── schema.sql
│   │   ├── static/
│   │   │   └── blog.css
│   │   └── templates/
│   │       ├── archive.html
│   │       ├── base.html
│   │       ├── compose.html
│   │       ├── create_author.html
│   │       ├── entry.html
│   │       ├── feed.xml
│   │       ├── home.html
│   │       ├── login.html
│   │       └── modules/
│   │           └── entry.html
│   ├── chat/
│   │   ├── chatdemo.py
│   │   ├── static/
│   │   │   ├── chat.css
│   │   │   └── chat.js
│   │   └── templates/
│   │       ├── index.html
│   │       └── message.html
│   ├── facebook/
│   │   ├── README
│   │   ├── facebook.py
│   │   ├── static/
│   │   │   ├── facebook.css
│   │   │   └── facebook.js
│   │   └── templates/
│   │       ├── modules/
│   │       │   └── post.html
│   │       └── stream.html
│   ├── file_upload/
│   │   ├── file_receiver.py
│   │   └── file_uploader.py
│   ├── google_auth/
│   │   ├── .gitignore
│   │   └── main.py
│   ├── helloworld/
│   │   └── helloworld.py
│   ├── tcpecho/
│   │   ├── README.md
│   │   ├── client.py
│   │   └── server.py
│   ├── websocket/
│   │   ├── chatdemo.py
│   │   ├── static/
│   │   │   ├── chat.css
│   │   │   └── chat.js
│   │   └── templates/
│   │       ├── index.html
│   │       └── message.html
│   └── webspider/
│       └── webspider.py
├── docs/
│   ├── Makefile
│   ├── asyncio.rst
│   ├── auth.rst
│   ├── autoreload.rst
│   ├── caresresolver.rst
│   ├── concurrent.rst
│   ├── conf.py
│   ├── coroutine.rst
│   ├── escape.rst
│   ├── faq.rst
│   ├── gen.rst
│   ├── guide/
│   │   ├── async.rst
│   │   ├── coroutines.rst
│   │   ├── intro.rst
│   │   ├── queues.rst
│   │   ├── running.rst
│   │   ├── security.rst
│   │   ├── structure.rst
│   │   └── templates.rst
│   ├── guide.rst
│   ├── http.rst
│   ├── http1connection.rst
│   ├── httpclient.rst
│   ├── httpserver.rst
│   ├── httputil.rst
│   ├── index.rst
│   ├── integration.rst
│   ├── ioloop.rst
│   ├── iostream.rst
│   ├── locale.rst
│   ├── locks.rst
│   ├── log.rst
│   ├── netutil.rst
│   ├── networking.rst
│   ├── options.rst
│   ├── process.rst
│   ├── queues.rst
│   ├── releases/
│   │   ├── v1.0.0.rst
│   │   ├── v1.0.1.rst
│   │   ├── v1.1.0.rst
│   │   ├── v1.1.1.rst
│   │   ├── v1.2.0.rst
│   │   ├── v1.2.1.rst
│   │   ├── v2.0.0.rst
│   │   ├── v2.1.0.rst
│   │   ├── v2.1.1.rst
│   │   ├── v2.2.0.rst
│   │   ├── v2.2.1.rst
│   │   ├── v2.3.0.rst
│   │   ├── v2.4.0.rst
│   │   ├── v2.4.1.rst
│   │   ├── v3.0.0.rst
│   │   ├── v3.0.1.rst
│   │   ├── v3.0.2.rst
│   │   ├── v3.1.0.rst
│   │   ├── v3.1.1.rst
│   │   ├── v3.2.0.rst
│   │   ├── v3.2.1.rst
│   │   ├── v3.2.2.rst
│   │   ├── v4.0.0.rst
│   │   ├── v4.0.1.rst
│   │   ├── v4.0.2.rst
│   │   ├── v4.1.0.rst
│   │   ├── v4.2.0.rst
│   │   ├── v4.2.1.rst
│   │   ├── v4.3.0.rst
│   │   ├── v4.4.0.rst
│   │   ├── v4.4.1.rst
│   │   ├── v4.4.2.rst
│   │   ├── v4.4.3.rst
│   │   ├── v4.5.0.rst
│   │   ├── v4.5.1.rst
│   │   ├── v4.5.2.rst
│   │   ├── v4.5.3.rst
│   │   ├── v5.0.0.rst
│   │   ├── v5.0.1.rst
│   │   ├── v5.0.2.rst
│   │   ├── v5.1.0.rst
│   │   ├── v5.1.1.rst
│   │   ├── v6.0.0.rst
│   │   ├── v6.0.1.rst
│   │   ├── v6.0.2.rst
│   │   ├── v6.0.3.rst
│   │   ├── v6.0.4.rst
│   │   ├── v6.1.0.rst
│   │   ├── v6.2.0.rst
│   │   ├── v6.3.0.rst
│   │   ├── v6.3.1.rst
│   │   ├── v6.3.2.rst
│   │   ├── v6.3.3.rst
│   │   ├── v6.4.0.rst
│   │   ├── v6.4.1.rst
│   │   ├── v6.4.2.rst
│   │   ├── v6.5.0.rst
│   │   ├── v6.5.1.rst
│   │   ├── v6.5.2.rst
│   │   ├── v6.5.3.rst
│   │   ├── v6.5.4.rst
│   │   └── v6.5.5.rst
│   ├── releases.rst
│   ├── routing.rst
│   ├── tcpclient.rst
│   ├── tcpserver.rst
│   ├── template.rst
│   ├── testing.rst
│   ├── twisted.rst
│   ├── util.rst
│   ├── utilities.rst
│   ├── web.rst
│   ├── webframework.rst
│   ├── websocket.rst
│   └── wsgi.rst
├── maint/
│   ├── README
│   ├── benchmark/
│   │   ├── benchmark.py
│   │   ├── chunk_benchmark.py
│   │   ├── gen_benchmark.py
│   │   ├── parsing_benchmark.py
│   │   └── template_benchmark.py
│   ├── scripts/
│   │   ├── custom_fixers/
│   │   │   ├── __init__.py
│   │   │   ├── fix_future_imports.py
│   │   │   └── fix_unicode_literal.py
│   │   ├── run_autopep8.sh
│   │   ├── run_fixers.py
│   │   ├── runcog.sh
│   │   └── test_resolvers.py
│   ├── test/
│   │   ├── README
│   │   ├── cython/
│   │   │   ├── .gitignore
│   │   │   ├── MANIFEST.in
│   │   │   ├── cythonapp.pyx
│   │   │   ├── cythonapp_test.py
│   │   │   ├── pythonmodule.py
│   │   │   ├── setup.py
│   │   │   └── tox.ini
│   │   ├── mypy/
│   │   │   ├── .gitignore
│   │   │   ├── bad.py
│   │   │   ├── good.py
│   │   │   ├── setup.py
│   │   │   └── tox.ini
│   │   ├── redbot/
│   │   │   ├── README
│   │   │   ├── red_test.py
│   │   │   └── tox.ini
│   │   └── websocket/
│   │       ├── .gitignore
│   │       ├── client.py
│   │       ├── fuzzingclient.json
│   │       ├── fuzzingserver.json
│   │       ├── run-client.sh
│   │       ├── run-server.sh
│   │       ├── server.py
│   │       └── tox.ini
│   └── vm/
│       ├── README
│       ├── freebsd/
│       │   ├── Vagrantfile
│       │   ├── setup.sh
│       │   └── tox.ini
│       ├── shared-setup.sh
│       ├── ubuntu12.04/
│       │   ├── Vagrantfile
│       │   ├── setup.sh
│       │   └── tox.ini
│       ├── ubuntu14.04/
│       │   ├── Vagrantfile
│       │   ├── setup.sh
│       │   └── tox.ini
│       └── windows/
│           ├── bootstrap.py
│           └── tox.ini
├── pyproject.toml
├── requirements.in
├── requirements.txt
├── runtests.sh
├── setup.cfg
├── setup.py
├── tornado/
│   ├── __init__.py
│   ├── __init__.pyi
│   ├── _locale_data.py
│   ├── auth.py
│   ├── autoreload.py
│   ├── concurrent.py
│   ├── curl_httpclient.py
│   ├── escape.py
│   ├── gen.py
│   ├── http1connection.py
│   ├── httpclient.py
│   ├── httpserver.py
│   ├── httputil.py
│   ├── ioloop.py
│   ├── iostream.py
│   ├── locale.py
│   ├── locks.py
│   ├── log.py
│   ├── netutil.py
│   ├── options.py
│   ├── platform/
│   │   ├── __init__.py
│   │   ├── asyncio.py
│   │   ├── caresresolver.py
│   │   └── twisted.py
│   ├── process.py
│   ├── py.typed
│   ├── queues.py
│   ├── routing.py
│   ├── simple_httpclient.py
│   ├── speedups.c
│   ├── speedups.pyi
│   ├── tcpclient.py
│   ├── tcpserver.py
│   ├── template.py
│   ├── test/
│   │   ├── __init__.py
│   │   ├── __main__.py
│   │   ├── asyncio_test.py
│   │   ├── auth_test.py
│   │   ├── autoreload_test.py
│   │   ├── circlerefs_test.py
│   │   ├── concurrent_test.py
│   │   ├── csv_translations/
│   │   │   └── fr_FR.csv
│   │   ├── curl_httpclient_test.py
│   │   ├── escape_test.py
│   │   ├── gen_test.py
│   │   ├── gettext_translations/
│   │   │   ├── extract_me.py
│   │   │   └── fr_FR/
│   │   │       └── LC_MESSAGES/
│   │   │           ├── tornado_test.mo
│   │   │           └── tornado_test.po
│   │   ├── http1connection_test.py
│   │   ├── httpclient_test.py
│   │   ├── httpserver_test.py
│   │   ├── httputil_test.py
│   │   ├── import_test.py
│   │   ├── ioloop_test.py
│   │   ├── iostream_test.py
│   │   ├── locale_test.py
│   │   ├── locks_test.py
│   │   ├── log_test.py
│   │   ├── netutil_test.py
│   │   ├── options_test.cfg
│   │   ├── options_test.py
│   │   ├── options_test_types.cfg
│   │   ├── options_test_types_str.cfg
│   │   ├── process_test.py
│   │   ├── queues_test.py
│   │   ├── resolve_test_helper.py
│   │   ├── routing_test.py
│   │   ├── runtests.py
│   │   ├── simple_httpclient_test.py
│   │   ├── static/
│   │   │   ├── dir/
│   │   │   │   └── index.html
│   │   │   ├── robots.txt
│   │   │   ├── sample.xml
│   │   │   └── sample.xml.bz2
│   │   ├── static_foo.txt
│   │   ├── tcpclient_test.py
│   │   ├── tcpserver_test.py
│   │   ├── template_test.py
│   │   ├── templates/
│   │   │   └── utf8.html
│   │   ├── test.crt
│   │   ├── test.key
│   │   ├── testing_test.py
│   │   ├── twisted_test.py
│   │   ├── util.py
│   │   ├── util_test.py
│   │   ├── web_test.py
│   │   ├── websocket_test.py
│   │   └── wsgi_test.py
│   ├── testing.py
│   ├── util.py
│   ├── web.py
│   ├── websocket.py
│   └── wsgi.py
└── tox.ini
Download .txt
Showing preview only (266K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (3471 symbols across 101 files)

FILE: demos/blog/blog.py
  class NoResultError (line 37) | class NoResultError(Exception):
  function maybe_create_tables (line 41) | async def maybe_create_tables(db):
  class Application (line 53) | class Application(tornado.web.Application):
    method __init__ (line 54) | def __init__(self, db):
  class BaseHandler (line 79) | class BaseHandler(tornado.web.RequestHandler):
    method row_to_obj (line 80) | def row_to_obj(self, row, cur):
    method execute (line 87) | async def execute(self, stmt, *args):
    method query (line 95) | async def query(self, stmt, *args):
    method queryone (line 110) | async def queryone(self, stmt, *args):
    method prepare (line 123) | async def prepare(self):
    method any_author_exists (line 132) | async def any_author_exists(self):
    method redirect_to_next (line 135) | def redirect_to_next(self):
  class HomeHandler (line 144) | class HomeHandler(BaseHandler):
    method get (line 145) | async def get(self):
  class EntryHandler (line 155) | class EntryHandler(BaseHandler):
    method get (line 156) | async def get(self, slug):
  class ArchiveHandler (line 163) | class ArchiveHandler(BaseHandler):
    method get (line 164) | async def get(self):
  class FeedHandler (line 169) | class FeedHandler(BaseHandler):
    method get (line 170) | async def get(self):
  class ComposeHandler (line 178) | class ComposeHandler(BaseHandler):
    method get (line 180) | async def get(self):
    method post (line 188) | async def post(self):
  class AuthCreateHandler (line 233) | class AuthCreateHandler(BaseHandler):
    method get (line 234) | def get(self):
    method post (line 237) | async def post(self):
  class AuthLoginHandler (line 257) | class AuthLoginHandler(BaseHandler):
    method get (line 258) | async def get(self):
    method post (line 265) | async def post(self):
  class AuthLogoutHandler (line 286) | class AuthLogoutHandler(BaseHandler):
    method get (line 287) | def get(self):
  class EntryModule (line 292) | class EntryModule(tornado.web.UIModule):
    method render (line 293) | def render(self, entry):
  function main (line 297) | async def main():

FILE: demos/blog/schema.sql
  type authors (line 24) | CREATE TABLE authors (
  type entries (line 32) | CREATE TABLE entries (
  type entries (line 43) | CREATE INDEX ON entries (published)

FILE: demos/chat/chatdemo.py
  class MessageBuffer (line 28) | class MessageBuffer:
    method __init__ (line 29) | def __init__(self):
    method get_messages_since (line 35) | def get_messages_since(self, cursor):
    method add_message (line 48) | def add_message(self, message):
  class MainHandler (line 59) | class MainHandler(tornado.web.RequestHandler):
    method get (line 60) | def get(self):
  class MessageNewHandler (line 64) | class MessageNewHandler(tornado.web.RequestHandler):
    method post (line 67) | def post(self):
  class MessageUpdatesHandler (line 85) | class MessageUpdatesHandler(tornado.web.RequestHandler):
    method post (line 91) | async def post(self):
    method on_connection_close (line 107) | def on_connection_close(self):
  function main (line 111) | async def main():

FILE: demos/chat/static/chat.js
  function newMessage (line 34) | function newMessage(form) {
  function getCookie (line 49) | function getCookie(name) {

FILE: demos/facebook/facebook.py
  class Application (line 28) | class Application(tornado.web.Application):
    method __init__ (line 29) | def __init__(self):
  class BaseHandler (line 50) | class BaseHandler(tornado.web.RequestHandler):
    method get_current_user (line 51) | def get_current_user(self):
  class MainHandler (line 58) | class MainHandler(BaseHandler, tornado.auth.FacebookGraphMixin):
    method get (line 60) | async def get(self):
  class AuthLoginHandler (line 71) | class AuthLoginHandler(BaseHandler, tornado.auth.FacebookGraphMixin):
    method get (line 72) | async def get(self):
  class AuthLogoutHandler (line 91) | class AuthLogoutHandler(BaseHandler, tornado.auth.FacebookGraphMixin):
    method get (line 92) | def get(self):
  class PostModule (line 97) | class PostModule(tornado.web.UIModule):
    method render (line 98) | def render(self, post):
  function main (line 102) | async def main():

FILE: demos/file_upload/file_receiver.py
  class POSTHandler (line 19) | class POSTHandler(tornado.web.RequestHandler):
    method post (line 20) | def post(self):
  class PUTHandler (line 33) | class PUTHandler(tornado.web.RequestHandler):
    method initialize (line 34) | def initialize(self):
    method data_received (line 37) | def data_received(self, chunk):
    method put (line 40) | def put(self, filename):
  function make_app (line 47) | def make_app():
  function main (line 51) | async def main():

FILE: demos/file_upload/file_uploader.py
  function multipart_producer (line 26) | async def multipart_producer(boundary, filenames, write):
  function post (line 57) | async def post(filenames):
  function raw_producer (line 72) | async def raw_producer(filename, write):
  function put (line 84) | async def put(filenames):

FILE: demos/google_auth/main.py
  class BaseHandler (line 32) | class BaseHandler(tornado.web.RequestHandler):
    method get_current_user (line 33) | def get_current_user(self):
  class IndexHandler (line 40) | class IndexHandler(BaseHandler, tornado.auth.GoogleOAuth2Mixin):
    method get (line 42) | async def get(self):
  class LoginHandler (line 58) | class LoginHandler(BaseHandler, tornado.auth.GoogleOAuth2Mixin):
    method get (line 59) | async def get(self):
  class LogoutHandler (line 86) | class LogoutHandler(BaseHandler):
    method get (line 87) | def get(self):
  function main (line 92) | async def main():

FILE: demos/helloworld/helloworld.py
  class MainHandler (line 25) | class MainHandler(tornado.web.RequestHandler):
    method get (line 26) | def get(self):
  function main (line 30) | async def main():

FILE: demos/tcpecho/client.py
  function send_message (line 12) | async def send_message():

FILE: demos/tcpecho/server.py
  class EchoServer (line 14) | class EchoServer(TCPServer):
    method handle_stream (line 16) | def handle_stream(self, stream, address):
  function main (line 31) | async def main():

FILE: demos/websocket/chatdemo.py
  class Application (line 32) | class Application(tornado.web.Application):
    method __init__ (line 33) | def __init__(self):
  class MainHandler (line 44) | class MainHandler(tornado.web.RequestHandler):
    method get (line 45) | def get(self):
  class ChatSocketHandler (line 49) | class ChatSocketHandler(tornado.websocket.WebSocketHandler):
    method get_compression_options (line 54) | def get_compression_options(self):
    method open (line 58) | def open(self):
    method on_close (line 61) | def on_close(self):
    method update_cache (line 65) | def update_cache(cls, chat):
    method send_updates (line 71) | def send_updates(cls, chat):
    method on_message (line 79) | def on_message(self, message):
  function main (line 91) | async def main():

FILE: demos/websocket/static/chat.js
  function newMessage (line 33) | function newMessage(form) {

FILE: demos/webspider/webspider.py
  function get_links_from_url (line 16) | async def get_links_from_url(url):
  function remove_fragment (line 30) | def remove_fragment(url):
  function get_links (line 35) | def get_links(html):
  function main (line 51) | async def main():

FILE: docs/conf.py
  function missing_reference_handler (line 139) | def missing_reference_handler(app, env, node, contnode):
  function setup (line 144) | def setup(app):

FILE: maint/benchmark/benchmark.py
  class RootHandler (line 41) | class RootHandler(RequestHandler):
    method get (line 42) | def get(self):
    method _log (line 45) | def _log(self):
  function main (line 49) | def main():
  function run (line 55) | async def run():

FILE: maint/benchmark/chunk_benchmark.py
  class ChunkHandler (line 22) | class ChunkHandler(RequestHandler):
    method get (line 23) | def get(self):
  function main (line 30) | def main():

FILE: maint/benchmark/gen_benchmark.py
  function e2 (line 21) | def e2(callback):
  function e1 (line 26) | def e1():
  function c2 (line 32) | def c2():
  function c1 (line 37) | def c1():
  function main (line 42) | def main():

FILE: maint/benchmark/parsing_benchmark.py
  function headers_split_re (line 30) | def headers_split_re(headers: str) -> None:
  function headers_split_simple (line 35) | def headers_split_simple(headers: str) -> None:
  function headers_parse_re (line 41) | def headers_parse_re(headers: str) -> HTTPHeaders:
  function headers_parse_simple (line 49) | def headers_parse_simple(headers: str) -> HTTPHeaders:
  function run_headers_split (line 59) | def run_headers_split():
  function run_headers_full (line 71) | def run_headers_full():
  class Benchmark (line 83) | class Benchmark(Enum):
    method __new__ (line 84) | def __new__(cls, arg_value: str, func: Callable[[], None]):
  function main (line 94) | def main():

FILE: maint/benchmark/template_benchmark.py
  function render (line 56) | def render():
  function main (line 60) | def main():

FILE: maint/scripts/custom_fixers/fix_future_imports.py
  function is_docstring (line 10) | def is_docstring(stmt):
  class FixFutureImports (line 14) | class FixFutureImports(fixer_base.BaseFix):
    method start_tree (line 19) | def start_tree(self, tree, filename):
    method new_future_import (line 22) | def new_future_import(self, old):
    method transform (line 31) | def transform(self, node, results):
    method finish_tree (line 35) | def finish_tree(self, tree, filename):

FILE: maint/scripts/custom_fixers/fix_unicode_literal.py
  class FixUnicodeLiteral (line 5) | class FixUnicodeLiteral(fixer_base.BaseFix):
    method transform (line 17) | def transform(self, node, results):

FILE: maint/scripts/test_resolvers.py
  function main (line 30) | def main():

FILE: maint/test/cython/cythonapp_test.py
  class CythonCoroutineTest (line 8) | class CythonCoroutineTest(AsyncTestCase):
    method test_native_coroutine (line 10) | def test_native_coroutine(self):
    method test_decorated_coroutine (line 15) | def test_decorated_coroutine(self):
  class CythonArgReplacerTest (line 20) | class CythonArgReplacerTest(unittest.TestCase):
    method test_arg_replacer_function (line 21) | def test_arg_replacer_function(self):
    method test_arg_replacer_method (line 29) | def test_arg_replacer_method(self):

FILE: maint/test/cython/pythonmodule.py
  function hello (line 5) | def hello():

FILE: maint/test/mypy/bad.py
  class MyHandler (line 4) | class MyHandler(RequestHandler):
    method get (line 5) | def get(self) -> str:  # Deliberate type error

FILE: maint/test/mypy/good.py
  class MyHandler (line 5) | class MyHandler(RequestHandler):
    method get (line 6) | def get(self) -> None:
    method post (line 9) | async def post(self) -> None:

FILE: maint/test/redbot/red_test.py
  class HelloHandler (line 15) | class HelloHandler(RequestHandler):
    method get (line 16) | def get(self):
  class RedirectHandler (line 20) | class RedirectHandler(RequestHandler):
    method get (line 21) | def get(self, path):
  class PostHandler (line 25) | class PostHandler(RequestHandler):
    method post (line 26) | def post(self):
  class ChunkedHandler (line 31) | class ChunkedHandler(RequestHandler):
    method get (line 34) | def get(self):
  class CacheHandler (line 42) | class CacheHandler(RequestHandler):
    method get (line 43) | def get(self, computed_etag):
    method compute_etag (line 46) | def compute_etag(self):
  class TestMixin (line 50) | class TestMixin(object):
    method get_handlers (line 51) | def get_handlers(self):
    method get_app_kwargs (line 60) | def get_app_kwargs(self):
    method get_allowed_warnings (line 63) | def get_allowed_warnings(self):
    method get_allowed_errors (line 73) | def get_allowed_errors(self):
    method check_url (line 76) | def check_url(self, path, method='GET', body=None, headers=None,
    method run_redbot (line 115) | def run_redbot(self, url, method, body, headers):
    method test_hello (line 130) | def test_hello(self):
    method test_static (line 133) | def test_static(self):
    method test_static_versioned_url (line 141) | def test_static_versioned_url(self):
    method test_redirect (line 145) | def test_redirect(self):
    method test_permanent_redirect (line 148) | def test_permanent_redirect(self):
    method test_404 (line 151) | def test_404(self):
    method test_post (line 154) | def test_post(self):
    method test_chunked (line 164) | def test_chunked(self):
    method test_strong_etag_match (line 167) | def test_strong_etag_match(self):
    method test_multiple_strong_etag_match (line 175) | def test_multiple_strong_etag_match(self):
    method test_strong_etag_not_match (line 183) | def test_strong_etag_not_match(self):
    method test_multiple_strong_etag_not_match (line 191) | def test_multiple_strong_etag_not_match(self):
    method test_wildcard_etag (line 199) | def test_wildcard_etag(self):
    method test_weak_etag_match (line 208) | def test_weak_etag_match(self):
    method test_multiple_weak_etag_match (line 216) | def test_multiple_weak_etag_match(self):
    method test_weak_etag_not_match (line 224) | def test_weak_etag_not_match(self):
    method test_multiple_weak_etag_not_match (line 232) | def test_multiple_weak_etag_not_match(self):
  class DefaultHTTPTest (line 241) | class DefaultHTTPTest(AsyncHTTPTestCase, TestMixin):
    method get_app (line 242) | def get_app(self):
  class GzipHTTPTest (line 246) | class GzipHTTPTest(AsyncHTTPTestCase, TestMixin):
    method get_app (line 247) | def get_app(self):
    method get_allowed_errors (line 250) | def get_allowed_errors(self):

FILE: maint/test/websocket/client.py
  function run_tests (line 13) | def run_tests():
  function main (line 38) | def main():

FILE: maint/test/websocket/server.py
  class EchoHandler (line 9) | class EchoHandler(WebSocketHandler):
    method on_message (line 10) | def on_message(self, message):
    method get_compression_options (line 13) | def get_compression_options(self):

FILE: maint/vm/windows/bootstrap.py
  function download_to_cache (line 43) | def download_to_cache(url, local_name=None):
  function main (line 54) | def main():

FILE: tornado/__init__.py
  function __getattr__ (line 64) | def __getattr__(name: str) -> typing.Any:

FILE: tornado/auth.py
  class AuthError (line 89) | class AuthError(Exception):
  class OpenIdMixin (line 93) | class OpenIdMixin:
    method authenticate_redirect (line 101) | def authenticate_redirect(
    method get_authenticated_user (line 129) | async def get_authenticated_user(
    method _openid_args (line 161) | def _openid_args(
    method _on_authentication_verified (line 215) | def _on_authentication_verified(
    method get_auth_http_client (line 277) | def get_auth_http_client(self) -> httpclient.AsyncHTTPClient:
  class OAuthMixin (line 286) | class OAuthMixin:
    method authorize_redirect (line 303) | async def authorize_redirect(
    method get_authenticated_user (line 352) | async def get_authenticated_user(
    method _oauth_request_token_url (line 396) | def _oauth_request_token_url(
    method _on_request_token (line 427) | def _on_request_token(
    method _oauth_access_token_url (line 451) | def _oauth_access_token_url(self, request_token: dict[str, Any]) -> str:
    method _oauth_consumer_token (line 477) | def _oauth_consumer_token(self) -> dict[str, Any]:
    method _oauth_get_user_future (line 484) | async def _oauth_get_user_future(
    method _oauth_request_parameters (line 508) | def _oauth_request_parameters(
    method get_auth_http_client (line 543) | def get_auth_http_client(self) -> httpclient.AsyncHTTPClient:
  class OAuth2Mixin (line 552) | class OAuth2Mixin:
    method authorize_redirect (line 564) | def authorize_redirect(
    method _oauth_request_token_url (line 605) | def _oauth_request_token_url(
    method oauth2_request (line 627) | async def oauth2_request(
    method get_auth_http_client (line 680) | def get_auth_http_client(self) -> httpclient.AsyncHTTPClient:
  class TwitterMixin (line 691) | class TwitterMixin(OAuthMixin):
    method authenticate_redirect (line 734) | async def authenticate_redirect(self, callback_uri: str | None = None)...
    method twitter_request (line 756) | async def twitter_request(
    method _oauth_consumer_token (line 828) | def _oauth_consumer_token(self) -> dict[str, Any]:
    method _oauth_get_user_future (line 837) | async def _oauth_get_user_future(
  class GoogleOAuth2Mixin (line 848) | class GoogleOAuth2Mixin(OAuth2Mixin):
    method get_google_oauth_settings (line 878) | def get_google_oauth_settings(self) -> dict[str, str]:
    method get_authenticated_user (line 894) | async def get_authenticated_user(
  class FacebookGraphMixin (line 978) | class FacebookGraphMixin(OAuth2Mixin):
    method get_authenticated_user (line 986) | async def get_authenticated_user(
    method facebook_request (line 1091) | async def facebook_request(
  function _oauth_signature (line 1151) | def _oauth_signature(
  function _oauth10a_signature (line 1182) | def _oauth10a_signature(
  function _oauth_escape (line 1215) | def _oauth_escape(val: str | bytes) -> str:
  function _oauth_parse_response (line 1221) | def _oauth_parse_response(body: bytes) -> dict[str, Any]:

FILE: tornado/autoreload.py
  function start (line 113) | def start(check_time: int = 500) -> None:
  function wait (line 131) | def wait() -> None:
  function watch (line 143) | def watch(filename: str) -> None:
  function add_reload_hook (line 151) | def add_reload_hook(fn: Callable[[], None]) -> None:
  function _reload_on_update (line 161) | def _reload_on_update(modify_times: dict[str, float]) -> None:
  function _check_file (line 187) | def _check_file(modify_times: dict[str, float], path: str) -> None:
  function _reload (line 200) | def _reload() -> None:
  function main (line 245) | def main() -> None:

FILE: tornado/concurrent.py
  class ReturnValueIgnoredError (line 42) | class ReturnValueIgnoredError(Exception):
  function is_future (line 52) | def is_future(x: Any) -> bool:
  class DummyExecutor (line 56) | class DummyExecutor(futures.Executor):
    method submit (line 57) | def submit(  # type: ignore[override]
    method shutdown (line 67) | def shutdown(self, wait: bool = True, cancel_futures: bool = False) ->...
  function run_on_executor (line 74) | def run_on_executor(*args: Any, **kwargs: Any) -> Callable:
  function chain_future (line 141) | def chain_future(
  function future_set_result_unless_cancelled (line 178) | def future_set_result_unless_cancelled(
  function future_set_exception_unless_cancelled (line 192) | def future_set_exception_unless_cancelled(
  function future_set_exc_info (line 214) | def future_set_exc_info(
  function future_add_done_callback (line 237) | def future_add_done_callback(
  function future_add_done_callback (line 244) | def future_add_done_callback(
  function future_add_done_callback (line 250) | def future_add_done_callback(

FILE: tornado/curl_httpclient.py
  class CurlAsyncHTTPClient (line 47) | class CurlAsyncHTTPClient(AsyncHTTPClient):
    method initialize (line 48) | def initialize(  # type: ignore
    method close (line 82) | def close(self) -> None:
    method fetch_impl (line 97) | def fetch_impl(
    method _handle_socket (line 104) | def _handle_socket(self, event: int, fd: int, multi: Any, data: bytes)...
    method _set_timeout (line 133) | def _set_timeout(self, msecs: int) -> None:
    method _handle_events (line 141) | def _handle_events(self, fd: int, events: int) -> None:
    method _handle_timeout (line 159) | def _handle_timeout(self) -> None:
    method _handle_force_timeout (line 188) | def _handle_force_timeout(self) -> None:
    method _finish_pending_requests (line 201) | def _finish_pending_requests(self) -> None:
    method _process_queue (line 215) | def _process_queue(self) -> None:
    method _finish (line 256) | def _finish(
    method handle_callback_exception (line 310) | def handle_callback_exception(self, callback: Any) -> None:
    method _curl_create (line 313) | def _curl_create(self) -> pycurl.Curl:
    method _curl_setup_request (line 325) | def _curl_setup_request(
    method _curl_header_callback (line 547) | def _curl_header_callback(
    method _curl_debug (line 572) | def _curl_debug(self, debug_type: int, debug_msg: str) -> None:
  class CurlError (line 585) | class CurlError(HTTPError):
    method __init__ (line 586) | def __init__(self, errno: int, message: str) -> None:

FILE: tornado/escape.py
  function xhtml_escape (line 39) | def xhtml_escape(value: str | bytes) -> str:
  function xhtml_unescape (line 62) | def xhtml_unescape(value: str | bytes) -> str:
  function json_encode (line 83) | def json_encode(value: Any) -> str:
  function json_decode (line 99) | def json_decode(value: str | bytes) -> Any:
  function squeeze (line 107) | def squeeze(value: str) -> str:
  function url_escape (line 112) | def url_escape(value: str | bytes, plus: bool = True) -> str:
  function url_unescape (line 132) | def url_unescape(value: str | bytes, encoding: None, plus: bool = True) ...
  function url_unescape (line 137) | def url_unescape(value: str | bytes, encoding: str = "utf-8", plus: bool...
  function url_unescape (line 141) | def url_unescape(
  function parse_qs_bytes (line 171) | def parse_qs_bytes(
  function utf8 (line 198) | def utf8(value: bytes) -> bytes:
  function utf8 (line 203) | def utf8(value: str) -> bytes:
  function utf8 (line 208) | def utf8(value: None) -> None:
  function utf8 (line 212) | def utf8(value: None | str | bytes) -> bytes | None:
  function to_unicode (line 229) | def to_unicode(value: str) -> str:
  function to_unicode (line 234) | def to_unicode(value: bytes) -> str:
  function to_unicode (line 239) | def to_unicode(value: None) -> None:
  function to_unicode (line 243) | def to_unicode(value: None | str | bytes) -> str | None:
  function recursive_unicode (line 266) | def recursive_unicode(obj: Any) -> Any:
  function linkify (line 297) | def linkify(

FILE: tornado/gen.py
  class KeyReuseError (line 106) | class KeyReuseError(Exception):
  class UnknownKeyError (line 110) | class UnknownKeyError(Exception):
  class LeakedCallbackError (line 114) | class LeakedCallbackError(Exception):
  class BadYieldError (line 118) | class BadYieldError(Exception):
  class ReturnValueIgnoredError (line 122) | class ReturnValueIgnoredError(Exception):
  function _value_from_stopiteration (line 126) | def _value_from_stopiteration(e: Union[StopIteration, "Return"]) -> Any:
  function _create_future (line 141) | def _create_future() -> Future:
  function _fake_ctx_run (line 156) | def _fake_ctx_run(f: Callable[..., _T], *args: Any, **kw: Any) -> _T:
  function coroutine (line 161) | def coroutine(
  function coroutine (line 167) | def coroutine(func: Callable[..., _T]) -> Callable[..., "Future[_T]"]: ...
  function coroutine (line 170) | def coroutine(
  function is_coroutine_function (line 262) | def is_coroutine_function(func: Any) -> bool:
  class Return (line 271) | class Return(Exception):
    method __init__ (line 289) | def __init__(self, value: Any = None) -> None:
  class WaitIterator (line 296) | class WaitIterator:
    method __init__ (line 353) | def __init__(self, *args: Future, **kwargs: Future) -> None:
    method done (line 372) | def done(self) -> bool:
    method next (line 380) | def next(self) -> Future:
    method _done_callback (line 393) | def _done_callback(self, done: Future) -> None:
    method _return_result (line 399) | def _return_result(self, done: Future) -> Future:
    method __aiter__ (line 414) | def __aiter__(self) -> typing.AsyncIterator:
    method __anext__ (line 417) | def __anext__(self) -> Future:
  function multi (line 425) | def multi(
  function multi (line 432) | def multi(
  function multi (line 438) | def multi(
  function multi_future (line 492) | def multi_future(
  function maybe_future (line 555) | def maybe_future(x: Any) -> Future:
  function with_timeout (line 576) | def with_timeout(
  function sleep (line 657) | def sleep(duration: float) -> "Future[None]":
  class _NullFuture (line 678) | class _NullFuture:
    method result (line 691) | def result(self) -> None:
    method done (line 694) | def done(self) -> bool:
  class Runner (line 723) | class Runner:
    method __init__ (line 732) | def __init__(
    method run (line 750) | def run(self) -> None:
    method handle_yield (line 808) | def handle_yield(self, yielded: _Yieldable) -> bool:
    method handle_exception (line 831) | def handle_exception(
  function _wrap_awaitable (line 843) | def _wrap_awaitable(awaitable: Awaitable) -> Future:
  function convert_yielded (line 856) | def convert_yielded(yielded: _Yieldable) -> Future:

FILE: tornado/http1connection.py
  class _QuietException (line 41) | class _QuietException(Exception):
    method __init__ (line 42) | def __init__(self) -> None:
  class _ExceptionLoggingContext (line 46) | class _ExceptionLoggingContext:
    method __init__ (line 52) | def __init__(self, logger: logging.Logger) -> None:
    method __enter__ (line 55) | def __enter__(self) -> None:
    method __exit__ (line 58) | def __exit__(
  class HTTP1ConnectionParameters (line 73) | class HTTP1ConnectionParameters:
    method __init__ (line 76) | def __init__(
  class HTTP1Connection (line 106) | class HTTP1Connection(httputil.HTTPConnection):
    method __init__ (line 113) | def __init__(
    method read_response (line 170) | def read_response(self, delegate: httputil.HTTPMessageDelegate) -> Awa...
    method _read_message (line 185) | async def _read_message(self, delegate: httputil.HTTPMessageDelegate) ...
    method _clear_callbacks (line 307) | def _clear_callbacks(self) -> None:
    method set_close_callback (line 319) | def set_close_callback(self, callback: Callable[[], None] | None) -> N...
    method _on_connection_close (line 333) | def _on_connection_close(self) -> None:
    method close (line 345) | def close(self) -> None:
    method detach (line 352) | def detach(self) -> iostream.IOStream:
    method set_body_timeout (line 367) | def set_body_timeout(self, timeout: float) -> None:
    method set_max_body_size (line 374) | def set_max_body_size(self, max_body_size: int) -> None:
    method write_headers (line 381) | def write_headers(
    method _format_chunk (line 468) | def _format_chunk(self, chunk: bytes) -> bytes:
    method write (line 484) | def write(self, chunk: bytes) -> "Future[None]":
    method finish (line 502) | def finish(self) -> None:
    method _on_write_complete (line 534) | def _on_write_complete(self, future: "Future[None]") -> None:
    method _can_keep_alive (line 547) | def _can_keep_alive(
    method _finish_request (line 567) | def _finish_request(self, future: "Optional[Future[None]]") -> None:
    method _parse_headers (line 578) | def _parse_headers(self, data: bytes) -> tuple[str, httputil.HTTPHeade...
    method _read_body (line 590) | def _read_body(
    method _read_fixed_body (line 643) | async def _read_fixed_body(
    method _read_chunked_body (line 657) | async def _read_chunked_body(self, delegate: httputil.HTTPMessageDeleg...
    method _read_body_until_close (line 691) | async def _read_body_until_close(
  class _GzipMessageDelegate (line 702) | class _GzipMessageDelegate(httputil.HTTPMessageDelegate):
    method __init__ (line 705) | def __init__(self, delegate: httputil.HTTPMessageDelegate, chunk_size:...
    method headers_received (line 710) | def headers_received(
    method data_received (line 724) | async def data_received(self, chunk: bytes) -> None:
    method finish (line 745) | def finish(self) -> None:
    method on_connection_close (line 760) | def on_connection_close(self) -> None:
  class HTTP1ServerConnection (line 764) | class HTTP1ServerConnection:
    method __init__ (line 767) | def __init__(
    method close (line 786) | async def close(self) -> None:
    method start_serving (line 800) | def start_serving(self, delegate: httputil.HTTPServerConnectionDelegat...
    method _server_request_loop (line 811) | async def _server_request_loop(
  function parse_int (line 845) | def parse_int(s: str) -> int:
  function parse_hex_int (line 852) | def parse_hex_int(s: str) -> int:
  function is_transfer_encoding_chunked (line 859) | def is_transfer_encoding_chunked(headers: httputil.HTTPHeaders) -> bool:

FILE: tornado/httpclient.py
  class HTTPClient (line 59) | class HTTPClient:
    method __init__ (line 89) | def __init__(
    method __del__ (line 112) | def __del__(self) -> None:
    method close (line 115) | def close(self) -> None:
    method fetch (line 122) | def fetch(
  class AsyncHTTPClient (line 140) | class AsyncHTTPClient(Configurable):
    method configurable_base (line 182) | def configurable_base(cls) -> type[Configurable]:
    method configurable_default (line 186) | def configurable_default(cls) -> type[Configurable]:
    method _async_clients (line 192) | def _async_clients(cls) -> dict[IOLoop, "AsyncHTTPClient"]:
    method __new__ (line 198) | def __new__(cls, force_instance: bool = False, **kwargs: Any) -> "Asyn...
    method initialize (line 216) | def initialize(self, defaults: dict[str, Any] | None = None) -> None:
    method close (line 223) | def close(self) -> None:
    method fetch (line 249) | def fetch(
    method fetch_impl (line 309) | def fetch_impl(
    method configure (line 315) | def configure(
  class HTTPRequest (line 339) | class HTTPRequest:
    method __init__ (line 358) | def __init__(
    method headers (line 552) | def headers(self) -> httputil.HTTPHeaders:
    method headers (line 559) | def headers(self, value: dict[str, str] | httputil.HTTPHeaders) -> None:
    method body (line 566) | def body(self) -> bytes:
    method body (line 570) | def body(self, value: bytes | str) -> None:
  class HTTPResponse (line 574) | class HTTPResponse:
    method __init__ (line 629) | def __init__(
    method body (line 672) | def body(self) -> bytes:
    method rethrow (line 680) | def rethrow(self) -> None:
    method __repr__ (line 685) | def __repr__(self) -> str:
  class HTTPClientError (line 690) | class HTTPClientError(Exception):
    method __init__ (line 711) | def __init__(
    method __str__ (line 722) | def __str__(self) -> str:
  class _RequestProxy (line 735) | class _RequestProxy:
    method __init__ (line 741) | def __init__(self, request: HTTPRequest, defaults: dict[str, Any] | No...
    method __getattr__ (line 745) | def __getattr__(self, name: str) -> Any:
  function main (line 755) | def main() -> None:

FILE: tornado/httpserver.py
  class HTTPServer (line 41) | class HTTPServer(TCPServer, Configurable, httputil.HTTPServerConnectionD...
    method __init__ (line 151) | def __init__(self, *args: Any, **kwargs: Any) -> None:
    method initialize (line 159) | def initialize(
    method configurable_base (line 204) | def configurable_base(cls) -> type[Configurable]:
    method configurable_default (line 208) | def configurable_default(cls) -> type[Configurable]:
    method close_all_connections (line 211) | async def close_all_connections(self) -> None:
    method handle_stream (line 230) | def handle_stream(self, stream: iostream.IOStream, address: tuple) -> ...
    method start_request (line 238) | def start_request(
    method on_close (line 251) | def on_close(self, server_conn: object) -> None:
  class _CallableAdapter (line 255) | class _CallableAdapter(httputil.HTTPMessageDelegate):
    method __init__ (line 256) | def __init__(
    method headers_received (line 267) | def headers_received(
    method data_received (line 279) | def data_received(self, chunk: bytes) -> Awaitable[None] | None:
    method finish (line 283) | def finish(self) -> None:
    method on_connection_close (line 289) | def on_connection_close(self) -> None:
  class _HTTPRequestContext (line 293) | class _HTTPRequestContext:
    method __init__ (line 294) | def __init__(
    method __str__ (line 328) | def __str__(self) -> str:
    method _apply_xheaders (line 339) | def _apply_xheaders(self, headers: httputil.HTTPHeaders) -> None:
    method _unapply_xheaders (line 361) | def _unapply_xheaders(self) -> None:
  class _ProxyAdapter (line 371) | class _ProxyAdapter(httputil.HTTPMessageDelegate):
    method __init__ (line 372) | def __init__(
    method headers_received (line 380) | def headers_received(
    method data_received (line 390) | def data_received(self, chunk: bytes) -> Awaitable[None] | None:
    method finish (line 393) | def finish(self) -> None:
    method on_connection_close (line 397) | def on_connection_close(self) -> None:
    method _cleanup (line 401) | def _cleanup(self) -> None:

FILE: tornado/httputil.py
  class _ABNF (line 66) | class _ABNF:
  function _normalize_header (line 123) | def _normalize_header(name: str) -> str:
  class HTTPHeaders (line 132) | class HTTPHeaders(collections.abc.MutableMapping[str, str]):
    method __init__ (line 162) | def __init__(self, __arg: Mapping[str, list[str]]) -> None:
    method __init__ (line 166) | def __init__(self, __arg: Mapping[str, str]) -> None:
    method __init__ (line 170) | def __init__(self, *args: tuple[str, str]) -> None:
    method __init__ (line 174) | def __init__(self, **kwargs: str) -> None:
    method __init__ (line 177) | def __init__(self, *args: typing.Any, **kwargs: str) -> None:
    method add (line 197) | def add(self, name: str, value: str, *, _chars_are_bytes: bool = True)...
    method get_list (line 217) | def get_list(self, name: str) -> list[str]:
    method get_all (line 222) | def get_all(self) -> Iterable[tuple[str, str]]:
    method parse_line (line 232) | def parse_line(self, line: str, *, _chars_are_bytes: bool = True) -> N...
    method parse (line 284) | def parse(cls, headers: str, *, _chars_are_bytes: bool = True) -> HTTP...
    method __setitem__ (line 326) | def __setitem__(self, name: str, value: str) -> None:
    method __contains__ (line 331) | def __contains__(self, name: object) -> bool:
    method __getitem__ (line 339) | def __getitem__(self, name: str) -> str:
    method __delitem__ (line 345) | def __delitem__(self, name: str) -> None:
    method __len__ (line 350) | def __len__(self) -> int:
    method __iter__ (line 353) | def __iter__(self) -> Iterator[typing.Any]:
    method copy (line 356) | def copy(self) -> HTTPHeaders:
    method __str__ (line 365) | def __str__(self) -> str:
  class HTTPServerRequest (line 374) | class HTTPServerRequest:
    method __init__ (line 478) | def __init__(
    method cookies (line 548) | def cookies(self) -> dict[str, http.cookies.Morsel]:
    method full_url (line 568) | def full_url(self) -> str:
    method request_time (line 572) | def request_time(self) -> float:
    method get_ssl_certificate (line 579) | def get_ssl_certificate(self, binary_form: bool = False) -> None | dic...
    method _parse_body (line 608) | def _parse_body(self) -> None:
    method __repr__ (line 620) | def __repr__(self) -> str:
  class HTTPInputError (line 626) | class HTTPInputError(Exception):
  class HTTPOutputError (line 636) | class HTTPOutputError(Exception):
  class HTTPServerConnectionDelegate (line 645) | class HTTPServerConnectionDelegate:
    method start_request (line 651) | def start_request(
    method on_close (line 665) | def on_close(self, server_conn: object) -> None:
  class HTTPMessageDelegate (line 674) | class HTTPMessageDelegate:
    method headers_received (line 681) | def headers_received(
    method data_received (line 700) | def data_received(self, chunk: bytes) -> Awaitable[None] | None:
    method finish (line 707) | def finish(self) -> None:
    method on_connection_close (line 711) | def on_connection_close(self) -> None:
  class HTTPConnection (line 720) | class HTTPConnection:
    method write_headers (line 726) | def write_headers(
    method write (line 750) | def write(self, chunk: bytes) -> Future[None]:
    method finish (line 761) | def finish(self) -> None:
  function url_concat (line 766) | def url_concat(
  class HTTPFile (line 811) | class HTTPFile(ObjectDict):
  function _parse_request_range (line 827) | def _parse_request_range(
  function _get_content_range (line 878) | def _get_content_range(start: int | None, end: int | None, total: int) -...
  function _int_or_none (line 893) | def _int_or_none(val: str) -> int | None:
  class ParseMultipartConfig (line 901) | class ParseMultipartConfig:
  class ParseBodyConfig (line 935) | class ParseBodyConfig:
  function set_parse_body_config (line 950) | def set_parse_body_config(config: ParseBodyConfig) -> None:
  function parse_body_arguments (line 976) | def parse_body_arguments(
  function parse_multipart_form_data (line 1031) | def parse_multipart_form_data(
  function format_timestamp (line 1095) | def format_timestamp(
  class RequestStartLine (line 1119) | class RequestStartLine(typing.NamedTuple):
  function parse_request_start_line (line 1125) | def parse_request_start_line(line: str) -> RequestStartLine:
  class ResponseStartLine (line 1147) | class ResponseStartLine(typing.NamedTuple):
  function parse_response_start_line (line 1153) | def parse_response_start_line(line: str) -> ResponseStartLine:
  function _parseparam (line 1189) | def _parseparam(s: str) -> Generator[str]:
  function _parse_header (line 1207) | def _parse_header(line: str) -> tuple[str, dict[str, str]]:
  function _encode_header (line 1242) | def _encode_header(key: str, pdict: dict[str, str]) -> str:
  function encode_username_password (line 1262) | def encode_username_password(username: str | bytes, password: str | byte...
  function doctests (line 1276) | def doctests() -> unittest.TestSuite:
  function split_host_and_port (line 1285) | def split_host_and_port(netloc: str) -> tuple[str, int | None]:
  function qs_to_qsl (line 1302) | def qs_to_qsl(qs: dict[str, list[AnyStr]]) -> Iterable[tuple[str, AnyStr]]:
  function _unquote_replace (line 1315) | def _unquote_replace(m: re.Match) -> str:
  function _unquote_cookie (line 1322) | def _unquote_cookie(s: str) -> str:
  function parse_cookie (line 1349) | def parse_cookie(cookie: str) -> dict[str, str]:

FILE: tornado/ioloop.py
  class _Selectable (line 55) | class _Selectable(Protocol):
    method fileno (line 56) | def fileno(self) -> int:
    method close (line 59) | def close(self) -> None:
  class IOLoop (line 67) | class IOLoop(Configurable):
    method configure (line 167) | def configure(cls, impl: None | str | type[Configurable], **kwargs: An...
    method instance (line 177) | def instance() -> IOLoop:
    method install (line 198) | def install(self) -> None:
    method clear_instance (line 213) | def clear_instance() -> None:
    method current (line 230) | def current() -> IOLoop:
    method current (line 235) | def current(instance: bool = True) -> IOLoop | None:
    method current (line 239) | def current(instance: bool = True) -> IOLoop | None:
    method make_current (line 283) | def make_current(self) -> None:
    method _make_current (line 310) | def _make_current(self) -> None:
    method clear_current (line 315) | def clear_current() -> None:
    method _clear_current (line 332) | def _clear_current() -> None:
    method _clear_current_hook (line 337) | def _clear_current_hook(self) -> None:
    method configurable_base (line 345) | def configurable_base(cls) -> type[Configurable]:
    method configurable_default (line 349) | def configurable_default(cls) -> type[Configurable]:
    method initialize (line 354) | def initialize(self, make_current: bool = True) -> None:
    method close (line 358) | def close(self, all_fds: bool = False) -> None:
    method add_handler (line 386) | def add_handler(
    method add_handler (line 392) | def add_handler(
    method add_handler (line 397) | def add_handler(
    method update_handler (line 416) | def update_handler(self, fd: int | _Selectable, events: int) -> None:
    method remove_handler (line 425) | def remove_handler(self, fd: int | _Selectable) -> None:
    method start (line 434) | def start(self) -> None:
    method stop (line 442) | def stop(self) -> None:
    method run_sync (line 455) | def run_sync(self, func: Callable, timeout: float | None = None) -> Any:
    method time (line 543) | def time(self) -> float:
    method add_timeout (line 557) | def add_timeout(
    method call_later (line 598) | def call_later(
    method call_at (line 613) | def call_at(
    method remove_timeout (line 631) | def remove_timeout(self, timeout: object) -> None:
    method add_callback (line 640) | def add_callback(self, callback: Callable, *args: Any, **kwargs: Any) ...
    method add_callback_from_signal (line 652) | def add_callback_from_signal(
    method spawn_callback (line 667) | def spawn_callback(self, callback: Callable, *args: Any, **kwargs: Any...
    method add_future (line 676) | def add_future(
    method run_in_executor (line 709) | def run_in_executor(
    method set_default_executor (line 737) | def set_default_executor(self, executor: concurrent.futures.Executor) ...
    method _run_callback (line 744) | def _run_callback(self, callback: Callable[[], Any]) -> None:
    method _discard_future_result (line 774) | def _discard_future_result(self, future: Future) -> None:
    method split_fd (line 778) | def split_fd(self, fd: int | _Selectable) -> tuple[int, int | _Selecta...
    method close_fd (line 798) | def close_fd(self, fd: int | _Selectable) -> None:
    method _register_task (line 818) | def _register_task(self, f: Future) -> None:
    method _unregister_task (line 821) | def _unregister_task(self, f: Future) -> None:
  class _Timeout (line 825) | class _Timeout:
    method __init__ (line 831) | def __init__(
    method __lt__ (line 847) | def __lt__(self, other: _Timeout) -> bool:
    method __le__ (line 850) | def __le__(self, other: _Timeout) -> bool:
  class PeriodicCallback (line 854) | class PeriodicCallback:
    method __init__ (line 892) | def __init__(
    method start (line 909) | def start(self) -> None:
    method stop (line 919) | def stop(self) -> None:
    method is_running (line 926) | def is_running(self) -> bool:
    method _run (line 933) | async def _run(self) -> None:
    method _schedule_next (line 945) | def _schedule_next(self) -> None:
    method _update_next (line 950) | def _update_next(self, current_time: float) -> None:

FILE: tornado/iostream.py
  class StreamClosedError (line 75) | class StreamClosedError(IOError):
    method __init__ (line 89) | def __init__(self, real_error: BaseException | None = None) -> None:
  class UnsatisfiableReadError (line 94) | class UnsatisfiableReadError(Exception):
  class StreamBufferFullError (line 104) | class StreamBufferFullError(Exception):
  class _StreamBuffer (line 108) | class _StreamBuffer:
    method __init__ (line 114) | def __init__(self) -> None:
    method __len__ (line 123) | def __len__(self) -> int:
    method append (line 130) | def append(self, data: bytes | bytearray | memoryview) -> None:
    method peek (line 152) | def peek(self, size: int) -> memoryview:
    method advance (line 169) | def advance(self, size: int) -> None:
  class BaseIOStream (line 198) | class BaseIOStream:
    method __init__ (line 216) | def __init__(
    method fileno (line 273) | def fileno(self) -> int | ioloop._Selectable:
    method close_fd (line 277) | def close_fd(self) -> None:
    method write_to_fd (line 285) | def write_to_fd(self, data: memoryview) -> int:
    method read_from_fd (line 292) | def read_from_fd(self, buf: bytearray | memoryview) -> int | None:
    method get_fd_error (line 307) | def get_fd_error(self) -> Exception | None:
    method read_until_regex (line 317) | def read_until_regex(
    method read_until (line 356) | def read_until(
    method read_bytes (line 391) | def read_bytes(self, num_bytes: int, partial: bool = False) -> Awaitab...
    method read_into (line 419) | def read_into(self, buf: bytearray, partial: bool = False) -> Awaitabl...
    method read_until_close (line 464) | def read_until_close(self) -> Awaitable[bytes]:
    method write (line 494) | def write(self, data: bytes | memoryview) -> "Future[None]":
    method set_close_callback (line 536) | def set_close_callback(self, callback: Callable[[], None] | None) -> N...
    method close (line 551) | def close(
    method _signal_closed (line 599) | def _signal_closed(self) -> None:
    method reading (line 638) | def reading(self) -> bool:
    method writing (line 642) | def writing(self) -> bool:
    method closed (line 646) | def closed(self) -> bool:
    method set_nodelay (line 650) | def set_nodelay(self, value: bool) -> None:
    method _handle_connect (line 665) | def _handle_connect(self) -> None:
    method _handle_events (line 668) | def _handle_events(self, fd: int | ioloop._Selectable, events: int) ->...
    method _read_to_buffer_loop (line 721) | def _read_to_buffer_loop(self) -> int | None:
    method _handle_read (line 762) | def _handle_read(self) -> None:
    method _start_read (line 776) | def _start_read(self) -> Future:
    method _finish_read (line 799) | def _finish_read(self, size: int) -> None:
    method _try_inline_read (line 814) | def _try_inline_read(self) -> None:
    method _read_to_buffer (line 836) | def _read_to_buffer(self) -> int | None:
    method _read_from_buffer (line 882) | def _read_from_buffer(self, pos: int) -> None:
    method _find_read_pos (line 892) | def _find_read_pos(self) -> int | None:
    method _check_max_bytes (line 931) | def _check_max_bytes(self, delimiter: bytes | Pattern, size: int) -> N...
    method _handle_write (line 938) | def _handle_write(self) -> None:
    method _consume (line 976) | def _consume(self, loc: int) -> bytes:
    method _check_closed (line 987) | def _check_closed(self) -> None:
    method _maybe_add_error_listener (line 991) | def _maybe_add_error_listener(self) -> None:
    method _add_io_state (line 1006) | def _add_io_state(self, state: int) -> None:
    method _is_connreset (line 1035) | def _is_connreset(self, exc: BaseException) -> bool:
  class IOStream (line 1046) | class IOStream(BaseIOStream):
    method __init__ (line 1086) | def __init__(self, socket: socket.socket, *args: Any, **kwargs: Any) -...
    method fileno (line 1091) | def fileno(self) -> int | ioloop._Selectable:
    method close_fd (line 1094) | def close_fd(self) -> None:
    method get_fd_error (line 1098) | def get_fd_error(self) -> Exception | None:
    method read_from_fd (line 1102) | def read_from_fd(self, buf: bytearray | memoryview) -> int | None:
    method write_to_fd (line 1110) | def write_to_fd(self, data: memoryview) -> int:
    method connect (line 1118) | def connect(
    method start_tls (line 1185) | def start_tls(
    method _handle_connect (line 1261) | def _handle_connect(self) -> None:
    method set_nodelay (line 1289) | def set_nodelay(self, value: bool) -> None:
  class SSLIOStream (line 1306) | class SSLIOStream(IOStream):
    method __init__ (line 1320) | def __init__(self, *args: Any, **kwargs: Any) -> None:
    method reading (line 1343) | def reading(self) -> bool:
    method writing (line 1346) | def writing(self) -> bool:
    method _do_ssl_handshake (line 1349) | def _do_ssl_handshake(self) -> None:
    method _finish_ssl_connect (line 1400) | def _finish_ssl_connect(self) -> None:
    method _handle_read (line 1406) | def _handle_read(self) -> None:
    method _handle_write (line 1412) | def _handle_write(self) -> None:
    method connect (line 1418) | def connect(
    method _handle_connect (line 1437) | def _handle_connect(self) -> None:
    method wait_for_handshake (line 1465) | def wait_for_handshake(self) -> "Future[SSLIOStream]":
    method write_to_fd (line 1497) | def write_to_fd(self, data: memoryview) -> int:
    method read_from_fd (line 1520) | def read_from_fd(self, buf: bytearray | memoryview) -> int | None:
    method _is_connreset (line 1546) | def _is_connreset(self, e: BaseException) -> bool:
  class PipeIOStream (line 1552) | class PipeIOStream(BaseIOStream):
    method __init__ (line 1563) | def __init__(self, fd: int, *args: Any, **kwargs: Any) -> None:
    method fileno (line 1576) | def fileno(self) -> int:
    method close_fd (line 1579) | def close_fd(self) -> None:
    method write_to_fd (line 1582) | def write_to_fd(self, data: memoryview) -> int:
    method read_from_fd (line 1590) | def read_from_fd(self, buf: bytearray | memoryview) -> int | None:
  function doctests (line 1605) | def doctests() -> Any:

FILE: tornado/locale.py
  function get (line 63) | def get(*locale_codes: str) -> Locale:
  function set_default_locale (line 77) | def set_default_locale(code: str) -> None:
  function load_translations (line 91) | def load_translations(directory: str, encoding: str | None = None) -> None:
  function load_gettext_translations (line 178) | def load_gettext_translations(directory: str, domain: str) -> None:
  function get_supported_locales (line 220) | def get_supported_locales() -> Iterable[str]:
  class Locale (line 225) | class Locale:
    method get_closest (line 235) | def get_closest(cls, *locale_codes: str) -> Locale:
    method get (line 253) | def get(cls, code: str) -> Locale:
    method __init__ (line 270) | def __init__(self, code: str) -> None:
    method translate (line 305) | def translate(
    method pgettext (line 320) | def pgettext(
    method format_date (line 329) | def format_date(
    method format_day (line 435) | def format_day(
    method list (line 457) | def list(self, parts: Any) -> str:
    method friendly_number (line 474) | def friendly_number(self, value: int) -> str:
  class CSVLocale (line 486) | class CSVLocale(Locale):
    method __init__ (line 489) | def __init__(self, code: str, translations: dict[str, dict[str, str]])...
    method translate (line 493) | def translate(
    method pgettext (line 510) | def pgettext(
  class GettextLocale (line 522) | class GettextLocale(Locale):
    method __init__ (line 525) | def __init__(self, code: str, translations: gettext.NullTranslations) ...
    method translate (line 532) | def translate(
    method pgettext (line 544) | def pgettext(

FILE: tornado/locks.py
  class _TimeoutGarbageCollector (line 27) | class _TimeoutGarbageCollector:
    method __init__ (line 37) | def __init__(self) -> None:
    method _garbage_collect (line 41) | def _garbage_collect(self) -> None:
  class Condition (line 49) | class Condition(_TimeoutGarbageCollector):
    method __repr__ (line 109) | def __repr__(self) -> str:
    method wait (line 115) | def wait(
    method notify (line 137) | def notify(self, n: int = 1) -> None:
    method notify_all (line 149) | def notify_all(self) -> None:
  class Event (line 154) | class Event:
    method __init__ (line 194) | def __init__(self) -> None:
    method __repr__ (line 198) | def __repr__(self) -> str:
    method is_set (line 204) | def is_set(self) -> bool:
    method set (line 208) | def set(self) -> None:
    method clear (line 220) | def clear(self) -> None:
    method wait (line 227) | def wait(
  class _ReleasingContextManager (line 254) | class _ReleasingContextManager:
    method __init__ (line 263) | def __init__(self, obj: Any) -> None:
    method __enter__ (line 266) | def __enter__(self) -> None:
    method __exit__ (line 269) | def __exit__(
  class Semaphore (line 278) | class Semaphore(_TimeoutGarbageCollector):
    method __init__ (line 379) | def __init__(self, value: int = 1) -> None:
    method __repr__ (line 386) | def __repr__(self) -> str:
    method release (line 393) | def release(self) -> None:
    method acquire (line 410) | def acquire(
    method __enter__ (line 438) | def __enter__(self) -> None:
    method __exit__ (line 441) | def __exit__(
    method __aenter__ (line 449) | async def __aenter__(self) -> None:
    method __aexit__ (line 452) | async def __aexit__(
  class BoundedSemaphore (line 461) | class BoundedSemaphore(Semaphore):
    method __init__ (line 470) | def __init__(self, value: int = 1) -> None:
    method release (line 474) | def release(self) -> None:
  class Lock (line 481) | class Lock:
    method __init__ (line 518) | def __init__(self) -> None:
    method __repr__ (line 521) | def __repr__(self) -> str:
    method acquire (line 524) | def acquire(
    method release (line 534) | def release(self) -> None:
    method __enter__ (line 546) | def __enter__(self) -> None:
    method __exit__ (line 549) | def __exit__(
    method __aenter__ (line 557) | async def __aenter__(self) -> None:
    method __aexit__ (line 560) | async def __aexit__(

FILE: tornado/log.py
  function _stderr_supports_color (line 56) | def _stderr_supports_color() -> bool:
  function _safe_unicode (line 75) | def _safe_unicode(s: Any) -> str:
  class LogFormatter (line 82) | class LogFormatter(logging.Formatter):
    method __init__ (line 117) | def __init__(
    method format (line 169) | def format(self, record: Any) -> str:
  function enable_pretty_logging (line 216) | def enable_pretty_logging(
  function define_logging_options (line 266) | def define_logging_options(options: Any = None) -> None:

FILE: tornado/netutil.py
  function bind_sockets (line 56) | def bind_sockets(
  function bind_unix_socket (line 192) | def bind_unix_socket(
  function add_accept_handler (line 233) | def add_accept_handler(
  function is_valid_ip (line 293) | def is_valid_ip(ip: str) -> bool:
  class Resolver (line 320) | class Resolver(Configurable):
    method configurable_base (line 349) | def configurable_base(cls) -> type["Resolver"]:
    method configurable_default (line 353) | def configurable_default(cls) -> type["Resolver"]:
    method resolve (line 356) | def resolve(
    method close (line 382) | def close(self) -> None:
  function _resolve_addr (line 391) | def _resolve_addr(
  class DefaultExecutorResolver (line 406) | class DefaultExecutorResolver(Resolver):
    method resolve (line 416) | async def resolve(
  class DefaultLoopResolver (line 425) | class DefaultLoopResolver(Resolver):
    method resolve (line 428) | async def resolve(
  class ExecutorResolver (line 444) | class ExecutorResolver(Resolver):
    method initialize (line 462) | def initialize(
    method close (line 474) | def close(self) -> None:
    method resolve (line 480) | def resolve(
  class BlockingResolver (line 486) | class BlockingResolver(ExecutorResolver):
    method initialize (line 497) | def initialize(self) -> None:  # type: ignore
  class ThreadedResolver (line 501) | class ThreadedResolver(ExecutorResolver):
    method initialize (line 521) | def initialize(self, num_threads: int = 10) -> None:  # type: ignore
    method _create_threadpool (line 526) | def _create_threadpool(
  class OverrideResolver (line 540) | class OverrideResolver(Resolver):
    method initialize (line 563) | def initialize(self, resolver: Resolver, mapping: dict) -> None:
    method close (line 567) | def close(self) -> None:
    method resolve (line 570) | def resolve(
  function ssl_options_to_context (line 590) | def ssl_options_to_context(
  function ssl_wrap_socket (line 643) | def ssl_wrap_socket(

FILE: tornado/options.py
  class Error (line 119) | class Error(Exception):
  class OptionParser (line 125) | class OptionParser:
    method __init__ (line 132) | def __init__(self) -> None:
    method _normalize_name (line 143) | def _normalize_name(self, name: str) -> str:
    method __getattr__ (line 146) | def __getattr__(self, name: str) -> Any:
    method __setattr__ (line 152) | def __setattr__(self, name: str, value: Any) -> None:
    method __iter__ (line 158) | def __iter__(self) -> Iterator:
    method __contains__ (line 161) | def __contains__(self, name: str) -> bool:
    method __getitem__ (line 165) | def __getitem__(self, name: str) -> Any:
    method __setitem__ (line 168) | def __setitem__(self, name: str, value: Any) -> None:
    method items (line 171) | def items(self) -> Iterable[tuple[str, Any]]:
    method groups (line 178) | def groups(self) -> set[str]:
    method group_dict (line 185) | def group_dict(self, group: str) -> dict[str, Any]:
    method as_dict (line 208) | def as_dict(self) -> dict[str, Any]:
    method define (line 215) | def define(
    method parse_command_line (line 307) | def parse_command_line(
    method parse_config_file (line 361) | def parse_config_file(self, path: str, final: bool = True) -> None:
    method print_help (line 432) | def print_help(self, file: TextIO | None = None) -> None:
    method _help_callback (line 462) | def _help_callback(self, value: bool) -> None:
    method add_parse_callback (line 467) | def add_parse_callback(self, callback: Callable[[], None]) -> None:
    method run_parse_callbacks (line 471) | def run_parse_callbacks(self) -> None:
    method mockable (line 475) | def mockable(self) -> "_Mockable":
  class _Mockable (line 489) | class _Mockable:
    method __init__ (line 502) | def __init__(self, options: OptionParser) -> None:
    method __getattr__ (line 507) | def __getattr__(self, name: str) -> Any:
    method __setattr__ (line 510) | def __setattr__(self, name: str, value: Any) -> None:
    method __delattr__ (line 515) | def __delattr__(self, name: str) -> None:
  class _Option (line 519) | class _Option:
    method __init__ (line 525) | def __init__(
    method value (line 552) | def value(self) -> Any:
    method parse (line 555) | def parse(self, value: str) -> Any:
    method set (line 579) | def set(self, value: Any) -> None:
    method _parse_datetime (line 616) | def _parse_datetime(self, value: str) -> datetime.datetime:
    method _parse_timedelta (line 642) | def _parse_timedelta(self, value: str) -> datetime.timedelta:
    method _parse_bool (line 660) | def _parse_bool(self, value: str) -> bool:
    method _parse_string (line 663) | def _parse_string(self, value: str) -> str:
  function define (line 674) | def define(
  function parse_command_line (line 700) | def parse_command_line(args: list[str] | None = None, final: bool = True...
  function parse_config_file (line 708) | def parse_config_file(path: str, final: bool = True) -> None:
  function print_help (line 716) | def print_help(file: TextIO | None = None) -> None:
  function add_parse_callback (line 724) | def add_parse_callback(callback: Callable[[], None]) -> None:

FILE: tornado/platform/asyncio.py
  class _HasFileno (line 52) | class _HasFileno(Protocol):
    method fileno (line 53) | def fileno(self) -> int:
  function _atexit_callback (line 68) | def _atexit_callback() -> None:
  class BaseAsyncIOLoop (line 89) | class BaseAsyncIOLoop(IOLoop):
    method initialize (line 90) | def initialize(  # type: ignore
    method close (line 139) | def close(self, all_fds: bool = False) -> None:
    method add_handler (line 156) | def add_handler(
    method update_handler (line 170) | def update_handler(self, fd: int | _Selectable, events: int) -> None:
    method remove_handler (line 189) | def remove_handler(self, fd: int | _Selectable) -> None:
    method _handle_events (line 201) | def _handle_events(self, fd: int, events: int) -> None:
    method start (line 205) | def start(self) -> None:
    method stop (line 208) | def stop(self) -> None:
    method call_at (line 211) | def call_at(
    method remove_timeout (line 223) | def remove_timeout(self, timeout: object) -> None:
    method add_callback (line 226) | def add_callback(self, callback: Callable, *args: Any, **kwargs: Any) ...
    method add_callback_from_signal (line 250) | def add_callback_from_signal(
    method run_in_executor (line 261) | def run_in_executor(
    method set_default_executor (line 269) | def set_default_executor(self, executor: concurrent.futures.Executor) ...
  class AsyncIOMainLoop (line 273) | class AsyncIOMainLoop(BaseAsyncIOLoop):
    method initialize (line 288) | def initialize(self, **kwargs: Any) -> None:  # type: ignore
    method _make_current (line 291) | def _make_current(self) -> None:
  class AsyncIOLoop (line 297) | class AsyncIOLoop(BaseAsyncIOLoop):
    method initialize (line 323) | def initialize(self, **kwargs: Any) -> None:  # type: ignore
    method close (line 337) | def close(self, all_fds: bool = False) -> None:
    method _make_current (line 342) | def _make_current(self) -> None:
    method _clear_current_hook (line 351) | def _clear_current_hook(self) -> None:
  function to_tornado_future (line 357) | def to_tornado_future(asyncio_future: asyncio.Future) -> asyncio.Future:
  function to_asyncio_future (line 369) | def to_asyncio_future(tornado_future: asyncio.Future) -> asyncio.Future:
  function __getattr__ (line 388) | def __getattr__(name: str) -> typing.Any:
  class SelectorThread (line 457) | class SelectorThread:
    method __init__ (line 470) | def __init__(self, real_loop: asyncio.AbstractEventLoop) -> None:
    method close (line 507) | def close(self) -> None:
    method _thread_manager (line 522) | async def _thread_manager(self) -> typing.AsyncGenerator[None, None]:
    method _wake_selector (line 547) | def _wake_selector(self) -> None:
    method _consume_waker (line 555) | def _consume_waker(self) -> None:
    method _start_select (line 561) | def _start_select(self) -> None:
    method _run_select (line 570) | def _run_select(self) -> None:
    method _handle_select (line 636) | def _handle_select(
    method _handle_event (line 645) | def _handle_event(
    method add_reader (line 656) | def add_reader(
    method add_writer (line 662) | def add_writer(
    method remove_reader (line 668) | def remove_reader(self, fd: _FileDescriptorLike) -> bool:
    method remove_writer (line 676) | def remove_writer(self, fd: _FileDescriptorLike) -> bool:
  class AddThreadSelectorEventLoop (line 685) | class AddThreadSelectorEventLoop(asyncio.AbstractEventLoop):
    method __getattribute__ (line 715) | def __getattribute__(self, name: str) -> Any:
    method __init__ (line 720) | def __init__(self, real_loop: asyncio.AbstractEventLoop) -> None:
    method close (line 724) | def close(self) -> None:
    method add_reader (line 728) | def add_reader(
    method add_writer (line 736) | def add_writer(
    method remove_reader (line 744) | def remove_reader(self, fd: "_FileDescriptorLike") -> bool:
    method remove_writer (line 747) | def remove_writer(self, fd: "_FileDescriptorLike") -> bool:

FILE: tornado/platform/caresresolver.py
  class CaresResolver (line 14) | class CaresResolver(Resolver):
    method initialize (line 35) | def initialize(self) -> None:
    method _sock_state_cb (line 40) | def _sock_state_cb(self, fd: int, readable: bool, writable: bool) -> N...
    method _handle_events (line 52) | def _handle_events(self, fd: int, events: int) -> None:
    method resolve (line 62) | def resolve(

FILE: tornado/platform/twisted.py
  function install (line 24) | def install() -> None:
  function _ (line 51) | def _(d: Deferred) -> Future:

FILE: tornado/process.py
  function cpu_count (line 44) | def cpu_count() -> int:
  function _reseed_random (line 60) | def _reseed_random() -> None:
  function fork_processes (line 78) | def fork_processes(num_processes: int | None, max_restarts: int | None =...
  function task_id (line 171) | def task_id() -> int | None:
  class Subprocess (line 179) | class Subprocess:
    method __init__ (line 206) | def __init__(self, *args: Any, **kwargs: Any) -> None:
    method set_exit_callback (line 245) | def set_exit_callback(self, callback: Callable[[int], None]) -> None:
    method wait_for_exit (line 267) | def wait_for_exit(self, raise_error: bool = True) -> "Future[int]":
    method initialize (line 300) | def initialize(cls) -> None:
    method uninitialize (line 321) | def uninitialize(cls) -> None:
    method _cleanup (line 330) | def _cleanup(cls) -> None:
    method _try_cleanup_process (line 335) | def _try_cleanup_process(cls, pid: int) -> None:
    method _set_returncode (line 346) | def _set_returncode(self, status: int) -> None:

FILE: tornado/queues.py
  class QueueEmpty (line 45) | class QueueEmpty(Exception):
  class QueueFull (line 51) | class QueueFull(Exception):
  function _set_timeout (line 57) | def _set_timeout(future: Future, timeout: None | float | datetime.timede...
  class _QueueIterator (line 69) | class _QueueIterator(Generic[_T]):
    method __init__ (line 70) | def __init__(self, q: Queue[_T]) -> None:
    method __anext__ (line 73) | def __anext__(self) -> Awaitable[_T]:
  class Queue (line 77) | class Queue(Generic[_T]):
    method __init__ (line 149) | def __init__(self, maxsize: int = 0) -> None:
    method maxsize (line 167) | def maxsize(self) -> int:
    method qsize (line 171) | def qsize(self) -> int:
    method empty (line 175) | def empty(self) -> bool:
    method full (line 178) | def full(self) -> bool:
    method put (line 184) | def put(
    method put_nowait (line 207) | def put_nowait(self, item: _T) -> None:
    method get (line 223) | def get(self, timeout: float | datetime.timedelta | None = None) -> Aw...
    method get_nowait (line 252) | def get_nowait(self) -> _T:
    method task_done (line 270) | def task_done(self) -> None:
    method join (line 288) | def join(
    method __aiter__ (line 298) | def __aiter__(self) -> _QueueIterator[_T]:
    method _init (line 302) | def _init(self) -> None:
    method _get (line 305) | def _get(self) -> _T:
    method _put (line 308) | def _put(self, item: _T) -> None:
    method __put_internal (line 313) | def __put_internal(self, item: _T) -> None:
    method _consume_expired (line 318) | def _consume_expired(self) -> None:
    method __repr__ (line 326) | def __repr__(self) -> str:
    method __str__ (line 329) | def __str__(self) -> str:
    method _format (line 332) | def _format(self) -> str:
  class PriorityQueue (line 345) | class PriorityQueue(Queue):
    method _init (line 374) | def _init(self) -> None:
    method _put (line 377) | def _put(self, item: _T) -> None:
    method _get (line 380) | def _get(self) -> _T:  # type: ignore[type-var]
  class LifoQueue (line 384) | class LifoQueue(Queue):
    method _init (line 411) | def _init(self) -> None:
    method _put (line 414) | def _put(self, item: _T) -> None:
    method _get (line 417) | def _get(self) -> _T:  # type: ignore[type-var]

FILE: tornado/routing.py
  class Router (line 195) | class Router(httputil.HTTPServerConnectionDelegate):
    method find_handler (line 198) | def find_handler(
    method start_request (line 212) | def start_request(
  class ReversibleRouter (line 218) | class ReversibleRouter(Router):
    method reverse_url (line 223) | def reverse_url(self, name: str, *args: Any) -> str | None:
  class _RoutingDelegate (line 234) | class _RoutingDelegate(httputil.HTTPMessageDelegate):
    method __init__ (line 235) | def __init__(
    method headers_received (line 243) | def headers_received(
    method data_received (line 267) | def data_received(self, chunk: bytes) -> Awaitable[None] | None:
    method finish (line 271) | def finish(self) -> None:
    method on_connection_close (line 275) | def on_connection_close(self) -> None:
  class _DefaultMessageDelegate (line 280) | class _DefaultMessageDelegate(httputil.HTTPMessageDelegate):
    method __init__ (line 281) | def __init__(self, connection: httputil.HTTPConnection) -> None:
    method finish (line 284) | def finish(self) -> None:
  class RuleRouter (line 305) | class RuleRouter(Router):
    method __init__ (line 308) | def __init__(self, rules: _RuleList | None = None) -> None:
    method add_rules (line 339) | def add_rules(self, rules: _RuleList) -> None:
    method process_rule (line 355) | def process_rule(self, rule: "Rule") -> "Rule":
    method find_handler (line 363) | def find_handler(
    method get_target_delegate (line 381) | def get_target_delegate(
  class ReversibleRuleRouter (line 409) | class ReversibleRuleRouter(ReversibleRouter, RuleRouter):
    method __init__ (line 417) | def __init__(self, rules: _RuleList | None = None) -> None:
    method process_rule (line 421) | def process_rule(self, rule: "Rule") -> "Rule":
    method reverse_url (line 433) | def reverse_url(self, name: str, *args: Any) -> str | None:
  class Rule (line 446) | class Rule:
    method __init__ (line 449) | def __init__(
    method reverse (line 482) | def reverse(self, *args: Any) -> str | None:
    method __repr__ (line 485) | def __repr__(self) -> str:
  class Matcher (line 495) | class Matcher:
    method match (line 498) | def match(self, request: httputil.HTTPServerRequest) -> dict[str, Any]...
    method reverse (line 510) | def reverse(self, *args: Any) -> str | None:
  class AnyMatches (line 515) | class AnyMatches(Matcher):
    method match (line 518) | def match(self, request: httputil.HTTPServerRequest) -> dict[str, Any]...
  class HostMatches (line 522) | class HostMatches(Matcher):
    method __init__ (line 525) | def __init__(self, host_pattern: str | Pattern) -> None:
    method match (line 533) | def match(self, request: httputil.HTTPServerRequest) -> dict[str, Any]...
  class DefaultHostMatches (line 540) | class DefaultHostMatches(Matcher):
    method __init__ (line 545) | def __init__(self, application: Any, host_pattern: Pattern) -> None:
    method match (line 549) | def match(self, request: httputil.HTTPServerRequest) -> dict[str, Any]...
  class PathMatches (line 557) | class PathMatches(Matcher):
    method __init__ (line 560) | def __init__(self, path_pattern: str | Pattern) -> None:
    method match (line 575) | def match(self, request: httputil.HTTPServerRequest) -> dict[str, Any]...
    method reverse (line 598) | def reverse(self, *args: Any) -> str | None:
    method _find_groups (line 613) | def _find_groups(self) -> tuple[str | None, int | None]:
  class URLSpec (line 654) | class URLSpec(Rule):
    method __init__ (line 662) | def __init__(
    method __repr__ (line 693) | def __repr__(self) -> str:
  function _unquote_or_none (line 704) | def _unquote_or_none(s: str) -> bytes:
  function _unquote_or_none (line 709) | def _unquote_or_none(s: None) -> None:
  function _unquote_or_none (line 713) | def _unquote_or_none(s: str | None) -> bytes | None:

FILE: tornado/simple_httpclient.py
  class HTTPTimeoutError (line 39) | class HTTPTimeoutError(HTTPError):
    method __init__ (line 48) | def __init__(self, message: str) -> None:
    method __str__ (line 51) | def __str__(self) -> str:
  class HTTPStreamClosedError (line 55) | class HTTPStreamClosedError(HTTPError):
    method __init__ (line 67) | def __init__(self, message: str) -> None:
    method __str__ (line 70) | def __str__(self) -> str:
  class SimpleAsyncHTTPClient (line 74) | class SimpleAsyncHTTPClient(AsyncHTTPClient):
    method initialize (line 113) | def initialize(  # type: ignore
    method close (line 151) | def close(self) -> None:
    method fetch_impl (line 157) | def fetch_impl(
    method _process_queue (line 184) | def _process_queue(self) -> None:
    method _connection_class (line 194) | def _connection_class(self) -> type:
    method _handle_request (line 197) | def _handle_request(
    method _release_fetch (line 214) | def _release_fetch(self, key: object) -> None:
    method _remove_timeout (line 218) | def _remove_timeout(self, key: object) -> None:
    method _on_timeout (line 225) | def _on_timeout(self, key: object, info: str | None = None) -> None:
  class _HTTPConnection (line 247) | class _HTTPConnection(httputil.HTTPMessageDelegate):
    method __init__ (line 250) | def __init__(
    method run (line 283) | async def run(self) -> None:
    method _get_ssl_options (line 444) | def _get_ssl_options(self, scheme: str) -> None | dict[str, Any] | ssl...
    method _on_timeout (line 473) | def _on_timeout(self, info: str | None = None) -> None:
    method _remove_timeout (line 487) | def _remove_timeout(self) -> None:
    method _create_connection (line 492) | def _create_connection(self, stream: IOStream) -> HTTP1Connection:
    method _write_body (line 507) | async def _write_body(self, start_read: bool) -> None:
    method _release (line 522) | def _release(self) -> None:
    method _run_callback (line 528) | def _run_callback(self, response: HTTPResponse) -> None:
    method _handle_exception (line 535) | def _handle_exception(
    method on_connection_close (line 571) | def on_connection_close(self) -> None:
    method headers_received (line 581) | async def headers_received(
    method _should_follow_redirect (line 604) | def _should_follow_redirect(self) -> bool:
    method finish (line 615) | def finish(self) -> None:
    method _on_end_request (line 680) | def _on_end_request(self) -> None:
    method data_received (line 683) | def data_received(self, chunk: bytes) -> Awaitable[None] | None:

FILE: tornado/speedups.c
  function PyObject (line 5) | static PyObject* websocket_mask(PyObject* self, PyObject* args) {
  function speedups_exec (line 54) | static int speedups_exec(PyObject *module) {
  type PyModuleDef (line 74) | struct PyModuleDef
  function PyMODINIT_FUNC (line 83) | PyMODINIT_FUNC

FILE: tornado/speedups.pyi
  function websocket_mask (line 1) | def websocket_mask(mask: bytes, data: bytes) -> bytes: ...

FILE: tornado/tcpclient.py
  class _Connector (line 36) | class _Connector:
    method __init__ (line 54) | def __init__(
    method split (line 73) | def split(
    method start (line 97) | def start(
    method try_connect (line 108) | def try_connect(self, addrs: Iterator[tuple[socket.AddressFamily, tupl...
    method on_connect_done (line 126) | def on_connect_done(
    method set_timeout (line 158) | def set_timeout(self, timeout: float) -> None:
    method on_timeout (line 163) | def on_timeout(self) -> None:
    method clear_timeout (line 168) | def clear_timeout(self) -> None:
    method set_connect_timeout (line 172) | def set_connect_timeout(self, connect_timeout: float | datetime.timede...
    method on_connect_timeout (line 177) | def on_connect_timeout(self) -> None:
    method clear_timeouts (line 182) | def clear_timeouts(self) -> None:
    method close_streams (line 188) | def close_streams(self) -> None:
  class TCPClient (line 193) | class TCPClient:
    method __init__ (line 200) | def __init__(self, resolver: Resolver | None = None) -> None:
    method close (line 208) | def close(self) -> None:
    method connect (line 212) | async def connect(
    method _create_stream (line 288) | def _create_stream(

FILE: tornado/tcpserver.py
  class TCPServer (line 38) | class TCPServer:
    method __init__ (line 119) | def __init__(
    method listen (line 154) | def listen(
    method add_sockets (line 188) | def add_sockets(self, sockets: Iterable[socket.socket]) -> None:
    method add_socket (line 203) | def add_socket(self, socket: socket.socket) -> None:
    method bind (line 207) | def bind(
    method start (line 259) | def start(
    method stop (line 301) | def stop(self) -> None:
    method handle_stream (line 316) | def handle_stream(self, stream: IOStream, address: tuple) -> Awaitable...
    method _handle_connection (line 333) | def _handle_connection(self, connection: socket.socket, address: Any) ...

FILE: tornado/template.py
  class _UnsetMarker (line 217) | class _UnsetMarker:
  function filter_whitespace (line 224) | def filter_whitespace(mode: str, text: str) -> str:
  class Template (line 249) | class Template:
    method __init__ (line 259) | def __init__(
    method generate (line 334) | def generate(self, **kwargs: Any) -> bytes:
    method _generate_python (line 361) | def _generate_python(self, loader: Optional["BaseLoader"]) -> str:
    method _get_ancestors (line 376) | def _get_ancestors(self, loader: Optional["BaseLoader"]) -> list["_Fil...
  class BaseLoader (line 389) | class BaseLoader:
    method __init__ (line 397) | def __init__(
    method reset (line 429) | def reset(self) -> None:
    method resolve_path (line 434) | def resolve_path(self, name: str, parent_path: str | None = None) -> str:
    method load (line 438) | def load(self, name: str, parent_path: str | None = None) -> Template:
    method _create_template (line 446) | def _create_template(self, name: str) -> Template:
  class Loader (line 450) | class Loader(BaseLoader):
    method __init__ (line 453) | def __init__(self, root_directory: str, **kwargs: Any) -> None:
    method resolve_path (line 457) | def resolve_path(self, name: str, parent_path: str | None = None) -> str:
    method _create_template (line 471) | def _create_template(self, name: str) -> Template:
  class DictLoader (line 478) | class DictLoader(BaseLoader):
    method __init__ (line 481) | def __init__(self, dict: dict[str, str], **kwargs: Any) -> None:
    method resolve_path (line 485) | def resolve_path(self, name: str, parent_path: str | None = None) -> str:
    method _create_template (line 496) | def _create_template(self, name: str) -> Template:
  class _Node (line 500) | class _Node:
    method each_child (line 501) | def each_child(self) -> Iterable["_Node"]:
    method generate (line 504) | def generate(self, writer: "_CodeWriter") -> None:
    method find_named_blocks (line 507) | def find_named_blocks(
  class _File (line 514) | class _File(_Node):
    method __init__ (line 515) | def __init__(self, template: Template, body: "_ChunkList") -> None:
    method generate (line 520) | def generate(self, writer: "_CodeWriter") -> None:
    method each_child (line 528) | def each_child(self) -> Iterable["_Node"]:
  class _ChunkList (line 532) | class _ChunkList(_Node):
    method __init__ (line 533) | def __init__(self, chunks: list[_Node]) -> None:
    method generate (line 536) | def generate(self, writer: "_CodeWriter") -> None:
    method each_child (line 540) | def each_child(self) -> Iterable["_Node"]:
  class _NamedBlock (line 544) | class _NamedBlock(_Node):
    method __init__ (line 545) | def __init__(self, name: str, body: _Node, template: Template, line: i...
    method each_child (line 551) | def each_child(self) -> Iterable["_Node"]:
    method generate (line 554) | def generate(self, writer: "_CodeWriter") -> None:
    method find_named_blocks (line 559) | def find_named_blocks(
  class _ExtendsBlock (line 566) | class _ExtendsBlock(_Node):
    method __init__ (line 567) | def __init__(self, name: str) -> None:
  class _IncludeBlock (line 571) | class _IncludeBlock(_Node):
    method __init__ (line 572) | def __init__(self, name: str, reader: "_TemplateReader", line: int) ->...
    method find_named_blocks (line 577) | def find_named_blocks(
    method generate (line 584) | def generate(self, writer: "_CodeWriter") -> None:
  class _ApplyBlock (line 591) | class _ApplyBlock(_Node):
    method __init__ (line 592) | def __init__(self, method: str, line: int, body: _Node) -> None:
    method each_child (line 597) | def each_child(self) -> Iterable["_Node"]:
    method generate (line 600) | def generate(self, writer: "_CodeWriter") -> None:
  class _ControlBlock (line 614) | class _ControlBlock(_Node):
    method __init__ (line 615) | def __init__(self, statement: str, line: int, body: _Node) -> None:
    method each_child (line 620) | def each_child(self) -> Iterable[_Node]:
    method generate (line 623) | def generate(self, writer: "_CodeWriter") -> None:
  class _IntermediateControlBlock (line 631) | class _IntermediateControlBlock(_Node):
    method __init__ (line 632) | def __init__(self, statement: str, line: int) -> None:
    method generate (line 636) | def generate(self, writer: "_CodeWriter") -> None:
  class _Statement (line 642) | class _Statement(_Node):
    method __init__ (line 643) | def __init__(self, statement: str, line: int) -> None:
    method generate (line 647) | def generate(self, writer: "_CodeWriter") -> None:
  class _Expression (line 651) | class _Expression(_Node):
    method __init__ (line 652) | def __init__(self, expression: str, line: int, raw: bool = False) -> N...
    method generate (line 657) | def generate(self, writer: "_CodeWriter") -> None:
  class _Module (line 674) | class _Module(_Expression):
    method __init__ (line 675) | def __init__(self, expression: str, line: int) -> None:
  class _Text (line 679) | class _Text(_Node):
    method __init__ (line 680) | def __init__(self, value: str, line: int, whitespace: str) -> None:
    method generate (line 685) | def generate(self, writer: "_CodeWriter") -> None:
  class ParseError (line 697) | class ParseError(Exception):
    method __init__ (line 707) | def __init__(
    method __str__ (line 716) | def __str__(self) -> str:
  class _CodeWriter (line 720) | class _CodeWriter:
    method __init__ (line 721) | def __init__(
    method indent_size (line 736) | def indent_size(self) -> int:
    method indent (line 739) | def indent(self) -> "ContextManager":
    method include (line 751) | def include(self, template: Template, line: int) -> "ContextManager":
    method write_line (line 764) | def write_line(
  class _TemplateReader (line 778) | class _TemplateReader:
    method __init__ (line 779) | def __init__(self, name: str, text: str, whitespace: str) -> None:
    method find (line 786) | def find(self, needle: str, start: int = 0, end: int | None = None) ->...
    method consume (line 800) | def consume(self, count: int | None = None) -> str:
    method remaining (line 809) | def remaining(self) -> int:
    method __len__ (line 812) | def __len__(self) -> int:
    method __getitem__ (line 815) | def __getitem__(self, key: int | slice) -> str:
    method __str__ (line 831) | def __str__(self) -> str:
    method raise_parse_error (line 834) | def raise_parse_error(self, msg: str) -> None:
  function _format_code (line 838) | def _format_code(code: str) -> str:
  function _parse (line 844) | def _parse(

FILE: tornado/test/asyncio_test.py
  class AsyncIOLoopTest (line 39) | class AsyncIOLoopTest(AsyncTestCase):
    method asyncio_loop (line 41) | def asyncio_loop(self):
    method test_asyncio_callback (line 44) | def test_asyncio_callback(self):
    method test_asyncio_future (line 53) | def test_asyncio_future(self):
    method test_asyncio_yield_from (line 62) | def test_asyncio_yield_from(self):
    method test_asyncio_adapter (line 72) | def test_asyncio_adapter(self):
    method test_add_thread_close_idempotent (line 112) | def test_add_thread_close_idempotent(self):
  class LeakTest (line 118) | class LeakTest(unittest.TestCase):
    method setUp (line 119) | def setUp(self):
    method tearDown (line 123) | def tearDown(self):
    method test_ioloop_close_leak (line 132) | def test_ioloop_close_leak(self):
    method test_asyncio_close_leak (line 143) | def test_asyncio_close_leak(self):
  class SelectorThreadLeakTest (line 158) | class SelectorThreadLeakTest(unittest.TestCase):
    method setUp (line 160) | def setUp(self):
    method assert_no_thread_leak (line 166) | def assert_no_thread_leak(self):
    method dummy_tornado_coroutine (line 180) | async def dummy_tornado_coroutine(self):
    method test_asyncio_run (line 184) | def test_asyncio_run(self):
    method test_asyncio_manual (line 190) | def test_asyncio_manual(self):
    method test_tornado (line 199) | def test_tornado(self):
  class AnyThreadEventLoopPolicyTest (line 209) | class AnyThreadEventLoopPolicyTest(unittest.TestCase):
    method setUp (line 210) | def setUp(self):
    method tearDown (line 220) | def tearDown(self):
    method get_event_loop_on_thread (line 224) | def get_event_loop_on_thread(self):
    method test_asyncio_accessor (line 240) | def test_asyncio_accessor(self):
    method test_tornado_accessor (line 258) | def test_tornado_accessor(self):
  class SelectorThreadContextvarsTest (line 273) | class SelectorThreadContextvarsTest(AsyncHTTPTestCase):
    method get_app (line 279) | def get_app(self) -> Application:
    method test_context_vars (line 297) | def test_context_vars(self):

FILE: tornado/test/auth_test.py
  class OpenIdClientLoginHandler (line 25) | class OpenIdClientLoginHandler(RequestHandler, OpenIdMixin):
    method initialize (line 26) | def initialize(self, test):
    method get (line 30) | def get(self):
  class OpenIdServerAuthenticateHandler (line 43) | class OpenIdServerAuthenticateHandler(RequestHandler):
    method post (line 44) | def post(self):
  class OAuth1ClientLoginHandler (line 50) | class OAuth1ClientLoginHandler(RequestHandler, OAuthMixin):
    method initialize (line 51) | def initialize(self, test, version):
    method _oauth_consumer_token (line 57) | def _oauth_consumer_token(self):
    method get (line 61) | def get(self):
    method _oauth_get_user_future (line 73) | def _oauth_get_user_future(self, access_token):
  class OAuth1ClientLoginCoroutineHandler (line 81) | class OAuth1ClientLoginCoroutineHandler(OAuth1ClientLoginHandler):
    method get (line 85) | def get(self):
  class OAuth1ClientRequestParametersHandler (line 98) | class OAuth1ClientRequestParametersHandler(RequestHandler, OAuthMixin):
    method initialize (line 99) | def initialize(self, version):
    method _oauth_consumer_token (line 102) | def _oauth_consumer_token(self):
    method get (line 105) | def get(self):
  class OAuth1ServerRequestTokenHandler (line 114) | class OAuth1ServerRequestTokenHandler(RequestHandler):
    method get (line 115) | def get(self):
  class OAuth1ServerAccessTokenHandler (line 119) | class OAuth1ServerAccessTokenHandler(RequestHandler):
    method get (line 120) | def get(self):
  class OAuth2ClientLoginHandler (line 124) | class OAuth2ClientLoginHandler(RequestHandler, OAuth2Mixin):
    method initialize (line 125) | def initialize(self, test):
    method get (line 128) | def get(self):
  class FacebookClientLoginHandler (line 133) | class FacebookClientLoginHandler(RequestHandler, FacebookGraphMixin):
    method initialize (line 134) | def initialize(self, test):
    method get (line 140) | def get(self):
  class FacebookServerAccessTokenHandler (line 157) | class FacebookServerAccessTokenHandler(RequestHandler):
    method get (line 158) | def get(self):
  class FacebookServerMeHandler (line 162) | class FacebookServerMeHandler(RequestHandler):
    method get (line 163) | def get(self):
  class TwitterClientHandler (line 167) | class TwitterClientHandler(RequestHandler, TwitterMixin):
    method initialize (line 168) | def initialize(self, test):
    method get_auth_http_client (line 175) | def get_auth_http_client(self):
  class TwitterClientLoginHandler (line 179) | class TwitterClientLoginHandler(TwitterClientHandler):
    method get (line 181) | def get(self):
  class TwitterClientAuthenticateHandler (line 191) | class TwitterClientAuthenticateHandler(TwitterClientHandler):
    method get (line 195) | def get(self):
  class TwitterClientLoginGenCoroutineHandler (line 205) | class TwitterClientLoginGenCoroutineHandler(TwitterClientHandler):
    method get (line 207) | def get(self):
  class TwitterClientShowUserHandler (line 217) | class TwitterClientShowUserHandler(TwitterClientHandler):
    method get (line 219) | def get(self):
  class TwitterServerAccessTokenHandler (line 236) | class TwitterServerAccessTokenHandler(RequestHandler):
    method get (line 237) | def get(self):
  class TwitterServerShowUserHandler (line 241) | class TwitterServerShowUserHandler(RequestHandler):
    method get (line 242) | def get(self, screen_name):
  class TwitterServerVerifyCredentialsHandler (line 255) | class TwitterServerVerifyCredentialsHandler(RequestHandler):
    method get (line 256) | def get(self):
  class AuthTest (line 267) | class AuthTest(AsyncHTTPTestCase):
    method get_app (line 268) | def get_app(self):
    method test_openid_redirect (line 336) | def test_openid_redirect(self):
    method test_openid_get_user (line 341) | def test_openid_get_user(self):
    method test_oauth10_redirect (line 352) | def test_oauth10_redirect(self):
    method test_oauth10_get_user (line 367) | def test_oauth10_get_user(self):
    method test_oauth10_request_parameters (line 377) | def test_oauth10_request_parameters(self):
    method test_oauth10a_redirect (line 386) | def test_oauth10a_redirect(self):
    method test_oauth10a_redirect_error (line 401) | def test_oauth10a_redirect_error(self):
    method test_oauth10a_get_user (line 408) | def test_oauth10a_get_user(self):
    method test_oauth10a_request_parameters (line 418) | def test_oauth10a_request_parameters(self):
    method test_oauth10a_get_user_coroutine_exception (line 427) | def test_oauth10a_get_user_coroutine_exception(self):
    method test_oauth2_redirect (line 434) | def test_oauth2_redirect(self):
    method test_facebook_login (line 439) | def test_facebook_login(self):
    method base_twitter_redirect (line 451) | def base_twitter_redirect(self, url):
    method test_twitter_redirect (line 467) | def test_twitter_redirect(self):
    method test_twitter_redirect_gen_coroutine (line 470) | def test_twitter_redirect_gen_coroutine(self):
    method test_twitter_authenticate_redirect (line 473) | def test_twitter_authenticate_redirect(self):
    method test_twitter_get_user (line 489) | def test_twitter_get_user(self):
    method test_twitter_show_user (line 510) | def test_twitter_show_user(self):
    method test_twitter_show_user_error (line 517) | def test_twitter_show_user_error(self):
  class GoogleLoginHandler (line 523) | class GoogleLoginHandler(RequestHandler, GoogleOAuth2Mixin):
    method initialize (line 524) | def initialize(self, test):
    method get (line 531) | def get(self):
  class GoogleOAuth2AuthorizeHandler (line 553) | class GoogleOAuth2AuthorizeHandler(RequestHandler):
    method get (line 554) | def get(self):
  class GoogleOAuth2TokenHandler (line 560) | class GoogleOAuth2TokenHandler(RequestHandler):
    method post (line 561) | def post(self):
  class GoogleOAuth2UserinfoHandler (line 569) | class GoogleOAuth2UserinfoHandler(RequestHandler):
    method get (line 570) | def get(self):
  class GoogleOAuth2Test (line 576) | class GoogleOAuth2Test(AsyncHTTPTestCase):
    method get_app (line 577) | def get_app(self):
    method test_google_login (line 593) | def test_google_login(self):

FILE: tornado/test/autoreload_test.py
  class AutoreloadTest (line 12) | class AutoreloadTest(unittest.TestCase):
    method setUp (line 13) | def setUp(self):
    method tearDown (line 41) | def tearDown(self):
    method write_files (line 53) | def write_files(self, tree, base_path=None):
    method run_subprocess (line 69) | def run_subprocess(self, args):
    method test_reload (line 103) | def test_reload(self):
    method test_reload_wrapper_preservation (line 184) | def test_reload_wrapper_preservation(self):
    method test_reload_wrapper_args (line 215) | def test_reload_wrapper_args(self):
    method test_reload_wrapper_until_success (line 244) | def test_reload_wrapper_until_success(self):

FILE: tornado/test/circlerefs_test.py
  function find_circular_references (line 24) | def find_circular_references(garbage):
  function assert_no_cycle_garbage (line 64) | def assert_no_cycle_garbage():
  class CircleRefsTest (line 104) | class CircleRefsTest(unittest.TestCase):
    method test_known_leak (line 105) | def test_known_leak(self):
    method run_handler (line 139) | async def run_handler(self, handler_class):
    method test_sync_handler (line 161) | def test_sync_handler(self):
    method test_finish_exception_handler (line 168) | def test_finish_exception_handler(self):
    method test_coro_handler (line 175) | def test_coro_handler(self):
    method test_async_handler (line 184) | def test_async_handler(self):
    method test_run_on_executor (line 192) | def test_run_on_executor(self):

FILE: tornado/test/concurrent_test.py
  class MiscFutureTest (line 34) | class MiscFutureTest(AsyncTestCase):
    method test_future_set_result_unless_cancelled (line 35) | def test_future_set_result_unless_cancelled(self):
  class ChainFutureTest (line 50) | class ChainFutureTest(AsyncTestCase):
    method test_asyncio_futures (line 52) | async def test_asyncio_futures(self):
    method test_concurrent_futures (line 61) | async def test_concurrent_futures(self):
  class CapServer (line 79) | class CapServer(TCPServer):
    method handle_stream (line 81) | def handle_stream(self, stream, address):
  class CapError (line 92) | class CapError(Exception):
  class BaseCapClient (line 96) | class BaseCapClient:
    method __init__ (line 97) | def __init__(self, port):
    method process_response (line 100) | def process_response(self, data):
  class GeneratorCapClient (line 111) | class GeneratorCapClient(BaseCapClient):
    method capitalize (line 113) | def capitalize(self, request_data):
  class GeneratorCapClientTest (line 126) | class GeneratorCapClientTest(AsyncTestCase):
    method setUp (line 127) | def setUp(self):
    method tearDown (line 134) | def tearDown(self):
    method test_future (line 138) | def test_future(self):
    method test_future_error (line 144) | def test_future_error(self):
    method test_generator (line 150) | def test_generator(self):
    method test_generator_error (line 158) | def test_generator_error(self):
  class RunOnExecutorTest (line 167) | class RunOnExecutorTest(AsyncTestCase):
    method test_no_calling (line 169) | def test_no_calling(self):
    method test_call_with_no_args (line 183) | def test_call_with_no_args(self):
    method test_call_with_executor (line 197) | def test_call_with_executor(self):
    method test_async_await (line 211) | def test_async_await(self):

FILE: tornado/test/curl_httpclient_test.py
  class CurlHTTPClientCommonTestCase (line 20) | class CurlHTTPClientCommonTestCase(httpclient_test.HTTPClientCommonTestC...
    method get_http_client (line 21) | def get_http_client(self):
  class DigestAuthHandler (line 28) | class DigestAuthHandler(RequestHandler):
    method initialize (line 29) | def initialize(self, username, password):
    method get (line 33) | def get(self):
  class CustomReasonHandler (line 69) | class CustomReasonHandler(RequestHandler):
    method get (line 70) | def get(self):
  class CustomFailReasonHandler (line 74) | class CustomFailReasonHandler(RequestHandler):
    method get (line 75) | def get(self):
  class CurlHTTPClientTestCase (line 80) | class CurlHTTPClientTestCase(AsyncHTTPTestCase):
    method setUp (line 81) | def setUp(self):
    method get_app (line 85) | def get_app(self):
    method create_client (line 99) | def create_client(self, **kwargs):
    method test_digest_auth (line 104) | def test_digest_auth(self):
    method test_custom_reason (line 110) | def test_custom_reason(self):
    method test_fail_custom_reason (line 114) | def test_fail_custom_reason(self):
    method test_digest_auth_non_ascii (line 118) | def test_digest_auth_non_ascii(self):
    method test_streaming_callback_not_permitted (line 127) | def test_streaming_callback_not_permitted(self):

FILE: tornado/test/escape_test.py
  class EscapeTestCase (line 213) | class EscapeTestCase(unittest.TestCase):
    method test_linkify (line 214) | def test_linkify(self):
    method test_xhtml_escape (line 219) | def test_xhtml_escape(self):
    method test_xhtml_unescape_numeric (line 233) | def test_xhtml_unescape_numeric(self):
    method test_url_escape_unicode (line 246) | def test_url_escape_unicode(self):
    method test_url_unescape_unicode (line 257) | def test_url_unescape_unicode(self):
    method test_url_escape_quote_plus (line 270) | def test_url_escape_quote_plus(self):
    method test_escape_return_types (line 283) | def test_escape_return_types(self):
    method test_json_decode (line 289) | def test_json_decode(self):
    method test_json_encode (line 298) | def test_json_encode(self):
    method test_squeeze (line 307) | def test_squeeze(self):
    method test_recursive_unicode (line 313) | def test_recursive_unicode(self):

FILE: tornado/test/gen_test.py
  class GenBasicTest (line 20) | class GenBasicTest(AsyncTestCase):
    method delay (line 22) | def delay(self, iterations, arg):
    method async_future (line 29) | def async_future(self, result):
    method async_exception (line 34) | def async_exception(self, e):
    method add_one_async (line 39) | def add_one_async(self, x):
    method test_no_yield (line 43) | def test_no_yield(self):
    method test_exception_phase1 (line 50) | def test_exception_phase1(self):
    method test_exception_phase2 (line 57) | def test_exception_phase2(self):
    method test_bogus_yield (line 65) | def test_bogus_yield(self):
    method test_bogus_yield_tuple (line 72) | def test_bogus_yield_tuple(self):
    method test_reuse (line 79) | def test_reuse(self):
    method test_none (line 87) | def test_none(self):
    method test_multi (line 94) | def test_multi(self):
    method test_multi_dict (line 102) | def test_multi_dict(self):
    method test_multi_delayed (line 110) | def test_multi_delayed(self):
    method test_multi_dict_delayed (line 121) | def test_multi_dict_delayed(self):
    method test_multi_performance (line 133) | def test_multi_performance(self):
    method test_multi_empty (line 143) | def test_multi_empty(self):
    method test_future (line 151) | def test_future(self):
    method test_multi_future (line 156) | def test_multi_future(self):
    method test_multi_future_duplicate (line 161) | def test_multi_future_duplicate(self):
    method test_multi_dict_future (line 169) | def test_multi_dict_future(self):
    method test_multi_exceptions (line 174) | def test_multi_exceptions(self):
    method test_multi_future_exceptions (line 202) | def test_multi_future_exceptions(self):
    method test_sync_raise_return (line 225) | def test_sync_raise_return(self):
    method test_async_raise_return (line 232) | def test_async_raise_return(self):
    method test_sync_raise_return_value (line 240) | def test_sync_raise_return_value(self):
    method test_sync_raise_return_value_tuple (line 247) | def test_sync_raise_return_value_tuple(self):
    method test_async_raise_return_value (line 254) | def test_async_raise_return_value(self):
    method test_async_raise_return_value_tuple (line 262) | def test_async_raise_return_value_tuple(self):
  class GenCoroutineTest (line 271) | class GenCoroutineTest(AsyncTestCase):
    method setUp (line 272) | def setUp(self):
    method tearDown (line 279) | def tearDown(self):
    method test_attributes (line 283) | def test_attributes(self):
    method test_is_coroutine_function (line 294) | def test_is_coroutine_function(self):
    method test_sync_gen_return (line 306) | def test_sync_gen_return(self):
    method test_async_gen_return (line 316) | def test_async_gen_return(self):
    method test_sync_return (line 327) | def test_sync_return(self):
    method test_async_return (line 337) | def test_async_return(self):
    method test_async_early_return (line 348) | def test_async_early_return(self):
    method test_async_await (line 363) | def test_async_await(self):
    method test_asyncio_sleep_zero (line 381) | def test_asyncio_sleep_zero(self):
    method test_async_await_mixed_multi_native_future (line 395) | def test_async_await_mixed_multi_native_future(self):
    method test_async_with_timeout (line 414) | def test_async_with_timeout(self):
    method test_sync_return_no_value (line 423) | def test_sync_return_no_value(self):
    method test_async_return_no_value (line 433) | def test_async_return_no_value(self):
    method test_sync_raise (line 444) | def test_sync_raise(self):
    method test_async_raise (line 458) | def test_async_raise(self):
    method test_replace_yieldpoint_exception (line 470) | def test_replace_yieldpoint_exception(self):
    method test_swallow_yieldpoint_exception (line 490) | def test_swallow_yieldpoint_exception(self):
    method test_moment (line 509) | def test_moment(self):
    method test_sleep (line 536) | def test_sleep(self):
    method test_py3_leak_exception_context (line 541) | def test_py3_leak_exception_context(self):
    method test_coroutine_refcounting (line 564) | def test_coroutine_refcounting(self):
    method test_asyncio_future_debug_info (line 593) | def test_asyncio_future_debug_info(self):
    method test_asyncio_gather (line 612) | def test_asyncio_gather(self):
  class GenCoroutineSequenceHandler (line 625) | class GenCoroutineSequenceHandler(RequestHandler):
    method get (line 627) | def get(self):
  class GenCoroutineUnfinishedSequenceHandler (line 636) | class GenCoroutineUnfinishedSequenceHandler(RequestHandler):
    method get (line 638) | def get(self):
  class UndecoratedCoroutinesHandler (line 649) | class UndecoratedCoroutinesHandler(RequestHandler):
    method prepare (line 651) | def prepare(self):
    method get (line 657) | def get(self):
  class AsyncPrepareErrorHandler (line 665) | class AsyncPrepareErrorHandler(RequestHandler):
    method prepare (line 667) | def prepare(self):
    method get (line 671) | def get(self):
  class NativeCoroutineHandler (line 675) | class NativeCoroutineHandler(RequestHandler):
    method get (line 676) | async def get(self):
  class GenWebTest (line 681) | class GenWebTest(AsyncHTTPTestCase):
    method get_app (line 682) | def get_app(self):
    method test_coroutine_sequence_handler (line 696) | def test_coroutine_sequence_handler(self):
    method test_coroutine_unfinished_sequence_handler (line 700) | def test_coroutine_unfinished_sequence_handler(self):
    method test_undecorated_coroutines (line 704) | def test_undecorated_coroutines(self):
    method test_async_prepare_error_handler (line 708) | def test_async_prepare_error_handler(self):
    method test_native_coroutine_handler (line 712) | def test_native_coroutine_handler(self):
  class WithTimeoutTest (line 718) | class WithTimeoutTest(AsyncTestCase):
    method test_timeout (line 720) | def test_timeout(self):
    method test_completes_before_timeout (line 725) | def test_completes_before_timeout(self):
    method test_fails_before_timeout (line 734) | def test_fails_before_timeout(self):
    method test_already_resolved (line 744) | def test_already_resolved(self):
    method test_timeout_concurrent_future (line 751) | def test_timeout_concurrent_future(self):
    method test_completed_concurrent_future (line 760) | def test_completed_concurrent_future(self):
    method test_normal_concurrent_future (line 773) | def test_normal_concurrent_future(self):
  class WaitIteratorTest (line 782) | class WaitIteratorTest(AsyncTestCase):
    method test_empty_iterator (line 784) | def test_empty_iterator(self):
    method test_already_done (line 795) | def test_already_done(self):
    method finish_coroutines (line 847) | def finish_coroutines(self, iteration, futures):
    method test_iterator (line 860) | def test_iterator(self):
    method test_iterator_async_await (line 886) | def test_iterator_async_await(self):
    method test_no_ref (line 923) | def test_no_ref(self):
  class RunnerGCTest (line 933) | class RunnerGCTest(AsyncTestCase):
    method is_pypy3 (line 934) | def is_pypy3(self):
    method test_gc (line 938) | def test_gc(self):
    method test_gc_infinite_coro (line 956) | def test_gc_infinite_coro(self):
    method test_gc_infinite_async_await (line 992) | def test_gc_infinite_async_await(self):
    method test_multi_moment (line 1028) | def test_multi_moment(self):
  class ContextVarsTest (line 1044) | class ContextVarsTest(AsyncTestCase):
    method native_root (line 1045) | async def native_root(self, x):
    method gen_root (line 1050) | def gen_root(self, x):
    method inner (line 1055) | async def inner(self, x):
    method gen_inner (line 1072) | def gen_inner(self, x):
    method thread_inner (line 1077) | def thread_inner(self, x):
    method test_propagate (line 1081) | def test_propagate(self):
    method test_reset (line 1092) | def test_reset(self):
    method test_propagate_to_first_yield_with_native_async_function (line 1100) | def test_propagate_to_first_yield_with_native_async_function(self):

FILE: tornado/test/http1connection_test.py
  class HTTP1ConnectionTest (line 11) | class HTTP1ConnectionTest(AsyncTestCase):
    method setUp (line 14) | def setUp(self):
    method asyncSetUp (line 19) | def asyncSetUp(self):
    method test_http10_no_content_length (line 36) | def test_http10_no_content_length(self):

FILE: tornado/test/httpclient_test.py
  class HelloWorldHandler (line 34) | class HelloWorldHandler(RequestHandler):
    method get (line 35) | def get(self):
  class PostHandler (line 41) | class PostHandler(RequestHandler):
    method post (line 42) | def post(self):
  class PutHandler (line 49) | class PutHandler(RequestHandler):
    method put (line 50) | def put(self):
  class RedirectHandler (line 55) | class RedirectHandler(RequestHandler):
    method prepare (line 56) | def prepare(self):
  class RedirectWithoutLocationHandler (line 63) | class RedirectWithoutLocationHandler(RequestHandler):
    method prepare (line 64) | def prepare(self):
  class ChunkHandler (line 70) | class ChunkHandler(RequestHandler):
    method get (line 72) | def get(self):
  class AuthHandler (line 80) | class AuthHandler(RequestHandler):
    method get (line 81) | def get(self):
  class CountdownHandler (line 85) | class CountdownHandler(RequestHandler):
    method get (line 86) | def get(self, count):
  class EchoPostHandler (line 94) | class EchoPostHandler(RequestHandler):
    method post (line 95) | def post(self):
  class UserAgentHandler (line 99) | class UserAgentHandler(RequestHandler):
    method get (line 100) | def get(self):
  class ContentLength304Handler (line 104) | class ContentLength304Handler(RequestHandler):
    method get (line 105) | def get(self):
    method _clear_representation_headers (line 109) | def _clear_representation_headers(self):
  class PatchHandler (line 115) | class PatchHandler(RequestHandler):
    method patch (line 116) | def patch(self):
  class AllMethodsHandler (line 121) | class AllMethodsHandler(RequestHandler):
    method method (line 124) | def method(self):
  class SetHeaderHandler (line 131) | class SetHeaderHandler(RequestHandler):
    method get (line 132) | def get(self):
  class InvalidGzipHandler (line 139) | class InvalidGzipHandler(RequestHandler):
    method get (line 140) | def get(self) -> None:
  class HeaderEncodingHandler (line 152) | class HeaderEncodingHandler(RequestHandler):
    method get (line 153) | def get(self):
  class HTTPClientCommonTestCase (line 162) | class HTTPClientCommonTestCase(AsyncHTTPTestCase):
    method get_app (line 163) | def get_app(self):
    method test_patch_receives_payload (line 186) | def test_patch_receives_payload(self):
    method test_hello_world (line 192) | def test_hello_world(self):
    method test_streaming_callback (line 203) | def test_streaming_callback(self):
    method test_post (line 211) | def test_post(self):
    method test_chunked (line 216) | def test_chunked(self):
    method test_chunked_close (line 225) | def test_chunked_close(self):
    method test_basic_auth (line 258) | def test_basic_auth(self):
    method test_basic_auth_explicit_mode (line 267) | def test_basic_auth_explicit_mode(self):
    method test_basic_auth_unicode (line 278) | def test_basic_auth_unicode(self):
    method test_unsupported_auth_mode (line 293) | def test_unsupported_auth_mode(self):
    method test_follow_redirect (line 307) | def test_follow_redirect(self):
    method test_redirect_without_location (line 317) | def test_redirect_without_location(self):
    method test_redirect_put_with_body (line 325) | def test_redirect_put_with_body(self):
    method test_redirect_put_without_body (line 331) | def test_redirect_put_without_body(self):
    method test_method_after_redirect (line 340) | def test_method_after_redirect(self):
    method test_credentials_in_url (line 370) | def test_credentials_in_url(self):
    method test_body_encoding (line 375) | def test_body_encoding(self):
    method test_types (line 411) | def test_types(self):
    method test_gzip (line 418) | def test_gzip(self):
    method test_invalid_gzip (line 435) | def test_invalid_gzip(self):
    method test_header_callback (line 448) | def test_header_callback(self):
    method test_header_callback_to_parse_line (line 479) | def test_header_callback_to_parse_line(self):
    method test_configure_defaults (line 497) | def test_configure_defaults(self):
    method test_header_types (line 507) | def test_header_types(self):
    method test_multi_line_headers (line 524) | def test_multi_line_headers(self):
    method test_header_encoding (line 553) | def test_header_encoding(self):
    method test_304_with_content_length (line 562) | def test_304_with_content_length(self):
    method test_future_interface (line 572) | def test_future_interface(self):
    method test_future_http_error (line 577) | def test_future_http_error(self):
    method test_future_http_error_no_raise (line 586) | def test_future_http_error_no_raise(self):
    method test_reuse_request_from_response (line 593) | def test_reuse_request_from_response(self):
    method test_bind_source_ip (line 606) | def test_bind_source_ip(self):
    method test_all_methods (line 620) | def test_all_methods(self):
    method test_body_sanity_checks (line 634) | def test_body_sanity_checks(self):
    method test_put_307 (line 682) | def test_put_307(self):
    method test_non_ascii_header (line 689) | def test_non_ascii_header(self):
    method test_response_times (line 695) | def test_response_times(self):
    method test_zero_timeout (line 715) | def test_zero_timeout(self):
    method test_error_after_cancel (line 726) | def test_error_after_cancel(self):
    method test_header_crlf (line 739) | def test_header_crlf(self):
  class RequestProxyTest (line 756) | class RequestProxyTest(unittest.TestCase):
    method test_request_set (line 757) | def test_request_set(self):
    method test_default_set (line 763) | def test_default_set(self):
    method test_both_set (line 769) | def test_both_set(self):
    method test_neither_set (line 775) | def test_neither_set(self):
    method test_bad_attribute (line 779) | def test_bad_attribute(self):
    method test_defaults_none (line 784) | def test_defaults_none(self):
  class HTTPResponseTestCase (line 789) | class HTTPResponseTestCase(unittest.TestCase):
    method test_str (line 790) | def test_str(self):
  class SyncHTTPClientTest (line 799) | class SyncHTTPClientTest(unittest.TestCase):
    method setUp (line 800) | def setUp(self):
    method tearDown (line 822) | def tearDown(self):
    method get_url (line 847) | def get_url(self, path):
    method test_sync_client (line 850) | def test_sync_client(self):
    method test_sync_client_error (line 854) | def test_sync_client_error(self):
  class SyncHTTPClientSubprocessTest (line 862) | class SyncHTTPClientSubprocessTest(unittest.TestCase):
    method test_destructor_log (line 863) | def test_destructor_log(self):
  class HTTPRequestTestCase (line 892) | class HTTPRequestTestCase(unittest.TestCase):
    method test_headers (line 893) | def test_headers(self):
    method test_headers_setter (line 897) | def test_headers_setter(self):
    method test_null_headers_setter (line 902) | def test_null_headers_setter(self):
    method test_body (line 907) | def test_body(self):
    method test_body_setter (line 911) | def test_body_setter(self):
    method test_if_modified_since (line 916) | def test_if_modified_since(self):
    method test_if_modified_since_naive_deprecated (line 923) | def test_if_modified_since_naive_deprecated(self):
  class HTTPErrorTestCase (line 932) | class HTTPErrorTestCase(unittest.TestCase):
    method test_copy (line 933) | def test_copy(self):
    method test_plain_error (line 939) | def test_plain_error(self):
    method test_error_with_response (line 944) | def test_error_with_response(self):

FILE: tornado/test/httpserver_test.py
  function read_stream_body (line 51) | async def read_stream_body(stream):
  class HandlerBaseTestCase (line 73) | class HandlerBaseTestCase(AsyncHTTPTestCase):
    method get_app (line 76) | def get_app(self):
    method fetch_json (line 79) | def fetch_json(self, *args, **kwargs):
  class HelloWorldRequestHandler (line 85) | class HelloWorldRequestHandler(RequestHandler):
    method initialize (line 86) | def initialize(self, protocol="http"):
    method get (line 89) | def get(self):
    method post (line 94) | def post(self):
  class SSLTest (line 98) | class SSLTest(AsyncHTTPSTestCase):
    method get_app (line 99) | def get_app(self):
    method get_ssl_options (line 102) | def get_ssl_options(self):
    method test_ssl (line 108) | def test_ssl(self):
    method test_large_post (line 112) | def test_large_post(self):
    method test_non_ssl_request (line 116) | def test_non_ssl_request(self):
    method test_error_logging (line 130) | def test_error_logging(self):
  class BadSSLOptionsTest (line 140) | class BadSSLOptionsTest(unittest.TestCase):
    method test_missing_arguments (line 141) | def test_missing_arguments(self):
    method test_missing_key (line 150) | def test_missing_key(self):
  class MultipartTestHandler (line 181) | class MultipartTestHandler(RequestHandler):
    method post (line 182) | def post(self):
  class HTTPConnectionTest (line 194) | class HTTPConnectionTest(AsyncHTTPTestCase):
    method get_handlers (line 195) | def get_handlers(self):
    method get_app (line 201) | def get_app(self):
    method raw_fetch (line 204) | def raw_fetch(self, headers, body, newline=b"\r\n"):
    method test_multipart_form (line 220) | def test_multipart_form(self):
    method test_newlines (line 249) | def test_newlines(self):
    method test_100_continue (line 256) | def test_100_continue(self):
  class EchoHandler (line 286) | class EchoHandler(RequestHandler):
    method get (line 287) | def get(self):
    method post (line 290) | def post(self):
  class TypeCheckHandler (line 294) | class TypeCheckHandler(RequestHandler):
    method prepare (line 295) | def prepare(self):
    method post (line 322) | def post(self):
    method get (line 326) | def get(self):
    method check_type (line 329) | def check_type(self, name, obj, expected_type):
  class PostEchoHandler (line 335) | class PostEchoHandler(RequestHandler):
    method post (line 336) | def post(self, *path_args):
  class PostEchoGBKHandler (line 340) | class PostEchoGBKHandler(PostEchoHandler):
    method decode_argument (line 341) | def decode_argument(self, value, name=None):
  class HTTPServerTest (line 348) | class HTTPServerTest(AsyncHTTPTestCase):
    method get_app (line 349) | def get_app(self):
    method test_query_string_encoding (line 360) | def test_query_string_encoding(self):
    method test_empty_query_string (line 365) | def test_empty_query_string(self):
    method test_empty_post_parameters (line 370) | def test_empty_post_parameters(self):
    method test_types (line 375) | def test_types(self):
    method test_double_slash (line 387) | def test_double_slash(self):
    method test_post_encodings (line 395) | def test_post_encodings(self):
  class HTTPServerRawTest (line 413) | class HTTPServerRawTest(AsyncHTTPTestCase):
    method get_app (line 414) | def get_app(self):
    method setUp (line 417) | def setUp(self):
    method tearDown (line 424) | def tearDown(self):
    method test_empty_request (line 428) | def test_empty_request(self):
    method test_malformed_first_line_response (line 433) | def test_malformed_first_line_response(self):
    method test_malformed_first_line_log (line 443) | def test_malformed_first_line_log(self):
    method test_malformed_headers (line 451) | def test_malformed_headers(self):
    method test_invalid_host_header_with_whitespace (line 461) | def test_invalid_host_header_with_whitespace(self):
    method test_chunked_request_body (line 473) | def test_chunked_request_body(self):
    method test_chunked_request_uppercase (line 494) | def test_chunked_request_uppercase(self):
    method test_chunked_request_body_invalid_size (line 515) | def test_chunked_request_body_invalid_size(self):
    method test_chunked_request_body_duplicate_header (line 534) | def test_chunked_request_body_duplicate_header(self):
    method test_chunked_request_body_unsupported_transfer_encoding (line 558) | def test_chunked_request_body_unsupported_transfer_encoding(self):
    method test_chunked_request_body_transfer_encoding_and_content_length (line 578) | def test_chunked_request_body_transfer_encoding_and_content_length(self):
    method test_invalid_content_length (line 602) | def test_invalid_content_length(self):
    method test_invalid_methods (line 630) | def test_invalid_methods(self):
  class XHeaderTest (line 662) | class XHeaderTest(HandlerBaseTestCase):
    class Handler (line 663) | class Handler(RequestHandler):
      method get (line 664) | def get(self):
    method get_httpserver_options (line 673) | def get_httpserver_options(self):
    method test_ip_headers (line 676) | def test_ip_headers(self):
    method test_trusted_downstream (line 716) | def test_trusted_downstream(self):
    method test_scheme_headers (line 726) | def test_scheme_headers(self):
  class SSLXHeaderTest (line 757) | class SSLXHeaderTest(AsyncHTTPSTestCase, HandlerBaseTestCase):
    method get_app (line 758) | def get_app(self):
    method get_httpserver_options (line 761) | def get_httpserver_options(self):
    method test_request_without_xprotocol (line 766) | def test_request_without_xprotocol(self):
  class ManualProtocolTest (line 780) | class ManualProtocolTest(HandlerBaseTestCase):
    class Handler (line 781) | class Handler(RequestHandler):
      method get (line 782) | def get(self):
    method get_httpserver_options (line 785) | def get_httpserver_options(self):
    method test_manual_protocol (line 788) | def test_manual_protocol(self):
  class UnixSocketTest (line 793) | class UnixSocketTest(AsyncTestCase):
    method setUp (line 806) | def setUp(self):
    method tearDown (line 812) | def tearDown(self):
    method test_unix_socket (line 818) | def test_unix_socket(self):
    method test_unix_socket_bad_request (line 830) | def test_unix_socket_bad_request(self):
  class UnixSocketTestFile (line 845) | class UnixSocketTestFile(UnixSocketTest):
    method setUp (line 846) | def setUp(self):
    method tearDown (line 851) | def tearDown(self):
  class UnixSocketTestAbstract (line 860) | class UnixSocketTestAbstract(UnixSocketTest):
    method setUp (line 861) | def setUp(self):
  class KeepAliveTest (line 866) | class KeepAliveTest(AsyncHTTPTestCase):
    method get_app (line 873) | def get_app(self):
    method setUp (line 922) | def setUp(self):
    method tearDown (line 926) | def tearDown(self):
    method connect (line 938) | def connect(self):
    method read_headers (line 943) | def read_headers(self):
    method read_response (line 951) | def read_response(self):
    method close (line 956) | def close(self):
    method test_two_requests (line 961) | def test_two_requests(self):
    method test_request_close (line 970) | def test_request_close(self):
    method test_http10 (line 983) | def test_http10(self):
    method test_http10_keepalive (line 994) | def test_http10_keepalive(self):
    method test_http10_keepalive_extra_crlf (line 1006) | def test_http10_keepalive_extra_crlf(self):
    method test_pipelined_requests (line 1018) | def test_pipelined_requests(self):
    method test_pipelined_cancel (line 1028) | def test_pipelined_cancel(self):
    method test_cancel_during_download (line 1038) | def test_cancel_during_download(self):
    method test_finish_while_closed (line 1046) | def test_finish_while_closed(self):
    method test_keepalive_chunked (line 1055) | def test_keepalive_chunked(self):
    method test_keepalive_chunked_head_no_body (line 1074) | def test_keepalive_chunked_head_no_body(self):
  class GzipBaseTest (line 1084) | class GzipBaseTest(AsyncHTTPTestCase):
    method get_app (line 1085) | def get_app(self):
    method post_gzip (line 1088) | def post_gzip(self, body):
    method test_uncompressed (line 1101) | def test_uncompressed(self):
  class GzipTest (line 1106) | class GzipTest(GzipBaseTest, AsyncHTTPTestCase):
    method get_httpserver_options (line 1107) | def get_httpserver_options(self):
    method test_gzip (line 1110) | def test_gzip(self):
    method test_gzip_case_insensitive (line 1114) | def test_gzip_case_insensitive(self):
  class GzipUnsupportedTest (line 1130) | class GzipUnsupportedTest(GzipBaseTest, AsyncHTTPTestCase):
    method test_gzip_unsupported (line 1131) | def test_gzip_unsupported(self):
  class StreamingChunkSizeTest (line 1140) | class StreamingChunkSizeTest(AsyncHTTPTestCase):
    method get_http_client (line 1145) | def get_http_client(self):
    method get_httpserver_options (line 1150) | def get_httpserver_options(self):
    class MessageDelegate (line 1153) | class MessageDelegate(HTTPMessageDelegate):
      method __init__ (line 1154) | def __init__(self, connection):
      method headers_received (line 1157) | def headers_received(self, start_line, headers):
      method data_received (line 1160) | def data_received(self, chunk):
      method finish (line 1163) | def finish(self):
    method get_app (line 1172) | def get_app(self):
    method fetch_chunk_sizes (line 1179) | def fetch_chunk_sizes(self, **kwargs):
    method compress (line 1191) | def compress(self, body):
    method test_regular_body (line 1201) | def test_regular_body(self):
    method test_compressed_body (line 1206) | def test_compressed_body(self):
    method test_chunked_body (line 1213) | def test_chunked_body(self):
    method test_chunked_compressed (line 1222) | def test_chunked_compressed(self):
  class InvalidOutputContentLengthTest (line 1235) | class InvalidOutputContentLengthTest(AsyncHTTPTestCase):
    class MessageDelegate (line 1236) | class MessageDelegate(HTTPMessageDelegate):
      method __init__ (line 1237) | def __init__(self, connection):
      method headers_received (line 1240) | def headers_received(self, start_line, headers):
    method get_app (line 1254) | def get_app(self):
    method test_invalid_output_content_length (line 1261) | def test_invalid_output_content_length(self):
  class MaxHeaderSizeTest (line 1275) | class MaxHeaderSizeTest(AsyncHTTPTestCase):
    method get_app (line 1276) | def get_app(self):
    method get_httpserver_options (line 1279) | def get_httpserver_options(self):
    method test_small_headers (line 1282) | def test_small_headers(self):
    method test_large_headers (line 1287) | def test_large_headers(self):
  class IdleTimeoutTest (line 1300) | class IdleTimeoutTest(AsyncHTTPTestCase):
    method get_app (line 1301) | def get_app(self):
    method get_httpserver_options (line 1304) | def get_httpserver_options(self):
    method setUp (line 1307) | def setUp(self):
    method tearDown (line 1311) | def tearDown(self):
    method connect (line 1317) | def connect(self):
    method test_unused_connection (line 1324) | def test_unused_connection(self):
    method test_idle_after_use (line 1331) | def test_idle_after_use(self):
  class BodyLimitsTest (line 1347) | class BodyLimitsTest(AsyncHTTPTestCase):
    method get_app (line 1348) | def get_app(self):
    method get_httpserver_options (line 1375) | def get_httpserver_options(self):
    method get_http_client (line 1378) | def get_http_client(self):
    method test_small_body (line 1383) | def test_small_body(self):
    method test_large_body_buffered (line 1389) | def test_large_body_buffered(self):
    method test_large_body_buffered_chunked (line 1395) | def test_large_body_buffered_chunked(self):
    method test_large_body_streaming (line 1405) | def test_large_body_streaming(self):
    method test_large_body_streaming_chunked (line 1411) | def test_large_body_streaming_chunked(self):
    method test_large_body_streaming_override (line 1420) | def test_large_body_streaming_override(self):
    method test_large_body_streaming_chunked_override (line 1426) | def test_large_body_streaming_chunked_override(self):
    method test_timeout (line 1435) | def test_timeout(self):
    method test_body_size_override_reset (line 1452) | def test_body_size_override_reset(self):
  class LegacyInterfaceTest (line 1479) | class LegacyInterfaceTest(AsyncHTTPTestCase):
    method get_app (line 1480) | def get_app(self):
    method test_legacy_interface (line 1503) | def test_legacy_interface(self):

FILE: tornado/test/httputil_test.py
  function form_data_args (line 27) | def form_data_args() -> tuple[dict[str, list[bytes]], dict[str, list[HTT...
  class TestUrlConcat (line 36) | class TestUrlConcat(unittest.TestCase):
    method test_url_concat_no_query_params (line 37) | def test_url_concat_no_query_params(self):
    method test_url_concat_encode_args (line 41) | def test_url_concat_encode_args(self):
    method test_url_concat_trailing_q (line 45) | def test_url_concat_trailing_q(self):
    method test_url_concat_q_with_no_trailing_amp (line 49) | def test_url_concat_q_with_no_trailing_amp(self):
    method test_url_concat_trailing_amp (line 53) | def test_url_concat_trailing_amp(self):
    method test_url_concat_mult_params (line 57) | def test_url_concat_mult_params(self):
    method test_url_concat_no_params (line 61) | def test_url_concat_no_params(self):
    method test_url_concat_none_params (line 65) | def test_url_concat_none_params(self):
    method test_url_concat_with_frag (line 69) | def test_url_concat_with_frag(self):
    method test_url_concat_multi_same_params (line 73) | def test_url_concat_multi_same_params(self):
    method test_url_concat_multi_same_query_params (line 77) | def test_url_concat_multi_same_query_params(self):
    method test_url_concat_dict_params (line 81) | def test_url_concat_dict_params(self):
  class QsParseTest (line 86) | class QsParseTest(unittest.TestCase):
    method test_parsing (line 87) | def test_parsing(self):
  class MultipartFormDataTest (line 96) | class MultipartFormDataTest(unittest.TestCase):
    method test_file_upload (line 97) | def test_file_upload(self):
    method test_unquoted_names (line 110) | def test_unquoted_names(self):
    method test_special_filenames (line 124) | def test_special_filenames(self):
    method test_invalid_chars (line 151) | def test_invalid_chars(self):
    method test_non_ascii_filename_rfc5987 (line 170) | def test_non_ascii_filename_rfc5987(self):
    method test_non_ascii_filename_raw (line 183) | def test_non_ascii_filename_raw(self):
    method test_boundary_starts_and_ends_with_quotes (line 196) | def test_boundary_starts_and_ends_with_quotes(self):
    method test_missing_headers (line 209) | def test_missing_headers(self):
    method test_invalid_content_disposition (line 222) | def test_invalid_content_disposition(self):
    method test_line_does_not_end_with_correct_line_break (line 234) | def test_line_does_not_end_with_correct_line_break(self):
    method test_content_disposition_header_without_name_parameter (line 245) | def test_content_disposition_header_without_name_parameter(self):
    method test_data_after_final_boundary (line 259) | def test_data_after_final_boundary(self):
    method test_disposition_param_linear_performance (line 276) | def test_disposition_param_linear_performance(self):
    method test_multipart_config (line 300) | def test_multipart_config(self):
  class HTTPHeadersTest (line 333) | class HTTPHeadersTest(unittest.TestCase):
    method test_multi_line (line 334) | def test_multi_line(self):
    method test_continuation (line 361) | def test_continuation(self):
    method test_forbidden_ascii_characters (line 377) | def test_forbidden_ascii_characters(self):
    method test_unicode_newlines (line 388) | def test_unicode_newlines(self):
    method test_unicode_whitespace (line 431) | def test_unicode_whitespace(self):
    method test_optional_cr (line 450) | def test_optional_cr(self):
    method test_copy (line 463) | def test_copy(self):
    method test_pickle_roundtrip (line 480) | def test_pickle_roundtrip(self):
    method test_setdefault (line 490) | def test_setdefault(self):
    method test_string (line 501) | def test_string(self):
    method test_invalid_header_names (line 509) | def test_invalid_header_names(self):
    method test_linear_performance (line 525) | def test_linear_performance(self):
  class FormatTimestampTest (line 541) | class FormatTimestampTest(unittest.TestCase):
    method check (line 546) | def check(self, value):
    method test_unix_time_float (line 549) | def test_unix_time_float(self):
    method test_unix_time_int (line 552) | def test_unix_time_int(self):
    method test_struct_time (line 555) | def test_struct_time(self):
    method test_time_tuple (line 558) | def test_time_tuple(self):
    method test_utc_naive_datetime (line 563) | def test_utc_naive_datetime(self):
    method test_utc_naive_datetime_deprecated (line 570) | def test_utc_naive_datetime_deprecated(self):
    method test_utc_aware_datetime (line 574) | def test_utc_aware_datetime(self):
    method test_other_aware_datetime (line 579) | def test_other_aware_datetime(self):
  class HTTPServerRequestTest (line 590) | class HTTPServerRequestTest(unittest.TestCase):
    method test_default_constructor (line 591) | def test_default_constructor(self):
    method test_body_is_a_byte_string (line 597) | def test_body_is_a_byte_string(self):
    method test_repr_does_not_contain_headers (line 601) | def test_repr_does_not_contain_headers(self):
  class ParseRequestStartLineTest (line 608) | class ParseRequestStartLineTest(unittest.TestCase):
    method test_parse_request_start_line (line 613) | def test_parse_request_start_line(self):
  class ParseCookieTest (line 621) | class ParseCookieTest(unittest.TestCase):
    method test_python_cookies (line 624) | def test_python_cookies(self):
    method test_cookie_edgecases (line 649) | def test_cookie_edgecases(self):
    method test_invalid_cookies (line 658) | def test_invalid_cookies(self):
    method test_unquote (line 692) | def test_unquote(self):
    method test_unquote_large (line 718) | def test_unquote_large(self):

FILE: tornado/test/import_test.py
  class ImportTest (line 44) | class ImportTest(unittest.TestCase):
    method test_import_everything (line 45) | def test_import_everything(self):
    method test_lazy_import (line 54) | def test_lazy_import(self):
    method test_import_aliases (line 60) | def test_import_aliases(self):

FILE: tornado/test/ioloop_test.py
  class TestIOLoop (line 35) | class TestIOLoop(AsyncTestCase):
    method test_add_callback_return_sequence (line 36) | def test_add_callback_return_sequence(self):
    method test_add_callback_wakeup (line 55) | def test_add_callback_wakeup(self):
    method test_add_callback_wakeup_other_thread (line 73) | def test_add_callback_wakeup_other_thread(self):
    method test_add_timeout_timedelta (line 87) | def test_add_timeout_timedelta(self):
    method test_multiple_add (line 91) | def test_multiple_add(self):
    method test_remove_without_add (line 110) | def test_remove_without_add(self):
    method test_add_callback_from_signal (line 119) | def test_add_callback_from_signal(self):
    method test_add_callback_from_signal_other_thread (line 126) | def test_add_callback_from_signal_other_thread(self):
    method test_add_callback_while_closing (line 138) | def test_add_callback_while_closing(self):
    method test_read_while_writeable (line 158) | def test_read_while_writeable(self):
    method test_remove_timeout_after_fire (line 179) | def test_remove_timeout_after_fire(self):
    method test_remove_timeout_cleanup (line 185) | def test_remove_timeout_cleanup(self):
    method test_remove_timeout_from_timeout (line 198) | def test_remove_timeout_from_timeout(self):
    method test_timeout_with_arguments (line 221) | def test_timeout_with_arguments(self):
    method test_add_timeout_return (line 234) | def test_add_timeout_return(self):
    method test_call_at_return (line 241) | def test_call_at_return(self):
    method test_call_later_return (line 246) | def test_call_later_return(self):
    method test_close_file_object (line 251) | def test_close_file_object(self):
    method test_handler_callback_file_object (line 283) | def test_handler_callback_file_object(self):
    method test_mixed_fd_fileobj (line 308) | def test_mixed_fd_fileobj(self):
    method test_reentrant (line 322) | def test_reentrant(self):
    method test_exception_logging (line 340) | def test_exception_logging(self):
    method test_exception_logging_future (line 347) | def test_exception_logging_future(self):
    method test_exception_logging_native_coro (line 359) | def test_exception_logging_native_coro(self):
    method test_spawn_callback (line 372) | def test_spawn_callback(self):
    method test_remove_handler_from_handler (line 387) | def test_remove_handler_from_handler(self):
    method test_init_close_race (line 417) | def test_init_close_race(self):
    method test_explicit_asyncio_loop (line 430) | def test_explicit_asyncio_loop(self):
  class TestIOLoopCurrent (line 442) | class TestIOLoopCurrent(unittest.TestCase):
    method setUp (line 443) | def setUp(self):
    method tearDown (line 448) | def tearDown(self):
    method test_non_current (line 452) | def test_non_current(self):
    method test_force_current (line 471) | def test_force_current(self):
  class TestIOLoopCurrentAsync (line 476) | class TestIOLoopCurrentAsync(AsyncTestCase):
    method setUp (line 477) | def setUp(self):
    method test_clear_without_current (line 482) | def test_clear_without_current(self):
  class TestIOLoopFutures (line 490) | class TestIOLoopFutures(AsyncTestCase):
    method test_add_future_threads (line 491) | def test_add_future_threads(self):
    method test_run_in_executor_gen (line 505) | def test_run_in_executor_gen(self):
    method test_run_in_executor_native (line 527) | def test_run_in_executor_native(self):
    method test_set_default_executor (line 549) | def test_set_default_executor(self):
  class TestIOLoopRunSync (line 570) | class TestIOLoopRunSync(unittest.TestCase):
    method setUp (line 571) | def setUp(self):
    method tearDown (line 574) | def tearDown(self):
    method test_sync_result (line 577) | def test_sync_result(self):
    method test_sync_exception (line 581) | def test_sync_exception(self):
    method test_async_result (line 585) | def test_async_result(self):
    method test_async_exception (line 593) | def test_async_exception(self):
    method test_current (line 602) | def test_current(self):
    method test_timeout (line 608) | def test_timeout(self):
    method test_native_coroutine (line 615) | def test_native_coroutine(self):
    method test_stop_no_timeout (line 625) | def test_stop_no_timeout(self):
  class TestPeriodicCallbackMath (line 636) | class TestPeriodicCallbackMath(unittest.TestCase):
    method simulate_calls (line 637) | def simulate_calls(self, pc, durations):
    method dummy (line 654) | def dummy(self):
    method test_basic (line 657) | def test_basic(self):
    method test_overrun (line 663) | def test_overrun(self):
    method test_clock_backwards (line 684) | def test_clock_backwards(self):
    method test_jitter (line 701) | def test_jitter(self):
    method test_timedelta (line 713) | def test_timedelta(self):
  class TestPeriodicCallbackAsync (line 719) | class TestPeriodicCallbackAsync(AsyncTestCase):
    method test_periodic_plain (line 720) | def test_periodic_plain(self):
    method test_periodic_coro (line 735) | def test_periodic_coro(self) -> None:
    method test_periodic_async (line 753) | def test_periodic_async(self) -> None:
  class TestIOLoopConfiguration (line 771) | class TestIOLoopConfiguration(unittest.TestCase):
    method run_python (line 772) | def run_python(self, *statements):
    method test_default (line 780) | def test_default(self):
    method test_asyncio (line 787) | def test_asyncio(self):
    method test_asyncio_main (line 797) | def test_asyncio_main(self):

FILE: tornado/test/iostream_test.py
  function _server_ssl_options (line 48) | def _server_ssl_options():
  class HelloHandler (line 55) | class HelloHandler(RequestHandler):
    method get (line 56) | def get(self):
  class TestIOStreamWebMixin (line 61) | class TestIOStreamWebMixin(AsyncTestCase):
    method _make_client_iostream (line 71) | def _make_client_iostream(self):
    method mixin_get_app (line 74) | def mixin_get_app(self):
    method get_http_port (line 77) | def get_http_port(self) -> int:
    method fetch (line 80) | def fetch(
    method test_connection_closed (line 86) | def test_connection_closed(self):
    method test_read_until_close (line 106) | def test_read_until_close(self):
    method test_read_zero_bytes (line 116) | def test_read_zero_bytes(self):
    method test_write_while_connecting (line 136) | def test_write_while_connecting(self):
    method test_future_interface (line 158) | def test_future_interface(self):
    method test_future_close_while_reading (line 175) | def test_future_close_while_reading(self):
    method test_future_read_until_close (line 184) | def test_future_read_until_close(self):
  class TestReadWriteMixin (line 200) | class TestReadWriteMixin(AsyncTestCase):
    method make_iostream_pair (line 204) | def make_iostream_pair(self, **kwargs):
    method iostream_pair (line 207) | def iostream_pair(self, **kwargs):
    method test_write_zero_bytes (line 229) | def test_write_zero_bytes(self):
    method test_future_delayed_close_callback (line 238) | def test_future_delayed_close_callback(self):
    method test_close_buffered_data (line 254) | def test_close_buffered_data(self):
    method test_read_until_close_after_close (line 280) | def test_read_until_close_after_close(self):
    method test_large_read_until (line 299) | def test_large_read_until(self):
    method test_read_until_with_close_after_second_packet (line 324) | async def test_read_until_with_close_after_second_packet(self):
    method test_read_until_unsatisfied_after_close (line 348) | async def test_read_until_unsatisfied_after_close(self):
    method test_close_callback_with_pending_read (line 362) | def test_close_callback_with_pending_read(self):
    method test_future_close_callback (line 386) | def test_future_close_callback(self):
    method test_write_memoryview (line 411) | def test_write_memoryview(self):
    method test_read_bytes_partial (line 423) | def test_read_bytes_partial(self):
    method test_read_until_max_bytes (line 448) | def test_read_until_max_bytes(self):
    method test_read_until_max_bytes_inline (line 476) | def test_read_until_max_bytes_inline(self):
    method test_read_until_max_bytes_ignores_extra (line 495) | def test_read_until_max_bytes_ignores_extra(self):
    method test_read_until_regex_max_bytes (line 512) | def test_read_until_regex_max_bytes(self):
    method test_read_until_regex_max_bytes_inline (line 540) | def test_read_until_regex_max_bytes_inline(self):
    method test_read_until_regex_max_bytes_ignores_extra (line 558) | def test_read_until_regex_max_bytes_ignores_extra(self):
    method test_small_reads_from_large_buffer (line 575) | def test_small_reads_from_large_buffer(self):
    method test_small_read_untils_from_large_buffer (line 590) | def test_small_read_untils_from_large_buffer(self):
    method test_flow_control (line 605) | def test_flow_control(self):
    method test_read_into (line 623) | def test_read_into(self):
    method test_read_into_partial (line 665) | def test_read_into_partial(self):
    method test_read_into_zero_bytes (line 694) | def test_read_into_zero_bytes(self):
    method test_many_mixed_reads (line 705) | def test_many_mixed_reads(self):
  class TestIOStreamMixin (line 756) | class TestIOStreamMixin(TestReadWriteMixin):
    method _make_server_iostream (line 757) | def _make_server_iostream(self, connection, **kwargs):
    method _make_client_iostream (line 760) | def _make_client_iostream(self, connection, **kwargs):
    method make_iostream_pair (line 764) | def make_iostream_pair(self, **kwargs):
    method test_connection_refused (line 782) | def test_connection_refused(self):
    method test_gaierror (line 799) | def test_gaierror(self):
    method test_read_until_close_with_error (line 816) | def test_read_until_close_with_error(self):
    method test_inline_read_error (line 831) | def test_inline_read_error(self):
    method test_async_read_error_logging (line 864) | def test_async_read_error_logging(self):
    method test_future_write (line 889) | def test_future_write(self):
  class TestIOStreamWebHTTP (line 920) | class TestIOStreamWebHTTP(AsyncHTTPTestCase, TestIOStreamWebMixin):
    method _make_client_iostream (line 921) | def _make_client_iostream(self):
    method get_app (line 924) | def get_app(self):
  class TestIOStreamWebHTTPS (line 928) | class TestIOStreamWebHTTPS(AsyncHTTPSTestCase, TestIOStreamWebMixin):
    method _make_client_iostream (line 929) | def _make_client_iostream(self):
    method get_app (line 932) | def get_app(self):
  class TestIOStream (line 936) | class TestIOStream(TestIOStreamMixin):
    method _make_server_iostream (line 937) | def _make_server_iostream(self, connection, **kwargs):
    method _make_client_iostream (line 940) | def _make_client_iostream(self, connection, **kwargs):
  class TestIOStreamSSL (line 944) | class TestIOStreamSSL(TestIOStreamMixin):
    method _make_server_iostream (line 945) | def _make_server_iostream(self, connection, **kwargs):
    method _make_client_iostream (line 954) | def _make_client_iostream(self, connection, **kwargs):
  class TestIOStreamSSLContext (line 963) | class TestIOStreamSSLContext(TestIOStreamMixin):
    method _make_server_iostream (line 964) | def _make_server_iostream(self, connection, **kwargs):
    method _make_client_iostream (line 975) | def _make_client_iostream(self, connection, **kwargs):
  class TestIOStreamStartTLS (line 982) | class TestIOStreamStartTLS(AsyncTestCase):
    method setUp (line 983) | def setUp(self):
    method tearDown (line 1001) | def tearDown(self):
    method accept (line 1010) | def accept(self, connection, address):
    method client_send_line (line 1017) | def client_send_line(self, line):
    method server_send_line (line 1025) | def server_send_line(self, line):
    method client_start_tls (line 1032) | def client_start_tls(self, ssl_options=None, server_hostname=None):
    method server_start_tls (line 1038) | def server_start_tls(self, ssl_options=None):
    method test_start_tls_smtp (line 1045) | def test_start_tls_smtp(self):
    method test_handshake_fail (line 1066) | def test_handshake_fail(self):
    method test_check_hostname (line 1077) | def test_check_hostname(self):
    method test_typed_memoryview (line 1092) | def test_typed_memoryview(self):
  class WaitForHandshakeTest (line 1103) | class WaitForHandshakeTest(AsyncTestCase):
    method connect_to_server (line 1105) | def connect_to_server(self, server_cls):
    method test_wait_for_handshake_future (line 1134) | def test_wait_for_handshake_future(self):
    method test_wait_for_handshake_already_waiting_error (line 1152) | def test_wait_for_handshake_already_waiting_error(self):
    method test_wait_for_handshake_already_connected (line 1169) | def test_wait_for_handshake_already_connected(self):
  class TestIOStreamCheckHostname (line 1183) | class TestIOStreamCheckHostname(AsyncTestCase):
    method setUp (line 1188) | def setUp(self):
    method tearDown (line 1214) | def tearDown(self):
    method test_match (line 1220) | async def test_match(self):
    method test_no_match (line 1229) | async def test_no_match(self):
    method test_check_disabled (line 1254) | async def test_check_disabled(self):
  class TestPipeIOStream (line 1266) | class TestPipeIOStream(TestReadWriteMixin, AsyncTestCase):
    method make_iostream_pair (line 1268) | def make_iostream_pair(self, **kwargs):
    method test_pipe_iostream (line 1274) | def test_pipe_iostream(self):
    method test_pipe_iostream_big_write (line 1294) | def test_pipe_iostream_big_write(self):
  class TestStreamBuffer (line 1309) | class TestStreamBuffer(unittest.TestCase):
    method setUp (line 1314) | def setUp(self):
    method to_bytes (line 1317) | def to_bytes(self, b):
    method make_streambuffer (line 1325) | def make_streambuffer(self, large_buf_threshold=10):
    method check_peek (line 1331) | def check_peek(self, buf, expected):
    method check_append_all_then_skip_all (line 1340) | def check_append_all_then_skip_all(self, buf, objs, input_type):
    method test_small (line 1360) | def test_small(self):
    method test_large (line 1386) | def test_large(self):

FILE: tornado/test/locale_test.py
  class TranslationLoaderTest (line 12) | class TranslationLoaderTest(unittest.TestCase):
    method clear_locale_cache (line 16) | def clear_locale_cache(self):
    method setUp (line 19) | def setUp(self):
    method tearDown (line 25) | def tearDown(self):
    method test_csv (line 30) | def test_csv(self):
    method test_csv_bom (line 38) | def test_csv_bom(self):
    method test_gettext (line 60) | def test_gettext(self):
  class LocaleDataTest (line 78) | class LocaleDataTest(unittest.TestCase):
    method test_non_ascii_name (line 79) | def test_non_ascii_name(self):
  class EnglishTest (line 86) | class EnglishTest(unittest.TestCase):
    method test_format_date (line 87) | def test_format_date(self):
    method test_friendly_number (line 144) | def test_friendly_number(self):
    method test_list (line 148) | def test_list(self):
    method test_format_day (line 155) | def test_format_day(self):

FILE: tornado/test/locks_test.py
  class ConditionTest (line 22) | class ConditionTest(AsyncTestCase):
    method setUp (line 23) | def setUp(self):
    method record_done (line 27) | def record_done(self, future, key):
    method loop_briefly (line 39) | def loop_briefly(self):
    method test_repr (line 49) | def test_repr(self):
    method test_notify (line 57) | def test_notify(self):
    method test_notify_1 (line 62) | def test_notify_1(self):
    method test_notify_n (line 74) | def test_notify_n(self):
    method test_notify_all (line 91) | def test_notify_all(self):
    method test_wait_timeout (line 104) | def test_wait_timeout(self):
    method test_wait_timeout_preempted (line 112) | def test_wait_timeout_preempted(self):
    method test_notify_n_with_timeout (line 122) | def test_notify_n_with_timeout(self):
    method test_notify_all_with_timeout (line 146) | def test_notify_all_with_timeout(self):
    method test_nested_notify (line 161) | def test_nested_notify(self):
    method test_garbage_collection (line 177) | def test_garbage_collection(self):
  class EventTest (line 196) | class EventTest(AsyncTestCase):
    method test_repr (line 197) | def test_repr(self):
    method test_event (line 205) | def test_event(self):
    method test_event_timeout (line 218) | def test_event_timeout(self):
    method test_event_set_multiple (line 227) | def test_event_set_multiple(self):
    method test_event_wait_clear (line 233) | def test_event_wait_clear(self):
  class SemaphoreTest (line 243) | class SemaphoreTest(AsyncTestCase):
    method test_negative_value (line 244) | def test_negative_value(self):
    method test_repr (line 247) | def test_repr(self):
    method test_acquire (line 257) | def test_acquire(self):
    method test_acquire_timeout (line 278) | def test_acquire_timeout(self):
    method test_acquire_timeout_preempted (line 295) | def test_acquire_timeout_preempted(self):
    method test_release_unacquired (line 305) | def test_release_unacquired(self):
    method test_garbage_collection (line 318) | def test_garbage_collection(self):
  class SemaphoreContextManagerTest (line 343) | class SemaphoreContextManagerTest(AsyncTestCase):
    method test_context_manager (line 345) | def test_context_manager(self):
    method test_context_manager_async_await (line 354) | def test_context_manager_async_await(self):
    method test_context_manager_exception (line 368) | def test_context_manager_exception(self):
    method test_context_manager_timeout (line 378) | def test_context_manager_timeout(self):
    method test_context_manager_timeout_error (line 387) | def test_context_manager_timeout_error(self):
    method test_context_manager_contended (line 397) | def test_context_manager_contended(self):
    method test_yield_sem (line 417) | def test_yield_sem(self):
    method test_context_manager_misuse (line 424) | def test_context_manager_misuse(self):
  class BoundedSemaphoreTest (line 432) | class BoundedSemaphoreTest(AsyncTestCase):
    method test_release_unacquired (line 433) | def test_release_unacquired(self):
  class LockTests (line 448) | class LockTests(AsyncTestCase):
    method test_repr (line 449) | def test_repr(self):
    method test_acquire_release (line 456) | def test_acquire_release(self):
    method test_acquire_fifo (line 465) | def test_acquire_fifo(self):
    method test_acquire_fifo_async_with (line 483) | def test_acquire_fifo_async_with(self):
    method test_acquire_timeout (line 501) | def test_acquire_timeout(self):
    method test_multi_release (line 510) | def test_multi_release(self):
    method test_yield_lock (line 518) | def test_yield_lock(self):
    method test_context_manager_misuse (line 525) | def test_context_manager_misuse(self):

FILE: tornado/test/log_test.py
  function ignore_bytes_warning (line 33) | def ignore_bytes_warning():
  class LogFormatterTest (line 39) | class LogFormatterTest(unittest.TestCase):
    method setUp (line 46) | def setUp(self):
    method tearDown (line 63) | def tearDown(self):
    method make_handler (line 68) | def make_handler(self, filename):
    method get_output (line 71) | def get_output(self):
    method test_basic_logging (line 80) | def test_basic_logging(self):
    method test_bytes_logging (line 84) | def test_bytes_logging(self):
    method test_utf8_logging (line 90) | def test_utf8_logging(self):
    method test_bytes_exception_logging (line 103) | def test_bytes_exception_logging(self):
    method test_unicode_logging (line 115) | def test_unicode_logging(self):
  class EnablePrettyLoggingTest (line 120) | class EnablePrettyLoggingTest(unittest.TestCase):
    method setUp (line 121) | def setUp(self):
    method test_log_file (line 128) | def test_log_file(self):
    method test_log_file_with_timed_rotating (line 148) | def test_log_file_with_timed_rotating(self):
    method test_wrong_rotate_mode_value (line 168) | def test_wrong_rotate_mode_value(self):
  class LoggingOptionTest (line 184) | class LoggingOptionTest(unittest.TestCase):
    method logs_present (line 187) | def logs_present(self, statement, args=None):
    method test_default (line 205) | def test_default(self):
    method test_tornado_default (line 208) | def test_tornado_default(self):
    method test_disable_command_line (line 211) | def test_disable_command_line(self):
    method test_disable_command_line_case_insensitive (line 214) | def test_disable_command_line_case_insensitive(self):
    method test_disable_code_string (line 217) | def test_disable_code_string(self):
    method test_disable_code_none (line 222) | def test_disable_code_none(self):
    method test_disable_override (line 227) | def test_disable_override(self):

FILE: tornado/test/netutil_test.py
  class _ResolverTestMixin (line 29) | class _ResolverTestMixin(AsyncTestCase):
    method test_localhost (line 33) | def test_localhost(self):
  class _ResolverErrorTestMixin (line 48) | class _ResolverErrorTestMixin(AsyncTestCase):
    method test_bad_host (line 52) | def test_bad_host(self):
  function _failing_getaddrinfo (line 57) | def _failing_getaddrinfo(*args):
  class BlockingResolverTest (line 63) | class BlockingResolverTest(_ResolverTestMixin):
    method setUp (line 64) | def setUp(self):
  class BlockingResolverErrorTest (line 72) | class BlockingResolverErrorTest(_ResolverErrorTestMixin):
    method setUp (line 73) | def setUp(self):
    method tearDown (line 79) | def tearDown(self):
  class OverrideResolverTest (line 84) | class OverrideResolverTest(_ResolverTestMixin):
    method setUp (line 85) | def setUp(self):
    method test_resolve_multiaddr (line 98) | def test_resolve_multiaddr(self):
  class ThreadedResolverTest (line 109) | class ThreadedResolverTest(_ResolverTestMixin):
    method setUp (line 110) | def setUp(self):
    method tearDown (line 114) | def tearDown(self):
  class ThreadedResolverErrorTest (line 123) | class ThreadedResolverErrorTest(_ResolverErrorTestMixin):
    method setUp (line 124) | def setUp(self):
    method tearDown (line 130) | def tearDown(self):
  class ThreadedResolverImportTest (line 137) | class ThreadedResolverImportTest(unittest.TestCase):
    method test_import (line 138) | def test_import(self):
  class CaresResolverTest (line 168) | class CaresResolverTest(_ResolverTestMixin):
    method setUp (line 169) | def setUp(self):
  class IsValidIPTest (line 174) | class IsValidIPTest(unittest.TestCase):
    method test_is_valid_ip (line 175) | def test_is_valid_ip(self):
  class TestPortAllocation (line 191) | class TestPortAllocation(unittest.TestCase):
    method test_same_port_allocation (line 192) | def test_same_port_allocation(self):
    method test_reuse_port (line 204) | def test_reuse_port(self):

FILE: tornado/test/options_test.py
  class Email (line 12) | class Email:
    method __init__ (line 13) | def __init__(self, value):
    method value (line 20) | def value(self):
  class OptionsTest (line 24) | class OptionsTest(unittest.TestCase):
    method test_parse_command_line (line 25) | def test_parse_command_line(self):
    method test_parse_config_file (line 31) | def test_parse_config_file(self):
    method test_parse_callbacks (line 44) | def test_parse_callbacks(self):
    method test_help (line 67) | def test_help(self):
    method test_subcommand (line 79) | def test_subcommand(self):
    method test_setattr (line 102) | def test_setattr(self):
    method test_setattr_type_check (line 108) | def test_setattr_type_check(self):
    method test_setattr_with_callback (line 116) | def test_setattr_with_callback(self):
    method _sample_options (line 123) | def _sample_options(self):
    method test_iter (line 129) | def test_iter(self):
    method test_getitem (line 134) | def test_getitem(self):
    method test_setitem (line 138) | def test_setitem(self):
    method test_items (line 144) | def test_items(self):
    method test_as_dict (line 151) | def test_as_dict(self):
    method test_group_dict (line 156) | def test_group_dict(self):
    method test_mock_patch (line 170) | def test_mock_patch(self):
    method _define_options (line 191) | def _define_options(self):
    method _check_options_values (line 204) | def _check_options_values(self, options):
    method test_types (line 216) | def test_types(self):
    method test_types_with_conf_file (line 234) | def test_types_with_conf_file(self):
    method test_multiple_string (line 245) | def test_multiple_string(self):
    method test_multiple_int (line 251) | def test_multiple_int(self):
    method test_error_redefine (line 257) | def test_error_redefine(self):
    method test_error_redefine_underscore (line 264) | def test_error_redefine_underscore(self):
    method test_dash_underscore_cli (line 281) | def test_dash_underscore_cli(self):
    method test_dash_underscore_file (line 294) | def test_dash_underscore_file(self):
    method test_dash_underscore_introspection (line 305) | def test_dash_underscore_introspection(self):

FILE: tornado/test/process_test.py
  class ProcessTest (line 22) | class ProcessTest(unittest.TestCase):
    method get_app (line 23) | def get_app(self):
    method tearDown (line 36) | def tearDown(self):
    method test_multi_process (line 51) | def test_multi_process(self):
  class SubprocessTest (line 136) | class SubprocessTest(AsyncTestCase):
    method term_and_wait (line 137) | def term_and_wait(self, subproc):
    method test_subprocess (line 142) | def test_subprocess(self):
    method test_close_stdin (line 163) | def test_close_stdin(self):
    method test_stderr (line 178) | def test_stderr(self):
    method test_sigchild (line 191) | def test_sigchild(self):
    method test_sigchild_future (line 201) | def test_sigchild_future(self):
    method test_sigchild_signal (line 209) | def test_sigchild_signal(self):
    method test_wait_for_exit_raise (line 250) | def test_wait_for_exit_raise(self):
    method test_wait_for_exit_raise_disabled (line 259) | def test_wait_for_exit_raise_disabled(self):

FILE: tornado/test/queues_test.py
  class QueueBasicTest (line 23) | class QueueBasicTest(AsyncTestCase):
    method test_repr_and_str (line 24) | def test_repr_and_str(self):
    method test_order (line 47) | def test_order(self):
    method test_maxsize (line 56) | def test_maxsize(self):
  class QueueGetTest (line 76) | class QueueGetTest(AsyncTestCase):
    method test_blocking_get (line 78) | def test_blocking_get(self):
    method test_nonblocking_get (line 83) | def test_nonblocking_get(self):
    method test_nonblocking_get_exception (line 88) | def test_nonblocking_get_exception(self):
    method test_get_with_putters (line 93) | def test_get_with_putters(self):
    method test_blocking_get_wait (line 101) | def test_blocking_get_wait(self):
    method test_get_timeout (line 110) | def test_get_timeout(self):
    method test_get_timeout_preempted (line 121) | def test_get_timeout_preempted(self):
    method test_get_clears_timed_out_putters (line 129) | def test_get_clears_timed_out_putters(self):
    method test_get_clears_timed_out_getters (line 145) | def test_get_clears_timed_out_getters(self):
    method test_async_for (line 161) | def test_async_for(self):
  class QueuePutTest (line 177) | class QueuePutTest(AsyncTestCase):
    method test_blocking_put (line 179) | def test_blocking_put(self):
    method test_nonblocking_put_exception (line 184) | def test_nonblocking_put_exception(self):
    method test_put_with_getters (line 190) | def test_put_with_getters(self):
    method test_nonblocking_put_with_getters (line 200) | def test_nonblocking_put_with_getters(self):
    method test_blocking_put_wait (line 213) | def test_blocking_put_wait(self):
    method test_put_timeout (line 227) | def test_put_timeout(self):
    method test_put_timeout_preempted (line 243) | def test_put_timeout_preempted(self):
    method test_put_clears_timed_out_putters (line 252) | def test_put_clears_timed_out_putters(self):
    method test_put_clears_timed_out_getters (line 267) | def test_put_clears_timed_out_getters(self):
    method test_float_maxsize (line 285) | def test_float_maxsize(self):
  class QueueJoinTest (line 310) | class QueueJoinTest(AsyncTestCase):
    method test_task_done_underflow (line 313) | def test_task_done_underflow(self):
    method test_task_done (line 318) | def test_task_done(self):
    method test_task_done_delay (line 340) | def test_task_done_delay(self):
    method test_join_empty_queue (line 354) | def test_join_empty_queue(self):
    method test_join_timeout (line 360) | def test_join_timeout(self):
  class PriorityQueueJoinTest (line 367) | class PriorityQueueJoinTest(QueueJoinTest):
    method test_order (line 371) | def test_order(self):
  class LifoQueueJoinTest (line 385) | class LifoQueueJoinTest(QueueJoinTest):
    method test_order (line 389) | def test_order(self):
  class ProducerConsumerTest (line 403) | class ProducerConsumerTest(AsyncTestCase):
    method test_producer_consumer (line 405) | def test_producer_consumer(self):

FILE: tornado/test/routing_test.py
  class BasicRouter (line 34) | class BasicRouter(Router):
    method find_handler (line 35) | def find_handler(self, request, **kwargs):
  class BasicRouterTestCase (line 51) | class BasicRouterTestCase(AsyncHTTPTestCase):
    method get_app (line 52) | def get_app(self):
    method test_basic_router (line 55) | def test_basic_router(self):
  class GetResource (line 63) | class GetResource(RequestHandler):
    method get (line 64) | def get(self, path):
  class PostResource (line 71) | class PostResource(RequestHandler):
    method post (line 72) | def post(self, path):
  class HTTPMethodRouter (line 76) | class HTTPMethodRouter(Router):
    method __init__ (line 77) | def __init__(self, app):
    method find_handler (line 80) | def find_handler(self, request, **kwargs):
  class HTTPMethodRouterTestCase (line 85) | class HTTPMethodRouterTestCase(AsyncHTTPTestCase):
    method get_app (line 86) | def get_app(self):
    method test_http_method_router (line 89) | def test_http_method_router(self):
  function _get_named_handler (line 101) | def _get_named_handler(handler_name):
  class CustomRouter (line 116) | class CustomRouter(ReversibleRouter):
    method __init__ (line 117) | def __init__(self):
    method add_routes (line 121) | def add_routes(self, routes):
    method find_handler (line 124) | def find_handler(self, request, **kwargs):
    method reverse_url (line 129) | def reverse_url(self, name, *args):
  class CustomRouterTestCase (line 134) | class CustomRouterTestCase(AsyncHTTPTestCase):
    method get_app (line 135) | def get_app(self):
    method test_custom_router (line 155) | def test_custom_router(self):
  class ConnectionDelegate (line 164) | class ConnectionDelegate(HTTPServerConnectionDelegate):
    method start_request (line 165) | def start_request(self, server_conn, request_conn):
  class RuleRouterTest (line 182) | class RuleRouterTest(AsyncHTTPTestCase):
    method get_app (line 183) | def get_app(self):
    method test_rule_based_router (line 222) | def test_rule_based_router(self):
  class WSGIContainerTestCase (line 245) | class WSGIContainerTestCase(AsyncHTTPTestCase):
    method get_app (line 246) | def get_app(self):
    method wsgi_app (line 263) | def wsgi_app(self, environ, start_response):
    method test_wsgi_container (line 267) | def test_wsgi_container(self):
    method test_delegate_not_found (line 274) | def test_delegate_not_found(self):

FILE: tornado/test/runtests.py
  function all (line 58) | def all():
  function test_runner_factory (line 62) | def test_runner_factory(stderr):
  class LogCounter (line 95) | class LogCounter(logging.Filter):
    method __init__ (line 98) | def __init__(self, *args, **kwargs):
    method filter (line 102) | def filter(self, record):
  class CountingStderr (line 112) | class CountingStderr(io.IOBase):
    method __init__ (line 113) | def __init__(self, real):
    method write (line 117) | def write(self, data):
    method flush (line 121) | def flush(self):
  function main (line 125) | def main():

FILE: tornado/test/simple_httpclient_test.py
  class SimpleHTTPClientCommonTestCase (line 50) | class SimpleHTTPClientCommonTestCase(httpclient_test.HTTPClientCommonTes...
    method get_http_client (line 51) | def get_http_client(self):
  class TriggerHandler (line 57) | class TriggerHandler(RequestHandler):
    method initialize (line 58) | def initialize(self, queue, wake_callback):
    method get (line 63) | def get(self):
  class ContentLengthHandler (line 72) | class ContentLengthHandler(RequestHandler):
    method get (line 73) | def get(self):
    method write_response (line 78) | def write_response(self):
  class HeadHandler (line 88) | class HeadHandler(RequestHandler):
    method head (line 89) | def head(self):
  class OptionsHandler (line 93) | class OptionsHandler(RequestHandler):
    method options (line 94) | def options(self):
  class NoContentHandler (line 99) | class NoContentHandler(RequestHandler):
    method get (line 100) | def get(self):
  class SeeOtherPostHandler (line 105) | class SeeOtherPostHandler(RequestHandler):
    method post (line 106) | def post(self):
  class SeeOtherGetHandler (line 113) | class SeeOtherGetHandler(RequestHandler):
    method get (line 114) | def get(self):
  class HostEchoHandler (line 120) | class HostEchoHandler(RequestHandler):
    method get (line 121) | def get(self):
  class NoContentLengthHandler (line 125) | class NoContentLengthHandler(RequestHandler):
    method get (line 126) | def get(self):
  class EchoPostHandler (line 138) | class EchoPostHandler(RequestHandler):
    method post (line 139) | def post(self):
  class RespondInPrepareHandler (line 144) | class RespondInPrepareHandler(RequestHandler):
    method prepare (line 145) | def prepare(self):
  class SimpleHTTPClientTestMixin (line 151) | class SimpleHTTPClientTestMixin(AsyncTestCase):
    method get_http_port (line 153) | def get_http_port(self) -> int:
    method fetch (line 156) | def fetch(
    method get_url (line 162) | def get_url(self, path: str) -> str:
    method get_protocol (line 165) | def get_protocol(self) -> str:
    method get_http_server (line 168) | def get_http_server(self) -> HTTPServer:
    method create_client (line 171) | def create_client(self, **kwargs):
    method mixin_get_app (line 174) | def mixin_get_app(self):
    method test_singleton (line 203) | def test_singleton(self):
    method test_connection_limit (line 221) | def test_connection_limit(self):
    method test_redirect_connection_limit (line 252) | def test_redirect_connection_limit(self):
    method test_max_redirects (line 258) | def test_max_redirects(self):
    method test_header_reuse (line 267) | def test_header_reuse(self):
    method test_default_user_agent (line 274) | def test_default_user_agent(self):
    method test_see_other_redirect (line 279) | def test_see_other_redirect(self):
    method test_connect_timeout (line 289) | def test_connect_timeout(self):
    method test_request_timeout (line 316) | def test_request_timeout(self):
    method test_ipv6 (line 328) | def test_ipv6(self):
    method test_multiple_content_length_accepted (line 341) | def test_multiple_content_length_accepted(self):
    method test_head_request (line 355) | def test_head_request(self):
    method test_options_request (line 361) | def test_options_request(self):
    method test_no_content (line 368) | def test_no_content(self):
    method test_host_header (line 377) | def test_host_header(self):
    method test_connection_refused (line 386) | def test_connection_refused(self):
    method test_queue_timeout (line 406) | def test_queue_timeout(self):
    method test_no_content_length (line 422) | def test_no_content_length(self):
    method sync_body_producer (line 429) | def sync_body_producer(self, write):
    method async_body_producer (line 434) | def async_body_producer(self, write):
    method test_sync_body_producer_chunked (line 439) | def test_sync_body_producer_chunked(self):
    method test_sync_body_producer_content_length (line 446) | def test_sync_body_producer_content_length(self):
    method test_async_body_producer_chunked (line 456) | def test_async_body_producer_chunked(self):
    method test_async_body_producer_content_length (line 463) | def test_async_body_producer_content_length(self):
    method test_native_body_producer_chunked (line 473) | def test_native_body_producer_chunked(self):
    method test_native_body_producer_content_length (line 485) | def test_native_body_producer_content_length(self):
    method test_100_continue (line 502) | def test_100_continue(self):
    method test_100_continue_early_response (line 508) | def test_100_continue_early_response(self):
    method test_streaming_follow_redirects (line 520) | def test_streaming_follow_redirects(self):
    method test_streaming_callback_coroutine (line 540) | def test_streaming_callback_coroutine(self: typing.Any):
  class SimpleHTTPClientTestCase (line 562) | class SimpleHTTPClientTestCase(AsyncHTTPTestCase, SimpleHTTPClientTestMi...
    method setUp (line 563) | def setUp(self):
    method get_app (line 567) | def get_app(self):
    method create_client (line 570) | def create_client(self, **kwargs):
  class SimpleHTTPSClientTestCase (line 574) | class SimpleHTTPSClientTestCase(AsyncHTTPSTestCase, SimpleHTTPClientTest...
    method setUp (line 575) | def setUp(self):
    method get_app (line 579) | def get_app(self):
    method create_client (line 582) | def create_client(self, **kwargs):
    method test_ssl_options (line 587) | def test_ssl_options(self):
    method test_ssl_context (line 591) | def test_ssl_context(self):
    method test_ssl_options_handshake_fail (line 598) | def test_ssl_options_handshake_fail(self):
    method test_ssl_context_handshake_fail (line 607) | def test_ssl_context_handshake_fail(self):
    method test_error_logging (line 614) | def test_error_logging(self):
  class CreateAsyncHTTPClientTestCase (line 624) | class CreateAsyncHTTPClientTestCase(AsyncTestCase):
    method setUp (line 625) | def setUp(self):
    method tearDown (line 629) | def tearDown(self):
    method test_max_clients (line 633) | def test_max_clients(self):
  class HTTP100ContinueTestCase (line 651) | class HTTP100ContinueTestCase(AsyncHTTPTestCase):
    method respond_100 (line 652) | def respond_100(self, request):
    method respond_200 (line 664) | def respond_200(self, fut):
    method get_app (line 671) | def get_app(self):
    method test_100_continue (line 675) | def test_100_continue(self):
  class HTTP204NoContentTestCase (line 682) | class HTTP204NoContentTestCase(AsyncHTTPTestCase):
    method respond_204 (line 683) | def respond_204(self, request):
    method get_app (line 708) | def get_app(self):
    method test_204_no_content (line 711) | def test_204_no_content(self):
    method test_204_invalid_content_length (line 718) | def test_204_invalid_content_length(self):
  class HostnameMappingTestCase (line 731) | class HostnameMappingTestCase(AsyncHTTPTestCase):
    method setUp (line 732) | def setUp(self):
    method get_app (line 741) | def get_app(self):
    method test_hostname_mapping (line 744) | def test_hostname_mapping(self):
    method test_port_mapping (line 749) | def test_port_mapping(self):
  class ResolveTimeoutTestCase (line 755) | class ResolveTimeoutTestCase(AsyncHTTPTestCase):
    method setUp (line 756) | def setUp(self):
    method get_app (line 771) | def get_app(self):
    method test_resolve_timeout (line 774) | def test_resolve_timeout(self):
  class MaxHeaderSizeTest (line 783) | class MaxHeaderSizeTest(AsyncHTTPTestCase):
    method get_app (line 784) | def get_app(self):
    method get_http_client (line 797) | def get_http_client(self):
    method test_small_headers (line 800) | def test_small_headers(self):
    method test_large_headers (line 805) | def test_large_headers(self):
  class MaxBodySizeTest (line 811) | class MaxBodySizeTest(AsyncHTTPTestCase):
    method get_app (line 812) | def get_app(self):
    method get_http_client (line 823) | def get_http_client(self):
    method test_small_body (line 826) | def test_small_body(self):
    method test_large_body (line 831) | def test_large_body(self):
  class MaxBufferSizeTest (line 841) | class MaxBufferSizeTest(AsyncHTTPTestCase):
    method get_app (line 842) | def get_app(self):
    method get_http_client (line 849) | def get_http_client(self):
    method test_large_body (line 855) | def test_large_body(self):
  class ChunkedWithContentLengthTest (line 861) | class ChunkedWithContentLengthTest(AsyncHTTPTestCase):
    method get_app (line 862) | def get_app(self):
    method get_http_client (line 871) | def get_http_client(self):
    method test_chunked_with_content_length (line 874) | def test_chunked_with_content_length(self):

FILE: tornado/test/tcpclient_test.py
  class TestTCPServer (line 36) | class TestTCPServer(TCPServer):
    method __init__ (line 37) | def __init__(self, family):
    method handle_stream (line 45) | def handle_stream(self, stream, address):
    method stop (line 49) | def stop(self):
  class TCPClientTest (line 55) | class TCPClientTest(AsyncTestCase):
    method setUp (line 56) | def setUp(self):
    method start_server (line 61) | def start_server(self, family):
    method stop_server (line 65) | def stop_server(self):
    method tearDown (line 70) | def tearDown(self):
    method skipIfLocalhostV4 (line 75) | def skipIfLocalhostV4(self):
    method do_test_connect (line 84) | def do_test_connect(self, family, host, source_ip=None, source_port=No...
    method test_connect_ipv4_ipv4 (line 100) | def test_connect_ipv4_ipv4(self):
    method test_connect_ipv4_dual (line 103) | def test_connect_ipv4_dual(self):
    method test_connect_ipv6_ipv6 (line 107) | def test_connect_ipv6_ipv6(self):
    method test_connect_ipv6_dual (line 112) | def test_connect_ipv6_dual(self):
    method test_connect_unspec_ipv4 (line 116) | def test_connect_unspec_ipv4(self):
    method test_connect_unspec_ipv6 (line 120) | def test_connect_unspec_ipv6(self):
    method test_connect_unspec_dual (line 124) | def test_connect_unspec_dual(self):
    method test_refused_ipv4 (line 128) | def test_refused_ipv4(self):
    method test_source_ip_fail (line 134) | def test_source_ip_fail(self):
    method test_source_ip_success (line 144) | def test_source_ip_success(self):
    method test_source_port_fail (line 149) | def test_source_port_fail(self):
    method test_connect_timeout (line 164) | def test_connect_timeout(self):
  class TestConnectorSplit (line 177) | class TestConnectorSplit(unittest.TestCase):
    method test_one_family (line 178) | def test_one_family(self):
    method test_mixed (line 184) | def test_mixed(self):
  class ConnectorTest (line 192) | class ConnectorTest(AsyncTestCase):
    class FakeStream (line 193) | class FakeStream:
      method __init__ (line 194) | def __init__(self):
      method close (line 197) | def close(self):
    method setUp (line 200) | def setUp(self):
    method tearDown (line 208) | def tearDown(self):
    method create_stream (line 215) | def create_stream(self, af, addr):
    method assert_pending (line 222) | def assert_pending(self, *keys):
    method resolve_connect (line 225) | def resolve_connect(self, af, addr, success):
    method assert_connector_streams_closed (line 236) | def assert_connector_streams_closed(self, conn):
    method start_connect (line 240) | def start_connect(self, addrinfo):
    method test_immediate_success (line 246) | def test_immediate_success(self):
    method test_immediate_failure (line 252) | def test_immediate_failure(self):
    method test_one_family_second_try (line 259) | def test_one_family_second_try(self):
    method test_one_family_second_try_failure (line 267) | def test_one_family_second_try_failure(self):
    method test_one_family_second_try_timeout (line 275) | def test_one_family_second_try_timeout(self):
    method test_two_families_immediate_failure (line 287) | def test_two_families_immediate_failure(self):
    method test_two_families_timeout (line 296) | def test_two_families_timeout(self):
    method test_success_after_timeout (line 307) | def test_success_after_timeout(self):
    method test_all_fail (line 318) | def test_all_fail(self):
    method test_one_family_timeout_after_connect_timeout (line 334) | def test_one_family_timeout_after_connect_timeout(self):
    method test_one_family_success_before_connect_timeout (line 350) | def test_one_family_success_before_connect_timeout(self):
    method test_one_family_second_try_after_connect_timeout (line 363) | def test_one_family_second_try_after_connect_timeout(self):
    method test_one_family_second_try_failure_before_connect_timeout (line 376) | def test_one_family_second_try_failure_before_connect_timeout(self):
    method test_two_family_timeout_before_connect_timeout (line 388) | def test_two_family_timeout_before_connect_timeout(self):
    method test_two_family_success_after_timeout (line 403) | def test_two_family_success_after_timeout(self):
    method test_two_family_timeout_after_connect_timeout (line 417) | def test_two_family_timeout_after_connect_timeout(self):

FILE: tornado/test/tcpserver_test.py
  class TCPServerTest (line 15) | class TCPServerTest(AsyncTestCase):
    method test_handle_stream_coroutine_logging (line 17) | def test_handle_stream_coroutine_logging(self):
    method test_handle_stream_native_coroutine (line 45) | def test_handle_stream_native_coroutine(self):
    method test_stop_twice (line 63) | def test_stop_twice(self):
    method test_stop_in_callback (line 71) | def test_stop_in_callback(self):
  class TestMultiprocess (line 118) | class TestMultiprocess(unittest.TestCase):
    method run_subproc (line 124) | def run_subproc(self, code: str) -> tuple[str, str]:
    method test_listen_single (line 139) | def test_listen_single(self):
    method test_bind_start (line 157) | def test_bind_start(self):
    method test_add_sockets (line 177) | def test_add_sockets(self):
    method test_listen_multi_reuse_port (line 197) | def test_listen_multi_reuse_port(self):

FILE: tornado/test/template_test.py
  class TemplateTest (line 10) | class TemplateTest(unittest.TestCase):
    method test_simple (line 11) | def test_simple(self):
    method test_bytes (line 15) | def test_bytes(self):
    method test_expressions (line 19) | def test_expressions(self):
    method test_comment (line 23) | def test_comment(self):
    method test_include (line 27) | def test_include(self):
    method test_extends (line 38) | def test_extends(self):
    method test_relative_load (line 57) | def test_relative_load(self):
    method test_escaping (line 67) | def test_escaping(self):
    method test_unicode_template (line 78) | def test_unicode_template(self):
    method test_unicode_literal_expression (line 82) | def test_unicode_literal_expression(self):
    method test_custom_namespace (line 90) | def test_custom_namespace(self):
    method test_apply (line 96) | def test_apply(self):
    method test_unicode_apply (line 103) | def test_unicode_apply(self):
    method test_bytes_apply (line 110) | def test_bytes_apply(self):
    method test_if (line 117) | def test_if(self):
    method test_if_empty_body (line 122) | def test_if_empty_body(self):
    method test_try (line 126) | def test_try(self):
    method test_comment_directive (line 136) | def test_comment_directive(self):
    method test_break_continue (line 140) | def test_break_continue(self):
    method test_break_outside_loop (line 156) | def test_break_outside_loop(self):
    method test_break_in_apply (line 160) | def test_break_in_apply(self):
    method test_no_inherit_future (line 169) | def test_no_inherit_future(self):
    method test_non_ascii_name (line 180) | def test_non_ascii_name(self):
  class StackTraceTest (line 185) | class StackTraceTest(unittest.TestCase):
    method test_error_line_number_expression (line 186) | def test_error_line_number_expression(self):
    method test_error_line_number_directive (line 197) | def test_error_line_number_directive(self):
    method test_error_line_number_module (line 208) | def test_error_line_number_module(self):
    method test_error_line_number_include (line 227) | def test_error_line_number_include(self):
    method test_error_line_number_extends_base_error (line 237) | def test_error_line_number_extends_base_error(self):
    method test_error_line_number_extends_sub_error (line 248) | def test_error_line_number_extends_sub_error(self):
    method test_multi_includes (line 266) | def test_multi_includes(self):
  class ParseErrorDetailTest (line 281) | class ParseErrorDetailTest(unittest.TestCase):
    method test_details (line 282) | def test_details(self):
    method test_custom_parse_error (line 290) | def test_custom_parse_error(self):
  class AutoEscapeTest (line 296) | class AutoEscapeTest(unittest.TestCase):
    method setUp (line 297) | def setUp(self):
    method test_default_off (line 335) | def test_default_off(self):
    method test_default_on (line 355) | def test_default_on(self):
    method test_unextended_block (line 375) | def test_unextended_block(self):
    method test_extended_block (line 386) | def test_extended_block(self):
    method test_raw_expression (line 404) | def test_raw_expression(self):
    method test_custom_escape (line 414) | def test_custom_escape(self):
    method test_manual_minimize_whitespace (line 430) | def test_manual_minimize_whitespace(self):
    method test_whitespace_by_filename (line 444) | def test_whitespace_by_filename(self):
    method test_whitespace_by_loader (line 467) | def test_whitespace_by_loader(self):
    method test_whitespace_directive (line 481) | def test_whitespace_directive(self):
  class TemplateLoaderTest (line 495) | class TemplateLoaderTest(unittest.TestCase):
    method setUp (line 496) | def setUp(self):
    method test_utf8_in_file (line 499) | def test_utf8_in_file(self):

FILE: tornado/test/testing_test.py
  function set_environ (line 19) | def set_environ(name, value):
  class AsyncTestCaseTest (line 32) | class AsyncTestCaseTest(AsyncTestCase):
    method test_wait_timeout (line 33) | def test_wait_timeout(self):
    method test_subsequent_wait_calls (line 51) | def test_subsequent_wait_calls(self):
  class LeakTest (line 65) | class LeakTest(AsyncTestCase):
    method tearDown (line 66) | def tearDown(self):
    method test_leaked_coroutine (line 71) | def test_leaked_coroutine(self):
  class AsyncHTTPTestCaseTest (line 89) | class AsyncHTTPTestCaseTest(AsyncHTTPTestCase):
    method setUp (line 90) | def setUp(self):
    method get_app (line 100) | def get_app(self):
    method test_fetch_segment (line 103) | def test_fetch_segment(self):
    method test_fetch_full_http_url (line 108) | def test_fetch_full_http_url(self):
    method tearDown (line 116) | def tearDown(self):
  class AsyncTestCaseReturnAssertionsTest (line 121) | class AsyncTestCaseReturnAssertionsTest(unittest.TestCase):
    method test_undecorated_generator (line 126) | def test_undecorated_generator(self):
    method test_undecorated_coroutine (line 147) | def test_undecorated_coroutine(self):
    method test_undecorated_generator_with_skip (line 163) | def test_undecorated_generator_with_skip(self):
    method test_other_return (line 175) | def test_other_return(self):
  class SetUpTearDownTest (line 187) | class SetUpTearDownTest(unittest.TestCase):
    method test_set_up_tear_down (line 188) | def test_set_up_tear_down(self):
  class AsyncHTTPTestCaseSetUpTearDownTest (line 216) | class AsyncHTTPTestCaseSetUpTearDownTest(unittest.TestCase):
    method test_tear_down_releases_app_and_http_server (line 217) | def test_tear_down_releases_app_and_http_server(self):
  class GenTest (line 234) | class GenTest(AsyncTestCase):
    method setUp (line 235) | def setUp(self):
    method tearDown (line 239) | def tearDown(self):
    method test_sync (line 244) | def test_sync(self):
    method test_async (line 248) | def test_async(self):
    method test_timeout (line 252) | def test_timeout(self):
    method test_no_timeout (line 270) | def test_no_timeout(self):
    method test_timeout_environment_variable (line 279) | def test_timeout_environment_variable(self):
    method test_no_timeout_environment_variable (line 290) | def test_no_timeout_environment_variable(self):
    method test_with_method_args (line 302) | def test_with_method_args(self):
    method test_with_method_kwargs (line 311) | def test_with_method_kwargs(self):
    method test_native_coroutine (line 320) | def test_native_coroutine(self):
    method test_native_coroutine_timeout (line 327) | def test_native_coroutine_timeout(self):

FILE: tornado/test/twisted_test.py
  class ConvertDeferredTest (line 43) | class ConvertDeferredTest(AsyncTestCase):
    method test_success (line 45) | def test_success(self):
    method test_failure (line 58) | def test_failure(self):

FILE: tornado/test/util.py
  function _detect_ipv6 (line 39) | def _detect_ipv6():
  function refusing_port (line 59) | def refusing_port():
  function exec_test (line 79) | def exec_test(caller_globals, caller_locals, s):
  function ignore_deprecation (line 95) | def ignore_deprecation():
  function abstract_base_test (line 105) | def abstract_base_test(cls: _TestCaseType) -> _TestCaseType:

FILE: tornado/test/util_test.py
  class RaiseExcInfoTest (line 21) | class RaiseExcInfoTest(unittest.TestCase):
    method test_two_arg_exception (line 22) | def test_two_arg_exception(self):
  class TestConfigurable (line 42) | class TestConfigurable(Configurable):
    method configurable_base (line 44) | def configurable_base(cls):
    method configurable_default (line 48) | def configurable_default(cls):
  class TestConfig1 (line 52) | class TestConfig1(TestConfigurable):
    method initialize (line 53) | def initialize(self, pos_arg=None, a=None):
  class TestConfig2 (line 58) | class TestConfig2(TestConfigurable):
    method initialize (line 59) | def initialize(self, pos_arg=None, b=None):
  class TestConfig3 (line 64) | class TestConfig3(TestConfigurable):
    method configurable_base (line 67) | def configurable_base(cls):
    method configurable_default (line 71) | def configurable_default(cls):
  class TestConfig3A (line 75) | class TestConfig3A(TestConfig3):
    method initialize (line 76) | def initialize(self, a=None):
  class TestConfig3B (line 80) | class TestConfig3B(TestConfig3):
    method initialize (line 81) | def initialize(self, b=None):
  class ConfigurableTest (line 85) | class ConfigurableTest(unittest.TestCase):
    method setUp (line 86) | def setUp(self):
    method tearDown (line 90) | def tearDown(self):
    method checkSubclasses (line 94) | def checkSubclasses(self):
    method test_default (line 105) | def test_default(self):
    method test_config_class (line 119) | def test_config_class(self):
    method test_config_str (line 131) | def test_config_str(self):
    method test_config_args (line 143) | def test_config_args(self):
    method test_config_class_args (line 159) | def test_config_class_args(self):
    method test_config_multi_level (line 175) | def test_config_multi_level(self):
    method test_config_inner_level (line 187) | def test_config_inner_level(self):
  class UnicodeLiteralTest (line 209) | class UnicodeLiteralTest(unittest.TestCase):
    method test_unicode_escapes (line 210) | def test_unicode_escapes(self):
  class ExecInTest (line 214) | class ExecInTest(unittest.TestCase):
    method test_no_inherit_future (line 215) | def test_no_inherit_future(self):
  class ArgReplacerTest (line 242) | class ArgReplacerTest(unittest.TestCase):
    method setUp (line 243) | def setUp(self):
    method test_omitted (line 249) | def test_omitted(self):
    method test_position (line 258) | def test_position(self):
    method test_keyword (line 267) | def test_keyword(self):
  class TimedeltaToSecondsTest (line 277) | class TimedeltaToSecondsTest(unittest.TestCase):
    method test_timedelta_to_seconds (line 278) | def test_timedelta_to_seconds(self):
  class ImportObjectTest (line 283) | class ImportObjectTest(unittest.TestCase):
    method test_import_member (line 284) | def test_import_member(self):
    method test_import_member_unicode (line 287) | def test_import_member_unicode(self):
    method test_import_module (line 290) | def test_import_module(self):
    method test_import_module_unicode (line 293) | def test_import_module_unicode(self):
  class ReUnescapeTest (line 300) | class ReUnescapeTest(unittest.TestCase):
    method test_re_unescape (line 301) | def test_re_unescape(self):
    method test_re_unescape_raises_error_on_invalid_input (line 306) | def test_re_unescape_raises_error_on_invalid_input(self):
  class VersionInfoTest (line 315) | class VersionInfoTest(unittest.TestCase):
    method assert_version_info_compatible (line 316) | def assert_version_info_compatible(self, version, version_info):
    method test_version_info_compatible (line 349) | def test_version_info_compatible(self):
    method test_current_version (line 367) | def test_current_version(self):

FILE: tornado/test/web_test.py
  function relpath (line 63) | def relpath(*a):
  class WebTestCase (line 67) | class WebTestCase(AsyncHTTPTestCase):
    method get_app (line 74) | def get_app(self):
    method get_handlers (line 78) | def get_handlers(self):
    method get_app_kwargs (line 81) | def get_app_kwargs(self):
  class SimpleHandlerTestCase (line 85) | class SimpleHandlerTestCase(WebTestCase):
    method get_handlers (line 93) | def get_handlers(self):
  class HelloHandler (line 97) | class HelloHandler(RequestHandler):
    method get (line 98) | def get(self):
  class CookieTestRequestHandler (line 102) | class CookieTestRequestHandler(RequestHandler):
    method __init__ (line 104) | def __init__(self, cookie_secret="0123456789", key_version=None):
    method get_cookie (line 116) | def get_cookie(self, name) -> str | None:  # type: ignore[override]
    method set_cookie (line 119) | def set_cookie(self, name, value, expires_days=None):  # type: ignore[...
  class SecureCookieV1Test (line 124) | class SecureCookieV1Test(unittest.TestCase):
    method test_round_trip (line 125) | def test_round_trip(self):
    method test_cookie_tampering_future_timestamp (line 130) | def test_cookie_tampering_future_timestamp(self):
    method test_arbitrary_bytes (line 169) | def test_arbitrary_bytes(self):
  class SecureCookieV2Test (line 178) | class SecureCookieV2Test(unittest.TestCase):
    method test_round_trip (line 181) | def test_round_trip(self):
    method test_key_version_roundtrip (line 186) | def test_key_version_roundtrip(self):
    method test_key_version_roundtrip_differing_version (line 193) | def test_key_version_roundtrip_differing_version(self):
    method test_key_version_increment_version (line 200) | def test_key_version_increment_version(self):
    method test_key_version_invalidate_version (line 211) | def test_key_version_invalidate_version(self):
  class FinalReturnTest (line 225) | class FinalReturnTest(WebTestCase):
    method get_handlers (line 228) | def get_handlers(self):
    method get_app_kwargs (line 254) | def get_app_kwargs(self):
    method test_finish_method_return_future (line 257) | def test_finish_method_return_future(self):
    method test_render_method_return_future (line 268) | def test_render_method_return_future(self):
  class CookieTest (line 274) | class CookieTest(WebTestCase):
    method get_handlers (line 275) | def get_handlers(self):
    method test_set_cookie (line 400) | def test_set_cookie(self):
    method test_get_cookie (line 407) | def test_get_cookie(self):
    method test_set_cookie_domain (line 417) | def test_set_cookie_domain(self):
    method test_cookie_special_char (line 424) | def test_cookie_special_char(self):
    method test_set_cookie_forbidden_char (line 450) | def test_set_cookie_forbidden_char(self):
    method test_set_cookie_overwrite (line 456) | def test_set_cookie_overwrite(self):
    method test_set_cookie_max_age (line 463) | def test_set_cookie_max_age(self):
    method test_set_cookie_expires_days (line 468) | def test_set_cookie_expires_days(self):
    method test_set_cookie_false_flags (line 483) | def test_set_cookie_false_flags(self):
    method test_set_cookie_deprecated (line 491) | def test_set_cookie_deprecated(self):
  class AuthRedirectRequestHandler (line 497) | class AuthRedirectRequestHandler(RequestHandler):
    method initialize (line 498) | def initialize(self, login_url):
    method get_login_url (line 501) | def get_login_url(self):
    method get (line 505) | def get(self):
  class AuthRedirectTest (line 510) | class AuthRedirectTest(WebTestCase):
    method get_handlers (line 511) | def get_handlers(self):
    method test_relative_auth_redirect (line 521) | def test_relative_auth_redirect(self):
    method test_absolute_auth_redirect (line 526) | def test_absolute_auth_redirect(self):
  class ConnectionCloseHandler (line 538) | class ConnectionCloseHandler(RequestHandler):
    method initialize (line 539) | def initialize(self, test):
    method get (line 543) | def get(self):
    method on_connection_close (line 547) | def on_connection_close(self):
  class ConnectionCloseTest (line 551) | class ConnectionCloseTest(WebTestCase):
    method get_handlers (line 552) | def get_handlers(self):
    method test_connection_close (line 556) | def test_connection_close(self):
    method on_handler_waiting (line 566) | def on_handler_waiting(self):
    method on_connection_close (line 570) | def on_connection_close(self):
  class EchoHandler (line 575) | class EchoHandler(RequestHandler):
    method get (line 576) | def get(self, *path_args):
  class RequestEncodingTest (line 602) | class RequestEncodingTest(WebTestCase):
    method get_handlers (line 603) | def get_handlers(self):
    method fetch_json (line 606) | def fetch_json(self, path):
    method test_group_question_mark (line 609) | def test_group_question_mark(self):
    method test_group_encoding (line 620) | def test_group_encoding(self):
    method test_slashes (line 631) | def test_slashes(self):
    method test_error (line 643) | def test_error(self):
  class TypeCheckHandler (line 650) | class TypeCheckHandler(RequestHandler):
    method prepare (line 651) | def prepare(self):
    method get (line 678) | def get(self, path_component):
    method post (line 684) | def post(self, path_component):
    method check_type (line 688) | def check_type(self, name, obj, expected_type):
  class DecodeArgHandler (line 694) | class DecodeArgHandler(RequestHandler):
    method decode_argument (line 695) | def decode_argument(self, value, name=None):
    method get (line 704) | def get(self, arg):
  class LinkifyHandler (line 715) | class LinkifyHandler(RequestHandler):
    method get (line 716) | def get(self):
  class UIModuleResourceHandler (line 720) | class UIModuleResourceHandler(RequestHandler):
    method get (line 721) | def get(self):
  class OptionalPathHandler (line 725) | class OptionalPathHandler(RequestHandler):
    method get (line 726) | def get(self, path):
  class MultiHeaderHandler (line 730) | class MultiHeaderHandler(RequestHandler):
    method get (line 731) | def get(self):
  class RedirectHandler (line 738) | class RedirectHandler(RequestHandler):
    method get (line 739) | def get(self):
  class EmptyFlushCallbackHandler (line 748) | class EmptyFlushCallbackHandler(RequestHandler):
    method get (line 750) | def get(self):
  class HeaderInjectionHandler (line 762) | class HeaderInjectionHandler(RequestHandler):
    method get (line 763) | def get(self):
  class SetHeaderHandler (line 774) | class SetHeaderHandler(RequestHandler):
    method get (line 775) | def get(self):
  class GetArgumentHandler (line 794) | class GetArgumentHandler(RequestHandler):
    method prepare (line 795) | def prepare(self):
  class GetArgumentsHandler (line 805) | class GetArgumentsHandler(RequestHandler):
    method prepare (line 806) | def prepare(self):
  class WSGISafeWebTest (line 817) | class WSGISafeWebTest(WebTestCase):
    method get_app_kwargs (line 820) | def get_app_kwargs(self):
    method tearDown (line 846) | def tearDown(self):
    method get_handlers (line 850) | def get_handlers(self):
    method fetch_json (line 882) | def fetch_json(self, *args, **kwargs):
    method test_types (line 887) | def test_types(self):
    method test_decode_argument (line 904) | def test_decode_argument(self):
    method test_decode_argument_invalid_unicode (line 925) | def test_decode_argument_invalid_unicode(self):
    method test_decode_argument_plus (line 933) | def test_decode_argument_plus(self):
    method test_reverse_url (line 948) | def test_reverse_url(self):
    method test_uimodule_unescaped (line 959) | def test_uimodule_unescaped(self):
    method test_uimodule_resources (line 965) | def test_uimodule_resources(self):
    method test_optional_path (line 993) | def test_optional_path(self):
    method test_multi_header (line 997) | def test_multi_header(self):
    method test_redirect (line 1002) | def test_redirect(self):
    method test_web_redirect (line 1010) | def test_web_redirect(self):
    method test_web_redirect_double_slash (line 1018) | def test_web_redirect_double_slash(self):
    method test_header_injection (line 1023) | def test_header_injection(self):
    method test_set_header (line 1027) | def test_set_header(self):
    method test_get_argument (line 1031) | def test_get_argument(self):
    method test_get_query_arguments (line 1051) | def test_get_query_arguments(self):
    method test_get_body_arguments (line 1066) | def test_get_body_arguments(self):
    method test_no_gzip (line 1085) | def test_no_gzip(self):
  class NonWSGIWebTests (line 1091) | class NonWSGIWebTests(WebTestCase):
    method get_handlers (line 1092) | def get_handlers(self):
    method test_empty_flush (line 1095) | def test_empty_flush(self):
  class ErrorResponseTest (line 1100) | class ErrorResponseTest(WebTestCase):
    method get_handlers (line 1101) | def get_handlers(self):
    method test_default (line 1135) | def test_default(self):
    method test_write_error (line 1149) | def test_write_error(self):
    method test_failed_write_error (line 1159) | def test_failed_write_error(self):
  class StaticFileTest (line 1166) | class StaticFileTest(WebTestCase):
    method get_handlers (line 1175) | def get_handlers(self):
    method get_app_kwargs (line 1212) | def get_app_kwargs(self):
    method test_static_files (line 1215) | def test_static_files(self):
    method test_static_files_cacheable (line 1223) | def test_static_files_cacheable(self):
    method test_static_compressed_files (line 1232) | def test_static_compressed_files(self):
    method test_static_windows_special_filenames (line 1245) | def test_static_windows_special_filenames(self):
    method test_static_url (line 1268) | def test_static_url(self):
    method test_absolute_static_url (line 1272) | def test_absolute_static_url(self):
    method test_relative_version_exclusion (line 1279) | def test_relative_version_exclusion(self):
    method test_absolute_version_exclusion (line 1283) | def test_absolute_version_exclusion(self):
    method test_include_host_override (line 1287) | def test_include_host_override(self):
    method _trigger_include_host_check (line 1291) | def _trigger_include_host_check(self, include_host):
    method get_and_head (line 1296) | def get_and_head(self, *args, **kwargs):
    method test_static_304_if_modified_since (line 1317) | def test_static_304_if_modified_since(self):
    method test_static_304_if_none_match (line 1326) | def test_static_304_if_none_match(self):
    method test_static_304_etag_modified_bug (line 1333) | def test_static_304_etag_modified_bug(self):
    method test_static_304_if_modified_since_invalid (line 1344) | def test_static_304_if_modified_since_invalid(self):
    method test_static_if_modified_since_pre_epoch (line 1351) | def test_static_if_modified_since_pre_epoch(self):
    method test_static_if_modified_since_time_zone (line 1361) | def test_static_if_modified_since_time_zone(self):
    method test_static_etag (line 1379) | def test_static_etag(self):
    method test_static_with_range (line 1385) | def test_static_with_range(self):
    method test_static_with_range_full_file (line 1397) | def test_static_with_range_full_file(self):
    method test_static_with_range_full_past_end (line 1410) | def test_static_with_range_full_past_end(self):
    method test_static_with_range_partial_past_end (line 1421) | def test_static_with_range_partial_past_end(self):
    method test_static_with_range_end_edge (line 1432) | def test_static_with_range_end_edge(self):
    method test_static_with_range_neg_end (line 1440) | def test_static_with_range_neg_end(self):
    method test_static_with_range_neg_past_start (line 1448) | def test_static_with_range_neg_past_start(self):
    method test_static_invalid_range (line 1459) | def test_static_invalid_range(self):
    method test_static_unsatisfiable_range_zero_suffix (line 1463) | def test_static_unsatisfia
Condensed preview — 317 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (2,173K chars).
[
  {
    "path": ".coveragerc",
    "chars": 473,
    "preview": "# Test coverage configuration.\n# Usage:\n#   pip install coverage\n#   coverage erase  # clears previous data if any\n#   c"
  },
  {
    "path": ".flake8",
    "chars": 628,
    "preview": "[flake8]\nexclude = .git,.tox,__pycache__,.eggs,build\nmax-line-length = 100\nignore =\n    # E265 block comment should star"
  },
  {
    "path": ".gitattributes",
    "chars": 187,
    "preview": "# Tests of static file handling assume unix-style line endings.\ntornado/test/static/*.txt text eol=lf\ntornado/test/stati"
  },
  {
    "path": ".github/workflows/build.yml",
    "chars": 4252,
    "preview": "# The \"build\" workflow produces wheels (and the sdist) for all python\n# versions/platforms. Where possible (i.e. the bui"
  },
  {
    "path": ".github/workflows/test.yml",
    "chars": 6776,
    "preview": "# The \"test\" workflow is run on every PR and runs tests across all\n# supported python versions and a range of configurat"
  },
  {
    "path": ".github/zizmor.yml",
    "chars": 525,
    "preview": "rules:\n  unpinned-uses:\n    config:\n      policies:\n        # Allow trusted repositories to use ref-pinning instead of h"
  },
  {
    "path": ".gitignore",
    "chars": 157,
    "preview": "*.pyc\n*.pyo\n*.so\n*.class\n*~\nbuild/\n/dist/\nMANIFEST\n/tornado.egg-info/\n.tox/\n.vagrant\n/.coverage\n/htmlcov/\n/env/\n# Used i"
  },
  {
    "path": ".readthedocs.yaml",
    "chars": 189,
    "preview": "version: 2\n\nbuild:\n  os: ubuntu-22.04\n  tools:\n    python: \"3.11\"\n\nsphinx:\n  configuration: docs/conf.py\n\nformats:\n  - p"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 2038,
    "preview": "# Contributing to Tornado\n\n## The basics\n\n* We use `black` as code formatter and recommend configuring your editor to ru"
  },
  {
    "path": "LICENSE",
    "chars": 11358,
    "preview": "\n                                 Apache License\n                           Version 2.0, January 2004\n                  "
  },
  {
    "path": "MANIFEST.in",
    "chars": 823,
    "preview": "recursive-include docs *\nprune docs/build\ninclude tornado/py.typed\ninclude tornado/speedups.c\ninclude tornado/test/READM"
  },
  {
    "path": "README.rst",
    "chars": 1599,
    "preview": "Tornado Web Server\n==================\n\n.. image:: https://badges.gitter.im/Join%20Chat.svg\n   :alt: Join the chat at htt"
  },
  {
    "path": "SECURITY.md",
    "chars": 528,
    "preview": "# Security Policy\n\n## Supported Versions\n\nIn general, due to limited maintainer bandwidth, only the latest version of\nTo"
  },
  {
    "path": "codecov.yml",
    "chars": 37,
    "preview": "comment: off\ncoverage:\n  status: off\n"
  },
  {
    "path": "demos/README.rst",
    "chars": 927,
    "preview": "Tornado Demo Apps\n-----------------\n\nThis directory contains several example apps that illustrate the usage of\nvarious T"
  },
  {
    "path": "demos/blog/Dockerfile",
    "chars": 210,
    "preview": "FROM python:3.7\n\nEXPOSE 8888\n\nRUN mkdir -p /usr/src/app\nWORKDIR /usr/src/app\n\nCOPY requirements.txt /usr/src/app/\nRUN pi"
  },
  {
    "path": "demos/blog/README",
    "chars": 2106,
    "preview": "Running the Tornado Blog example app\n====================================\n\nThis demo is a simple blogging engine that us"
  },
  {
    "path": "demos/blog/blog.py",
    "chars": 10685,
    "preview": "#!/usr/bin/env python3\n#\n# Copyright 2009 Facebook\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"); y"
  },
  {
    "path": "demos/blog/docker-compose.yml",
    "chars": 242,
    "preview": "postgres:\n  image: postgres:10.3\n  environment:\n    POSTGRES_USER: blog\n    POSTGRES_PASSWORD: blog\n    POSTGRES_DB: blo"
  },
  {
    "path": "demos/blog/requirements.txt",
    "chars": 39,
    "preview": "aiopg\nbcrypt\nmarkdown\npsycopg2\ntornado\n"
  },
  {
    "path": "demos/blog/schema.sql",
    "chars": 1354,
    "preview": "-- Copyright 2009 FriendFeed\n--\n-- Licensed under the Apache License, Version 2.0 (the \"License\"); you may\n-- not use th"
  },
  {
    "path": "demos/blog/static/blog.css",
    "chars": 2130,
    "preview": "/*\n * Copyright 2009 Facebook\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may\n * not use t"
  },
  {
    "path": "demos/blog/templates/archive.html",
    "chars": 673,
    "preview": "{% extends \"base.html\" %}\n\n{% block head %}\n  <style type=\"text/css\">\n    ul.archive {\n      list-style-type: none;\n    "
  },
  {
    "path": "demos/blog/templates/base.html",
    "chars": 988,
    "preview": "<!DOCTYPE html>\n<html>\n\n<head>\n  <meta charset=\"UTF-8\">\n  <title>{{ escape(handler.settings[\"blog_title\"]) }}</title>\n  "
  },
  {
    "path": "demos/blog/templates/compose.html",
    "chars": 1549,
    "preview": "{% extends \"base.html\" %}\n\n{% block body %}\n  <form action=\"{{ request.path }}\" method=\"post\" class=\"compose\">\n    <div "
  },
  {
    "path": "demos/blog/templates/create_author.html",
    "chars": 307,
    "preview": "{% extends \"base.html\" %}\n\n{% block body %}\n<form action=\"/auth/create\" method=\"POST\">\n  Email: <input name=\"email\" type"
  },
  {
    "path": "demos/blog/templates/entry.html",
    "chars": 82,
    "preview": "{% extends \"base.html\" %}\n\n{% block body %}\n  {% module Entry(entry) %}\n{% end %}\n"
  },
  {
    "path": "demos/blog/templates/feed.xml",
    "chars": 1363,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<feed xmlns=\"http://www.w3.org/2005/Atom\">\n  {% set date_format = \"%Y-%m-%dT%H:%M"
  },
  {
    "path": "demos/blog/templates/home.html",
    "chars": 180,
    "preview": "{% extends \"base.html\" %}\n\n{% block body %}\n  {% for entry in entries %}\n    {% module Entry(entry) %}\n  {% end %}\n  <di"
  },
  {
    "path": "demos/blog/templates/login.html",
    "chars": 342,
    "preview": "{% extends \"base.html\" %}\n\n{% block body %}\n{% if error %}\n<span style=\"color: red\">Error: {{ error }}</span><p>\n{% end "
  },
  {
    "path": "demos/blog/templates/modules/entry.html",
    "chars": 373,
    "preview": "<div class=\"entry\">\n  <h1><a href=\"/entry/{{ entry.slug }}\">{{ entry.title }}</a></h1>\n  <div class=\"date\">{{ locale.for"
  },
  {
    "path": "demos/chat/chatdemo.py",
    "chars": 4384,
    "preview": "#!/usr/bin/env python3\n#\n# Copyright 2009 Facebook\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"); y"
  },
  {
    "path": "demos/chat/static/chat.css",
    "chars": 989,
    "preview": "/*\n * Copyright 2009 FriendFeed\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may\n * not use"
  },
  {
    "path": "demos/chat/static/chat.js",
    "chars": 4033,
    "preview": "// Copyright 2009 FriendFeed\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\"); you may\n// not use th"
  },
  {
    "path": "demos/chat/templates/index.html",
    "chars": 1127,
    "preview": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\">\n    <title>Tornado Chat Demo</title>\n    <link rel=\"styleshee"
  },
  {
    "path": "demos/chat/templates/message.html",
    "chars": 91,
    "preview": "<div class=\"message\" id=\"m{{ message[\"id\"] }}\">{% module linkify(message[\"body\"]) %}</div>\n"
  },
  {
    "path": "demos/facebook/README",
    "chars": 399,
    "preview": "Running the Tornado Facebook example\n====================================\n\nTo run this example, you must register a Face"
  },
  {
    "path": "demos/facebook/facebook.py",
    "chars": 3954,
    "preview": "#!/usr/bin/env python3\n#\n# Copyright 2009 Facebook\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"); y"
  },
  {
    "path": "demos/facebook/static/facebook.css",
    "chars": 1492,
    "preview": "/*\n * Copyright 2009 Facebook\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may\n * not use t"
  },
  {
    "path": "demos/facebook/static/facebook.js",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "demos/facebook/templates/modules/post.html",
    "chars": 766,
    "preview": "<div class=\"post\">\n  <div class=\"picture\">\n    {% set author_url=\"http://www.facebook.com/profile.php?id=\" + escape(post"
  },
  {
    "path": "demos/facebook/templates/stream.html",
    "chars": 627,
    "preview": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\">\n    <title>Tornado Facebook Stream Demo</title>\n    <link rel"
  },
  {
    "path": "demos/file_upload/file_receiver.py",
    "chars": 1562,
    "preview": "#!/usr/bin/env python\n\n\"\"\"Usage: python file_receiver.py\n\nDemonstrates a server that receives a multipart-form-encoded s"
  },
  {
    "path": "demos/file_upload/file_uploader.py",
    "chars": 3388,
    "preview": "#!/usr/bin/env python\n\n\"\"\"Usage: python file_uploader.py [--put] file1.txt file2.png ...\n\nDemonstrates uploading files t"
  },
  {
    "path": "demos/google_auth/.gitignore",
    "chars": 9,
    "preview": "main.cfg\n"
  },
  {
    "path": "demos/google_auth/main.py",
    "chars": 3991,
    "preview": "\"\"\"Demo app for GoogleOAuth2Mixin\n\nRecommended usage:\n- Register an app with Google following the instructions at\n  http"
  },
  {
    "path": "demos/helloworld/helloworld.py",
    "chars": 1155,
    "preview": "#!/usr/bin/env python\n#\n# Copyright 2009 Facebook\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"); yo"
  },
  {
    "path": "demos/tcpecho/README.md",
    "chars": 604,
    "preview": "TCP echo demo\n=============\n\nThis demo shows how to use Tornado's asynchronous TCP client and\nserver by implementing `ha"
  },
  {
    "path": "demos/tcpecho/client.py",
    "chars": 696,
    "preview": "#!/usr/bin/env python\n\nimport asyncio\nfrom tornado.tcpclient import TCPClient\nfrom tornado.options import options, defin"
  },
  {
    "path": "demos/tcpecho/server.py",
    "chars": 1118,
    "preview": "#!/usr/bin/env python\n\nimport asyncio\nimport logging\nfrom tornado import gen\nfrom tornado.iostream import StreamClosedEr"
  },
  {
    "path": "demos/websocket/chatdemo.py",
    "chars": 3013,
    "preview": "#!/usr/bin/env python\n#\n# Copyright 2009 Facebook\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"); yo"
  },
  {
    "path": "demos/websocket/static/chat.css",
    "chars": 989,
    "preview": "/*\n * Copyright 2009 FriendFeed\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may\n * not use"
  },
  {
    "path": "demos/websocket/static/chat.js",
    "chars": 2013,
    "preview": "// Copyright 2009 FriendFeed\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\"); you may\n// not use th"
  },
  {
    "path": "demos/websocket/templates/index.html",
    "chars": 1100,
    "preview": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\">\n    <title>Tornado Chat Demo</title>\n    <link rel=\"styleshee"
  },
  {
    "path": "demos/websocket/templates/message.html",
    "chars": 91,
    "preview": "<div class=\"message\" id=\"m{{ message[\"id\"] }}\">{% module linkify(message[\"body\"]) %}</div>\n"
  },
  {
    "path": "demos/webspider/webspider.py",
    "chars": 2699,
    "preview": "#!/usr/bin/env python3\n\nimport asyncio\nimport time\nfrom datetime import timedelta\n\nfrom html.parser import HTMLParser\nfr"
  },
  {
    "path": "docs/Makefile",
    "chars": 812,
    "preview": ".PHONY: all\nall: sphinx\n\n# No -W for doctests because that disallows tests with empty output.\nSPHINX_DOCTEST_OPTS=-n -d "
  },
  {
    "path": "docs/asyncio.rst",
    "chars": 518,
    "preview": "``tornado.platform.asyncio`` --- Bridge between ``asyncio`` and Tornado\n================================================"
  },
  {
    "path": "docs/auth.rst",
    "chars": 1136,
    "preview": "``tornado.auth`` --- Third-party login with OpenID and OAuth\n==========================================================="
  },
  {
    "path": "docs/autoreload.rst",
    "chars": 201,
    "preview": "``tornado.autoreload`` --- Automatically detect code changes in development\n============================================"
  },
  {
    "path": "docs/caresresolver.rst",
    "chars": 1109,
    "preview": "``tornado.platform.caresresolver`` --- Asynchronous DNS Resolver using C-Ares\n=========================================="
  },
  {
    "path": "docs/concurrent.rst",
    "chars": 1206,
    "preview": "``tornado.concurrent`` --- Work with ``Future`` objects\n=======================================================\n\n.. test"
  },
  {
    "path": "docs/conf.py",
    "chars": 4327,
    "preview": "import os\nimport sphinx.errors\nimport sys\n\n# Ensure we get the local copy of tornado instead of what's on the standard p"
  },
  {
    "path": "docs/coroutine.rst",
    "chars": 106,
    "preview": "Coroutines and concurrency\n==========================\n\n.. toctree::\n\n   gen\n   locks\n   queues\n   process\n"
  },
  {
    "path": "docs/escape.rst",
    "chars": 912,
    "preview": "``tornado.escape`` --- Escaping and string manipulation\n=======================================================\n\n.. auto"
  },
  {
    "path": "docs/faq.rst",
    "chars": 3783,
    "preview": "Frequently Asked Questions\n==========================\n\n.. contents::\n   :local:\n\nWhy isn't this example with ``time.slee"
  },
  {
    "path": "docs/gen.rst",
    "chars": 1047,
    "preview": "``tornado.gen`` --- Generator-based coroutines\n==============================================\n\n.. testsetup::\n\n   from t"
  },
  {
    "path": "docs/guide/async.rst",
    "chars": 4567,
    "preview": "Asynchronous and non-Blocking I/O\n---------------------------------\n\nReal-time web features require a long-lived mostly-"
  },
  {
    "path": "docs/guide/coroutines.rst",
    "chars": 10894,
    "preview": "Coroutines\n==========\n\n.. testsetup::\n\n   from tornado import gen\n\n**Coroutines** are the recommended way to write async"
  },
  {
    "path": "docs/guide/intro.rst",
    "chars": 1409,
    "preview": "Introduction\n------------\n\n`Tornado <http://www.tornadoweb.org>`_ is a Python web framework and\nasynchronous networking "
  },
  {
    "path": "docs/guide/queues.rst",
    "chars": 1317,
    "preview": ":class:`~tornado.queues.Queue` example - a concurrent web spider\n======================================================="
  },
  {
    "path": "docs/guide/running.rst",
    "chars": 10878,
    "preview": "Running and deploying\n=====================\n\nSince Tornado supplies its own HTTPServer, running and deploying it is\na li"
  },
  {
    "path": "docs/guide/security.rst",
    "chars": 12523,
    "preview": "Authentication and security\n===========================\n\n.. testsetup::\n\n   import tornado\n\nCookies and signed cookies\n~"
  },
  {
    "path": "docs/guide/structure.rst",
    "chars": 14167,
    "preview": ".. currentmodule:: tornado.web\n\n.. testsetup::\n\n   import tornado\n\nStructure of a Tornado web application\n=============="
  },
  {
    "path": "docs/guide/templates.rst",
    "chars": 13579,
    "preview": "Templates and UI\n================\n\n.. testsetup::\n\n   import tornado\n\nTornado includes a simple, fast, and flexible temp"
  },
  {
    "path": "docs/guide.rst",
    "chars": 180,
    "preview": "User's guide\n============\n\n.. toctree::\n\n   guide/intro\n   guide/async\n   guide/coroutines\n   guide/queues\n   guide/stru"
  },
  {
    "path": "docs/http.rst",
    "chars": 124,
    "preview": "HTTP servers and clients\n========================\n\n.. toctree::\n\n   httpserver\n   httpclient\n   httputil\n   http1connect"
  },
  {
    "path": "docs/http1connection.rst",
    "chars": 192,
    "preview": "``tornado.http1connection`` -- HTTP/1.x client/server implementation\n==================================================="
  },
  {
    "path": "docs/httpclient.rst",
    "chars": 2085,
    "preview": "``tornado.httpclient`` --- Asynchronous HTTP client\n===================================================\n\n.. automodule::"
  },
  {
    "path": "docs/httpserver.rst",
    "chars": 910,
    "preview": "``tornado.httpserver`` --- Non-blocking HTTP server\n===================================================\n\n.. automodule::"
  },
  {
    "path": "docs/httputil.rst",
    "chars": 214,
    "preview": "``tornado.httputil`` --- Manipulate HTTP headers and URLs\n=========================================================\n\n.. "
  },
  {
    "path": "docs/index.rst",
    "chars": 5629,
    "preview": ".. title:: Tornado Web Server\n\n.. meta::\n    :google-site-verification: g4bVhgwbVO1d9apCUsT-eKlApg31Cygbp8VGZY8Rf0g\n\n|To"
  },
  {
    "path": "docs/integration.rst",
    "chars": 134,
    "preview": "Integration with other services\n===============================\n\n.. toctree::\n\n   auth\n   wsgi\n   caresresolver\n   twist"
  },
  {
    "path": "docs/ioloop.rst",
    "chars": 1263,
    "preview": "``tornado.ioloop`` --- Main event loop\n======================================\n\n.. automodule:: tornado.ioloop\n\n   IOLoop"
  },
  {
    "path": "docs/iostream.rst",
    "chars": 1394,
    "preview": "``tornado.iostream`` --- Convenient wrappers for non-blocking sockets\n=================================================="
  },
  {
    "path": "docs/locale.rst",
    "chars": 149,
    "preview": "``tornado.locale`` --- Internationalization support\n===================================================\n\n.. automodule::"
  },
  {
    "path": "docs/locks.rst",
    "chars": 1101,
    "preview": "``tornado.locks`` -- Synchronization primitives\n===============================================\n\n.. versionadded:: 4.2\n\n"
  },
  {
    "path": "docs/log.rst",
    "chars": 114,
    "preview": "``tornado.log`` --- Logging support\n===================================\n\n.. automodule:: tornado.log\n   :members:\n"
  },
  {
    "path": "docs/netutil.rst",
    "chars": 158,
    "preview": "``tornado.netutil`` --- Miscellaneous network utilities\n=======================================================\n\n.. auto"
  },
  {
    "path": "docs/networking.rst",
    "chars": 122,
    "preview": "Asynchronous networking\n=======================\n\n.. toctree::\n\n   ioloop\n   iostream\n   netutil\n   tcpclient\n   tcpserve"
  },
  {
    "path": "docs/options.rst",
    "chars": 1036,
    "preview": "``tornado.options`` --- Command-line parsing\n============================================\n\n.. automodule:: tornado.optio"
  },
  {
    "path": "docs/process.rst",
    "chars": 251,
    "preview": "``tornado.process`` --- Utilities for multiple processes\n========================================================\n\n.. au"
  },
  {
    "path": "docs/queues.rst",
    "chars": 523,
    "preview": "``tornado.queues`` -- Queues for coroutines\n===========================================\n\n.. versionadded:: 4.2\n\n.. autom"
  },
  {
    "path": "docs/releases/v1.0.0.rst",
    "chars": 2667,
    "preview": "What's new in Tornado 1.0\n=========================\n\nJuly 22, 2010\n-------------\n\n::\n\n    We are pleased to announce the"
  },
  {
    "path": "docs/releases/v1.0.1.rst",
    "chars": 262,
    "preview": "What's new in Tornado 1.0.1\n===========================\n\nAug 13, 2010\n------------\n\n::\n    \n    This release fixes a bug"
  },
  {
    "path": "docs/releases/v1.1.0.rst",
    "chars": 2693,
    "preview": "What's new in Tornado 1.1\n=========================\n\nSep 7, 2010\n-----------\n\n::\n\n    We are pleased to announce the rel"
  },
  {
    "path": "docs/releases/v1.1.1.rst",
    "chars": 873,
    "preview": "What's new in Tornado 1.1.1\n===========================\n\nFeb 8, 2011\n-----------\n\n::\n\n    Tornado 1.1.1 is a BACKWARDS-I"
  },
  {
    "path": "docs/releases/v1.2.0.rst",
    "chars": 5743,
    "preview": "What's new in Tornado 1.2\n=========================\n\nFeb 20, 2011\n------------\n\n::\n\n    We are pleased to announce the r"
  },
  {
    "path": "docs/releases/v1.2.1.rst",
    "chars": 753,
    "preview": "What's new in Tornado 1.2.1\n===========================\n\nMar 3, 2011\n-----------\n\n::\n\n    We are pleased to announce the"
  },
  {
    "path": "docs/releases/v2.0.0.rst",
    "chars": 2702,
    "preview": "What's new in Tornado 2.0\n=========================\n\nJun 21, 2011\n------------\n\n::\n\n    Major changes:\n    * Template ou"
  },
  {
    "path": "docs/releases/v2.1.0.rst",
    "chars": 7576,
    "preview": "What's new in Tornado 2.1\n=========================\n\nSep 20, 2011\n------------\n\nBackwards-incompatible changes\n~~~~~~~~~"
  },
  {
    "path": "docs/releases/v2.1.1.rst",
    "chars": 1118,
    "preview": "What's new in Tornado 2.1.1\n===========================\n\nOct 4, 2011\n-----------\n\nBug fixes\n~~~~~~~~~\n\n* Fixed handling "
  },
  {
    "path": "docs/releases/v2.2.0.rst",
    "chars": 5583,
    "preview": "What's new in Tornado 2.2\n=========================\n\nJan 30, 2012\n------------\n\nHighlights\n~~~~~~~~~~\n\n* Updated and exp"
  },
  {
    "path": "docs/releases/v2.2.1.rst",
    "chars": 573,
    "preview": "What's new in Tornado 2.2.1\n===========================\n\nApr 23, 2012\n------------\n\nSecurity fixes\n~~~~~~~~~~~~~~\n\n* `to"
  },
  {
    "path": "docs/releases/v2.3.0.rst",
    "chars": 5077,
    "preview": "What's new in Tornado 2.3\n=========================\n\nMay 31, 2012\n------------\n\nHTTP clients\n~~~~~~~~~~~~\n\n* `tornado.ht"
  },
  {
    "path": "docs/releases/v2.4.0.rst",
    "chars": 2885,
    "preview": "What's new in Tornado 2.4\n=========================\n\nSep 4, 2012\n-----------\n\nGeneral\n~~~~~~~\n\n* Fixed Python 3 bugs in "
  },
  {
    "path": "docs/releases/v2.4.1.rst",
    "chars": 467,
    "preview": "What's new in Tornado 2.4.1\n===========================\n\nNov 24, 2012\n------------\n\nBug fixes\n~~~~~~~~~\n\n* Fixed a memor"
  },
  {
    "path": "docs/releases/v3.0.0.rst",
    "chars": 21098,
    "preview": "What's new in Tornado 3.0\n=========================\n\nMar 29, 2013\n------------\n\nHighlights\n^^^^^^^^^^\n\n* The ``callback`"
  },
  {
    "path": "docs/releases/v3.0.1.rst",
    "chars": 1021,
    "preview": "What's new in Tornado 3.0.1\n===========================\n\nApr 8, 2013\n-----------\n\n* The interface of `tornado.auth.Faceb"
  },
  {
    "path": "docs/releases/v3.0.2.rst",
    "chars": 417,
    "preview": "What's new in Tornado 3.0.2\n===========================\n\nJun 2, 2013\n-----------\n\n* `tornado.auth.TwitterMixin` now defa"
  },
  {
    "path": "docs/releases/v3.1.0.rst",
    "chars": 10631,
    "preview": "What's new in Tornado 3.1\n=========================\n\nJun 15, 2013\n------------\n\nMultiple modules\n~~~~~~~~~~~~~~~~\n\n* Man"
  },
  {
    "path": "docs/releases/v3.1.1.rst",
    "chars": 348,
    "preview": "What's new in Tornado 3.1.1\n===========================\n\nSep 1, 2013\n-----------\n\n* `.StaticFileHandler` no longer fails"
  },
  {
    "path": "docs/releases/v3.2.0.rst",
    "chars": 7270,
    "preview": "What's new in Tornado 3.2\n=========================\n\nJan 14, 2014\n------------\n\nInstallation\n~~~~~~~~~~~~\n* Tornado now "
  },
  {
    "path": "docs/releases/v3.2.1.rst",
    "chars": 1665,
    "preview": "What's new in Tornado 3.2.1\n===========================\n\nMay 5, 2014\n-----------\n\nSecurity fixes\n~~~~~~~~~~~~~~\n\n* The s"
  },
  {
    "path": "docs/releases/v3.2.2.rst",
    "chars": 920,
    "preview": "What's new in Tornado 3.2.2\n===========================\n\nJune 3, 2014\n------------\n\nSecurity fixes\n~~~~~~~~~~~~~~\n\n* The"
  },
  {
    "path": "docs/releases/v4.0.0.rst",
    "chars": 14923,
    "preview": "What's new in Tornado 4.0\n=========================\n\nJuly 15, 2014\n-------------\n\nHighlights\n~~~~~~~~~~\n\n* The `tornado."
  },
  {
    "path": "docs/releases/v4.0.1.rst",
    "chars": 861,
    "preview": "What's new in Tornado 4.0.1\n===========================\n\nAug 12, 2014\n------------\n\n* The build will now fall back to pu"
  },
  {
    "path": "docs/releases/v4.0.2.rst",
    "chars": 824,
    "preview": "What's new in Tornado 4.0.2\n===========================\n\nSept 10, 2014\n-------------\n\nBug fixes\n~~~~~~~~~\n\n* Fixed a bug"
  },
  {
    "path": "docs/releases/v4.1.0.rst",
    "chars": 7851,
    "preview": "What's new in Tornado 4.1\n=========================\n\nFeb 7, 2015\n-----------\n\nHighlights\n~~~~~~~~~~\n\n* If a `.Future` co"
  },
  {
    "path": "docs/releases/v4.2.0.rst",
    "chars": 8800,
    "preview": "What's new in Tornado 4.2\n=========================\n\nMay 26, 2015\n------------\n\nBackwards-compatibility notes\n~~~~~~~~~~"
  },
  {
    "path": "docs/releases/v4.2.1.rst",
    "chars": 325,
    "preview": "What's new in Tornado 4.2.1\n===========================\n\nJul 17, 2015\n------------\n\nSecurity fix\n~~~~~~~~~~~~\n\n* This re"
  },
  {
    "path": "docs/releases/v4.3.0.rst",
    "chars": 6985,
    "preview": "What's new in Tornado 4.3\n=========================\n\nNov 6, 2015\n-----------\n\nHighlights\n~~~~~~~~~~\n\n* The new async/awa"
  },
  {
    "path": "docs/releases/v4.4.0.rst",
    "chars": 2638,
    "preview": "What's new in Tornado 4.4\n=========================\n\nJul 15, 2016\n------------\n\nGeneral\n~~~~~~~\n\n* Tornado now requires "
  },
  {
    "path": "docs/releases/v4.4.1.rst",
    "chars": 248,
    "preview": "What's new in Tornado 4.4.1\n===========================\n\nJul 23, 2016\n------------\n\n`tornado.web`\n~~~~~~~~~~~~~\n\n* Fixed"
  },
  {
    "path": "docs/releases/v4.4.2.rst",
    "chars": 755,
    "preview": "What's new in Tornado 4.4.2\n===========================\n\nOct 1, 2016\n------------\n\nSecurity fixes\n~~~~~~~~~~~~~~\n\n* A di"
  },
  {
    "path": "docs/releases/v4.4.3.rst",
    "chars": 276,
    "preview": "What's new in Tornado 4.4.3\n===========================\n\nMar 30, 2017\n------------\n\nBug fixes\n~~~~~~~~~\n\n* The `tornado."
  },
  {
    "path": "docs/releases/v4.5.0.rst",
    "chars": 7142,
    "preview": "What's new in Tornado 4.5\n=========================\n\nApr 16, 2017\n------------\n\nBackwards-compatibility warning\n~~~~~~~~"
  },
  {
    "path": "docs/releases/v4.5.1.rst",
    "chars": 285,
    "preview": "What's new in Tornado 4.5.1\n===========================\n\nApr 20, 2017\n------------\n\n`tornado.log`\n~~~~~~~~~~~~~\n\n- Impro"
  },
  {
    "path": "docs/releases/v4.5.2.rst",
    "chars": 323,
    "preview": "What's new in Tornado 4.5.2\n===========================\n\nAug 27, 2017\n------------\n\nBug Fixes\n~~~~~~~~~\n\n- Tornado now s"
  },
  {
    "path": "docs/releases/v4.5.3.rst",
    "chars": 1189,
    "preview": "What's new in Tornado 4.5.3\n===========================\n\nJan 6, 2018\n------------\n\n`tornado.curl_httpclient`\n~~~~~~~~~~~"
  },
  {
    "path": "docs/releases/v5.0.0.rst",
    "chars": 13117,
    "preview": "What's new in Tornado 5.0\n=========================\n\nMar 5, 2018\n-----------\n\nHighlights\n~~~~~~~~~~\n\n- The focus of this"
  },
  {
    "path": "docs/releases/v5.0.1.rst",
    "chars": 279,
    "preview": "What's new in Tornado 5.0.1\n===========================\n\nMar 18, 2018\n------------\n\nBug fix\n~~~~~~~\n\n- This release rest"
  },
  {
    "path": "docs/releases/v5.0.2.rst",
    "chars": 621,
    "preview": "What's new in Tornado 5.0.2\n===========================\n\nApr 7, 2018\n-----------\n\nBug fixes\n~~~~~~~~~\n\n- Fixed a memory "
  },
  {
    "path": "docs/releases/v5.1.0.rst",
    "chars": 7840,
    "preview": "What's new in Tornado 5.1\n=========================\n\nJuly 12, 2018\n-------------\n\nDeprecation notice\n~~~~~~~~~~~~~~~~~~\n"
  },
  {
    "path": "docs/releases/v5.1.1.rst",
    "chars": 390,
    "preview": "What's new in Tornado 5.1.1\n===========================\n\nSep 16, 2018\n------------\n\nBug fixes\n~~~~~~~~~\n\n- Fixed an case"
  },
  {
    "path": "docs/releases/v6.0.0.rst",
    "chars": 5573,
    "preview": "What's new in Tornado 6.0\n=========================\n\nMar 1, 2019\n-----------\n\nBackwards-incompatible changes\n~~~~~~~~~~~"
  },
  {
    "path": "docs/releases/v6.0.1.rst",
    "chars": 202,
    "preview": "What's new in Tornado 6.0.1\n===========================\n\nMar 3, 2019\n-----------\n\nBug fixes\n~~~~~~~~~\n\n- Fixed issues wi"
  },
  {
    "path": "docs/releases/v6.0.2.rst",
    "chars": 346,
    "preview": "What's new in Tornado 6.0.2\n===========================\n\nMar 23, 2019\n------------\n\nBug fixes\n~~~~~~~~~\n\n- `.WebSocketHa"
  },
  {
    "path": "docs/releases/v6.0.3.rst",
    "chars": 434,
    "preview": "What's new in Tornado 6.0.3\n===========================\n\nJun 22, 2019\n------------\n\nBug fixes\n~~~~~~~~~\n\n- `.gen.with_ti"
  },
  {
    "path": "docs/releases/v6.0.4.rst",
    "chars": 636,
    "preview": "What's new in Tornado 6.0.4\n===========================\n\nMar 3, 2020\n-----------\n\nGeneral changes\n~~~~~~~~~~~~~~~\n\n- Bin"
  },
  {
    "path": "docs/releases/v6.1.0.rst",
    "chars": 3691,
    "preview": "What's new in Tornado 6.1.0\n===========================\n\nOct 30, 2020\n------------\n\nDeprecation notice\n~~~~~~~~~~~~~~~~~"
  },
  {
    "path": "docs/releases/v6.2.0.rst",
    "chars": 5100,
    "preview": "What's new in Tornado 6.2.0\n===========================\n\nJul 3, 2022\n-----------\n\nDeprecation notice\n~~~~~~~~~~~~~~~~~~\n"
  },
  {
    "path": "docs/releases/v6.3.0.rst",
    "chars": 4225,
    "preview": "What's new in Tornado 6.3.0\n===========================\n\nApr 17, 2023\n------------\n\nHighlights\n~~~~~~~~~~\n\n- The new `.A"
  },
  {
    "path": "docs/releases/v6.3.1.rst",
    "chars": 311,
    "preview": "What's new in Tornado 6.3.1\n===========================\n\nApr 21, 2023\n------------\n\n``tornado.web``\n~~~~~~~~~~~~~~~\n\n- `"
  },
  {
    "path": "docs/releases/v6.3.2.rst",
    "chars": 220,
    "preview": "What's new in Tornado 6.3.2\n===========================\n\nMay 13, 2023\n------------\n\nSecurity improvements\n~~~~~~~~~~~~~~"
  },
  {
    "path": "docs/releases/v6.3.3.rst",
    "chars": 362,
    "preview": "What's new in Tornado 6.3.3\n===========================\n\nAug 11, 2023\n------------\n\nSecurity improvements\n~~~~~~~~~~~~~~"
  },
  {
    "path": "docs/releases/v6.4.0.rst",
    "chars": 3278,
    "preview": "What's new in Tornado 6.4.0\n===========================\n\nNov 28, 2023\n------------\n\nGeneral Changes\n~~~~~~~~~~~~~~~\n\n- P"
  },
  {
    "path": "docs/releases/v6.4.1.rst",
    "chars": 1623,
    "preview": "What's new in Tornado 6.4.1\n===========================\n\nJun 6, 2024\n-----------\n\nSecurity Improvements\n~~~~~~~~~~~~~~~~"
  },
  {
    "path": "docs/releases/v6.4.2.rst",
    "chars": 418,
    "preview": "What's new in Tornado 6.4.2\n===========================\n\nNov 21, 2024\n------------\n\nSecurity Improvements\n~~~~~~~~~~~~~~"
  },
  {
    "path": "docs/releases/v6.5.0.rst",
    "chars": 5139,
    "preview": "What's new in Tornado 6.5.0\n===========================\n\nMay 15, 2025\n------------\n\nSecurity Improvements\n~~~~~~~~~~~~~~"
  },
  {
    "path": "docs/releases/v6.5.1.rst",
    "chars": 282,
    "preview": "What's new in Tornado 6.5.1\n===========================\n\nMay 22, 2025\n------------\n\nBug fixes\n~~~~~~~~~\n\n- Fixed a bug i"
  },
  {
    "path": "docs/releases/v6.5.2.rst",
    "chars": 675,
    "preview": "What's new in Tornado 6.5.2\n===========================\n\nAug 8, 2025\n-----------\n\nBug fixes\n~~~~~~~~~\n\n- Fixed a bug tha"
  },
  {
    "path": "docs/releases/v6.5.3.rst",
    "chars": 1912,
    "preview": "What's new in Tornado 6.5.3\n===========================\n\nDec 10, 2025\n------------\n\nSecurity fixes\n~~~~~~~~~~~~~~\n- Fixe"
  },
  {
    "path": "docs/releases/v6.5.4.rst",
    "chars": 414,
    "preview": "What's new in Tornado 6.5.4\n===========================\n\nDec 15, 2025\n------------\n\nBug fixes\n~~~~~~~~~\n\n- The ``in`` op"
  },
  {
    "path": "docs/releases/v6.5.5.rst",
    "chars": 1004,
    "preview": "What's new in Tornado 6.5.5\n===========================\n\nMar 10, 2026\n------------\n\nSecurity fixes\n~~~~~~~~~~~~~~\n\n- ``m"
  },
  {
    "path": "docs/releases.rst",
    "chars": 1237,
    "preview": "Release notes\n=============\n\n.. toctree::\n   :maxdepth: 2\n\n   releases/v6.5.5\n   releases/v6.5.4\n   releases/v6.5.3\n   r"
  },
  {
    "path": "docs/routing.rst",
    "chars": 152,
    "preview": "``tornado.routing`` --- Basic routing implementation\n====================================================\n\n.. automodule"
  },
  {
    "path": "docs/tcpclient.rst",
    "chars": 162,
    "preview": "``tornado.tcpclient`` --- `.IOStream` connection factory\n========================================================\n\n.. au"
  },
  {
    "path": "docs/tcpserver.rst",
    "chars": 171,
    "preview": "``tornado.tcpserver`` --- Basic `.IOStream`-based TCP server\n==========================================================="
  },
  {
    "path": "docs/template.rst",
    "chars": 546,
    "preview": "``tornado.template`` --- Flexible output generation\n===================================================\n\n.. automodule::"
  },
  {
    "path": "docs/testing.rst",
    "chars": 739,
    "preview": "``tornado.testing`` --- Unit testing support for asynchronous code\n====================================================="
  },
  {
    "path": "docs/twisted.rst",
    "chars": 1384,
    "preview": "``tornado.platform.twisted`` --- Bridges between Twisted and Tornado\n==================================================="
  },
  {
    "path": "docs/util.rst",
    "chars": 619,
    "preview": "``tornado.util`` --- General-purpose utilities\n==============================================\n\n.. testsetup::\n\n   from t"
  },
  {
    "path": "docs/utilities.rst",
    "chars": 100,
    "preview": "Utilities\n=========\n\n.. toctree::\n\n   autoreload\n   concurrent\n   log\n   options\n   testing\n   util\n"
  },
  {
    "path": "docs/web.rst",
    "chars": 15452,
    "preview": "``tornado.web`` --- ``RequestHandler`` and ``Application`` classes\n====================================================="
  },
  {
    "path": "docs/webframework.rst",
    "chars": 106,
    "preview": "Web framework\n=============\n\n.. toctree::\n\n   web\n   template\n   routing\n   escape\n   locale\n   websocket\n"
  },
  {
    "path": "docs/websocket.rst",
    "chars": 1178,
    "preview": "``tornado.websocket`` --- Bidirectional communication to the browser\n==================================================="
  },
  {
    "path": "docs/wsgi.rst",
    "chars": 237,
    "preview": "``tornado.wsgi`` --- Interoperability with other Python frameworks and servers\n========================================="
  },
  {
    "path": "maint/README",
    "chars": 161,
    "preview": "This directory contains tools and scripts that are used in the development\nand maintenance of Tornado itself, but are pr"
  },
  {
    "path": "maint/benchmark/benchmark.py",
    "chars": 2027,
    "preview": "#!/usr/bin/env python\n#\n# A simple benchmark of tornado's HTTP stack.\n# Requires 'ab' to be installed.\n#\n# Running witho"
  },
  {
    "path": "maint/benchmark/chunk_benchmark.py",
    "chars": 1622,
    "preview": "#!/usr/bin/env python\n#\n# Downloads a large file in chunked encoding with both curl and simple clients\n\nimport logging\nf"
  },
  {
    "path": "maint/benchmark/gen_benchmark.py",
    "chars": 1195,
    "preview": "#!/usr/bin/env python\n#\n# A simple benchmark of the tornado.gen module.\n# Runs in two modes, testing new-style (@corouti"
  },
  {
    "path": "maint/benchmark/parsing_benchmark.py",
    "chars": 3085,
    "preview": "#!/usr/bin/env python\r\nimport re\r\nimport timeit\r\nfrom enum import Enum\r\nfrom typing import Callable\r\n\r\nfrom tornado.http"
  },
  {
    "path": "maint/benchmark/template_benchmark.py",
    "chars": 1596,
    "preview": "#!/usr/bin/env python\n#\n# A simple benchmark of tornado template rendering, based on\n# https://github.com/mitsuhiko/jinj"
  },
  {
    "path": "maint/scripts/custom_fixers/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "maint/scripts/custom_fixers/fix_future_imports.py",
    "chars": 2175,
    "preview": "\"\"\"Updates all source files to import the same set of __future__ directives.\n\"\"\"\nfrom lib2to3 import fixer_base\nfrom lib"
  },
  {
    "path": "maint/scripts/custom_fixers/fix_unicode_literal.py",
    "chars": 407,
    "preview": "from lib2to3 import fixer_base\nfrom lib2to3.fixer_util import String\n\n\nclass FixUnicodeLiteral(fixer_base.BaseFix):\n    "
  },
  {
    "path": "maint/scripts/run_autopep8.sh",
    "chars": 534,
    "preview": "#!/bin/sh\n\n# Runs autopep8 in the configuration used for tornado.\n#\n# W602 is \"deprecated form of raising exception\", bu"
  },
  {
    "path": "maint/scripts/run_fixers.py",
    "chars": 174,
    "preview": "#!/usr/bin/env python\n# Usage is like 2to3:\n# $ maint/scripts/run_fixers.py -wn --no-diffs tornado\n\nimport sys\nfrom lib2"
  },
  {
    "path": "maint/scripts/runcog.sh",
    "chars": 818,
    "preview": "#!/bin/sh\n\n# max/min_python_minor are the range of Python 3.x versions we support.\n# max_min_python_threaded_minor are t"
  },
  {
    "path": "maint/scripts/test_resolvers.py",
    "chars": 1725,
    "preview": "#!/usr/bin/env python\n\"\"\"Basic test for Tornado resolvers.\n\nQueries real domain names and prints the results from each r"
  },
  {
    "path": "maint/test/README",
    "chars": 185,
    "preview": "This directory contains additional tests that are not included in the main\nsuite (because e.g. they have extra dependenc"
  },
  {
    "path": "maint/test/cython/.gitignore",
    "chars": 30,
    "preview": ".eggs\ncythonapp.egg-info\ndist\n"
  },
  {
    "path": "maint/test/cython/MANIFEST.in",
    "chars": 22,
    "preview": "include cythonapp.pyx\n"
  },
  {
    "path": "maint/test/cython/cythonapp.pyx",
    "chars": 780,
    "preview": "import cython\nfrom tornado import gen\nimport pythonmodule\n\nasync def native_coroutine():\n    x = await pythonmodule.hell"
  },
  {
    "path": "maint/test/cython/cythonapp_test.py",
    "chars": 1196,
    "preview": "from tornado.testing import AsyncTestCase, gen_test\nfrom tornado.util import ArgReplacer\nimport unittest\n\nimport cythona"
  },
  {
    "path": "maint/test/cython/pythonmodule.py",
    "chars": 111,
    "preview": "from tornado import gen\n\n\n@gen.coroutine\ndef hello():\n    yield gen.sleep(0.001)\n    raise gen.Return(\"hello\")\n"
  },
  {
    "path": "maint/test/cython/setup.py",
    "chars": 341,
    "preview": "from setuptools import setup\n\ntry:\n    import Cython.Build\nexcept:\n    Cython = None\n\nif Cython is None:\n    ext_modules"
  },
  {
    "path": "maint/test/cython/tox.ini",
    "chars": 370,
    "preview": "[tox]\n# This currently segfaults on pypy.\nenvlist = py27,py36\n\n[testenv]\ndeps =\n     ../../..\n     Cython>=0.23.3\n     b"
  },
  {
    "path": "maint/test/mypy/.gitignore",
    "chars": 17,
    "preview": "UNKNOWN.egg-info\n"
  },
  {
    "path": "maint/test/mypy/bad.py",
    "chars": 146,
    "preview": "from tornado.web import RequestHandler\n\n\nclass MyHandler(RequestHandler):\n    def get(self) -> str:  # Deliberate type e"
  },
  {
    "path": "maint/test/mypy/good.py",
    "chars": 239,
    "preview": "from tornado import gen\nfrom tornado.web import RequestHandler\n\n\nclass MyHandler(RequestHandler):\n    def get(self) -> N"
  },
  {
    "path": "maint/test/mypy/setup.py",
    "chars": 38,
    "preview": "from setuptools import setup\n\nsetup()\n"
  },
  {
    "path": "maint/test/mypy/tox.ini",
    "chars": 302,
    "preview": "# Test that the py.typed marker file is respected and client\n# application code can be typechecked using tornado's publi"
  },
  {
    "path": "maint/test/redbot/README",
    "chars": 329,
    "preview": "Redbot is an HTTP validator that checks for common problems, especially\nrelated to cacheability.  These tests ensure tha"
  },
  {
    "path": "maint/test/redbot/red_test.py",
    "chars": 8805,
    "preview": "#!/usr/bin/env python\n\nimport logging\nfrom redbot.resource import HttpResource\nimport redbot.speak as rs\nimport thor\nimp"
  },
  {
    "path": "maint/test/redbot/tox.ini",
    "chars": 211,
    "preview": "[tox]\nenvlist = py27\nsetupdir=../../..\n\n[testenv]\ncommands = python red_test.py\ndeps =\n     # Newer versions of thor hav"
  },
  {
    "path": "maint/test/websocket/.gitignore",
    "chars": 9,
    "preview": "reports/\n"
  },
  {
    "path": "maint/test/websocket/client.py",
    "chars": 1367,
    "preview": "import logging\n\nfrom tornado import gen\nfrom tornado.ioloop import IOLoop\nfrom tornado.options import define, options, p"
  },
  {
    "path": "maint/test/websocket/fuzzingclient.json",
    "chars": 836,
    "preview": "{\n    \"options\": {\n        \"failByDrop\": false\n    },\n    \"outdir\": \"./reports/servers\",\n    \"servers\": [\n        {\n    "
  }
]

// ... and 117 more files (download for full content)

About this extraction

This page contains the full source code of the tornadoweb/tornado GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 317 files (2.0 MB), approximately 533.0k tokens, and a symbol index with 3471 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!