# Natural Language Toolkit (NLTK)
[![PyPI](https://img.shields.io/pypi/v/nltk.svg)](https://pypi.python.org/pypi/nltk)
![CI](https://github.com/nltk/nltk/actions/workflows/ci.yaml/badge.svg?branch=develop)

NLTK -- the Natural Language Toolkit -- is a suite of open source Python
modules, data sets, and tutorials supporting research and development in Natural
Language Processing. NLTK requires Python version 3.8, 3.9, 3.10, 3.11 or 3.12.

For documentation, please visit [nltk.org](https://www.nltk.org/).

## Contributing

Do you want to contribute to NLTK development? Great!
Please read [CONTRIBUTING.md](CONTRIBUTING.md) for more details.

See also [how to contribute to NLTK](https://www.nltk.org/contribute.html).

## Donate

Have you found the toolkit helpful?  Please support NLTK development by donating
to the project via PayPal, using the link on the NLTK homepage.

## Citing

If you publish work that uses NLTK, please cite the NLTK book, as follows:

    Bird, Steven, Edward Loper and Ewan Klein (2009).
    Natural Language Processing with Python.  O'Reilly Media Inc.

## Copyright

Copyright (C) 2001-2023 NLTK Project

For license information, see [LICENSE.txt](LICENSE.txt).

[AUTHORS.md](AUTHORS.md) contains a list of everyone who has contributed to NLTK.

### Redistributing

- NLTK source code is distributed under the Apache 2.0 License.
- NLTK documentation is distributed under the Creative Commons
  Attribution-Noncommercial-No Derivative Works 3.0 United States license.
- NLTK corpora are provided under the terms given in the README file for each
  corpus; all are redistributable and available for non-commercial use.
- NLTK may be freely redistributed, subject to the provisions of these licenses.


.. raw:: html

|Build Status| |Docs| |codecov.io|

The Falcon Web Framework
========================

`Falcon <https://falconframework.org>`__ is a minimalist ASGI/WSGI framework for
building mission-critical REST APIs and microservices, with a focus on
reliability, correctness, and performance at scale.

When it comes to building HTTP APIs, other frameworks weigh you down with tons
of dependencies and unnecessary abstractions. Falcon cuts to the chase with a
clean design that embraces HTTP and the REST architectural style.

Falcon apps work with any `WSGI <https://www.python.org/dev/peps/pep-3333/>`_
or `ASGI <https://asgi.readthedocs.io/en/latest/>`_ server, and run like a
champ under CPython 3.7+ and PyPy 3.7+.

Quick Links
-----------

* `Read the docs <https://falcon.readthedocs.io/en/stable>`_
  (`FAQ <https://falcon.readthedocs.io/en/stable/user/faq.html>`_ -
  `getting help <https://falcon.readthedocs.io/en/stable/community/help.html>`_ -
  `reference <https://falcon.readthedocs.io/en/stable/api/index.html>`_)
* `Falcon add-ons and complementary packages <https://github.com/falconry/falcon/wiki>`_
* `Falcon articles, talks and podcasts <https://github.com/falconry/falcon/wiki/Articles,-Talks-and-Podcasts>`_
* `falconry/user for Falcon users <https://gitter.im/falconry/user>`_ @ Gitter
* `falconry/dev for Falcon contributors <https://gitter.im/falconry/dev>`_ @ Gitter

What People are Saying
----------------------

"Falcon is rock solid and it's fast."

"We have been using Falcon as a replacement for [another framework] and
we simply love the performance (three times faster) and code base size (easily
half of our [original] code)."

"I'm loving #falconframework! Super clean and simple, I finally
have the speed and flexibility I need!"

"Falcon looks great so far. I hacked together a quick test for a
tiny server of mine and was ~40% faster with only 20 minutes of
work."

"I feel like I'm just talking HTTP at last, with nothing in the
middle. Falcon seems like the requests of backend."

"The source code for Falcon is so good, I almost prefer it to
documentation. It basically can't be wrong."

"What other framework has integrated support for 786 TRY IT NOW ?"

Features
--------

Falcon tries to do as little as possible while remaining highly effective.

- ASGI, WSGI, and WebSocket support
- Native ``asyncio`` support
- No reliance on magic globals for routing and state management
- Stable interfaces with an emphasis on backwards-compatibility
- Simple API modeling through centralized RESTful routing
- Highly-optimized, extensible code base
- Easy access to headers and bodies through request and response
  classes
- DRY request processing via middleware components and hooks
- Strict adherence to RFCs
- Idiomatic HTTP error responses
- Straightforward exception handling
- Snappy testing with WSGI/ASGI helpers and mocks
- CPython 3.7+ and PyPy 3.7+ support

.. Patron list starts here. For Python package, we substitute this section with:
   Support Falcon Development
   --------------------------

A Big Thank You to Our Patrons!
-------------------------------

.. raw:: html

.. Patron list ends here (see the comment above this section).

Has Falcon helped you make an awesome app? Show your support today with a one-time donation or by becoming a patron. Supporters get cool gear, an opportunity to promote their brand to Python developers, and
prioritized support.

* `Learn how to support Falcon development <https://falconframework.org/#sectionSupportFalconDevelopment>`_

Thanks!

How is Falcon Different?
------------------------

    Perfection is finally attained not when there is no longer anything
    to add, but when there is no longer anything to take away.

    *- Antoine de Saint-Exupéry*

We designed Falcon to support the demanding needs of large-scale
microservices and responsive app backends. Falcon complements more
general Python web frameworks by providing bare-metal performance,
reliability, and flexibility wherever you need it.

**Reliable.** We go to great lengths to avoid introducing breaking changes, and
when we do they are fully documented and only introduced (in the spirit of
`SemVer <http://semver.org/>`_) with a major version increment. The code is
rigorously tested with numerous inputs and we require 100% coverage at all
times. Falcon has no dependencies outside the standard library, helping
minimize your app's attack surface while avoiding transitive bugs and breaking
changes.

**Debuggable.** Falcon eschews magic. It's easy to tell which inputs lead to
which outputs. Unhandled exceptions are never encapsulated or masked.
Potentially surprising behaviors, such as automatic request body parsing, are
well-documented and disabled by default. Finally, when it comes to the
framework itself, we take care to keep logic paths simple and understandable.
All this makes it easier to reason about the code and to debug edge cases in
large-scale deployments.

**Fast.** Same hardware, more requests. Falcon turns around requests
significantly faster than other popular Python frameworks like Django and
Flask. For an extra speed boost, Falcon compiles itself with Cython when
available, and also works well with `PyPy <https://pypy.org>`_. Considering a
move to another programming language? Benchmark with Falcon+PyPy first!

**Flexible.** Falcon leaves a lot of decisions and implementation details to
you, the API developer. This gives you a lot of freedom to customize and tune
your implementation. It also helps you understand your apps at a deeper level,
making them easier to tune, debug, and refactor over the long run. Falcon's
minimalist design provides space for Python community members to independently
innovate on `Falcon add-ons and complementary packages
<https://github.com/falconry/falcon/wiki>`_.

Who's Using Falcon?
-------------------

Falcon is used around the world by a growing number of organizations,
including:

- 7ideas
- Cronitor
- EMC
- Hurricane Electric
- Leadpages
- OpenStack
- Rackspace
- Shiftgig
- tempfil.es
- Opera Software

If you are using the Falcon framework for a community or commercial
project, please consider adding your information to our wiki under
`Who's Using Falcon? <https://github.com/falconry/falcon/wiki/Who's-using-Falcon%3F>`_

Community
---------

A number of Falcon add-ons, templates, and complementary packages are
available for use in your projects. We've listed several of these on the
`Falcon wiki <https://github.com/falconry/falcon/wiki>`_ as a starting
point, but you may also wish to search PyPI for additional resources.

The Falconry community on Gitter is a great place to ask questions and
share your ideas. You can find us in `falconry/user
<https://gitter.im/falconry/user>`_. We also have a
`falconry/dev <https://gitter.im/falconry/dev>`_ room for discussing
the design and development of the framework itself.

Per our
`Code of Conduct <https://github.com/falconry/falcon/blob/master/CODEOFCONDUCT.md>`_,
we expect everyone who participates in community discussions to act
professionally, and lead by example in encouraging constructive
discussions. Each individual in the community is responsible for
creating a positive, constructive, and productive culture.

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

PyPy
^^^^

`PyPy <http://pypy.org/>`__ is the fastest way to run your Falcon app.
PyPy3.7+ is supported as of PyPy v7.3.4+.

.. code:: bash

    $ pip install falcon

Or, to install the latest beta or release candidate, if any:

.. code:: bash

    $ pip install --pre falcon

CPython
^^^^^^^

Falcon also fully supports
`CPython <https://www.python.org/downloads/>`__ 3.7+.

The latest stable version of Falcon can be installed directly from PyPI:

.. code:: bash

    $ pip install falcon

Or, to install the latest beta or release candidate, if any:

.. code:: bash

    $ pip install --pre falcon

In order to provide an extra speed boost, Falcon can compile itself with
Cython. Wheels containing pre-compiled binaries are available from PyPI for
several common platforms. However, if a wheel for your platform of choice is not
available, you can install the source distribution. The installation process
will automatically try to cythonize Falcon for your environment, falling back to
a normal pure-Python install if any issues are encountered during the
cythonization step:

.. code:: bash

    $ pip install --no-binary :all: falcon

If you want to verify that Cython is being invoked, simply
pass the verbose flag `-v` to pip in order to echo the compilation commands.

The cythonization step is only active when using the ``CPython`` Python
implementation, so installing using ``PyPy`` will skip it.
If you want to skip Cython compilation step and install
the pure-Python version directly you can set the environment variable
``FALCON_DISABLE_CYTHON`` to a non empty value before install:

.. code:: bash

    $ FALCON_DISABLE_CYTHON=Y pip install -v --no-binary :all: falcon

Please note that ``pip>=10`` is required to be able to install Falcon from
source.

**Installing on OS X**

Xcode Command Line Tools are required to compile Cython. Install them
with this command:

.. code:: bash

    $ xcode-select --install

The Clang compiler treats unrecognized command-line options as
errors, for example:

.. code:: bash

    clang: error: unknown argument: '-mno-fused-madd' [-Wunused-command-line-argument-hard-error-in-future]

You might also see warnings about unused functions. You can work around
these issues by setting additional Clang C compiler flags as follows:

.. code:: bash

    $ export CFLAGS="-Qunused-arguments -Wno-unused-function"

Dependencies
^^^^^^^^^^^^

Falcon does not require the installation of any other packages, although if
Cython has been installed into the environment, it will be used to optimize
the framework as explained above.

WSGI Server
-----------

Falcon speaks `WSGI <https://www.python.org/dev/peps/pep-3333/>`_ (or
`ASGI <https://asgi.readthedocs.io/en/latest/>`_; see also below). In order to
serve a Falcon app, you will need a WSGI server. Gunicorn and uWSGI are some of
the more popular ones out there, but anything that can load a WSGI app will do.

.. code:: bash

    $ pip install [gunicorn|uwsgi]

ASGI Server
-----------

In order to serve a Falcon ASGI app, you will need an ASGI server. Uvicorn
is a popular choice:

.. code:: bash

    $ pip install uvicorn

Source Code
-----------

Falcon `lives on GitHub <https://github.com/falconry/falcon>`_, making the
code easy to browse, download, fork, etc. Pull requests are always welcome! Also,
please remember to star the project if it makes you happy. :)

Once you have cloned the repo or downloaded a tarball from GitHub, you
can install Falcon like this:

.. code:: bash

    $ cd falcon
    $ pip install .

Or, if you want to edit the code, first fork the main repo, clone the fork
to your desktop, and then run the following to install it using symbolic
linking, so that when you change your code, the changes will be automagically
available to your app without having to reinstall the package:

.. code:: bash

    $ cd falcon
    $ pip install -e .

You can manually test changes to the Falcon framework by switching to the
directory of the cloned repo and then running pytest:

.. code:: bash

    $ cd falcon
    $ pip install -r requirements/tests
    $ pytest tests

Or, to run the default set of tests:

.. code:: bash

    $ pip install tox && tox

See also the `tox.ini <https://github.com/falconry/falcon/blob/master/tox.ini>`_
file for a full list of available environments.

Read the Docs
-------------

The docstrings in the Falcon code base are quite extensive, and we
recommend keeping a REPL running while learning the framework so that
you can query the various modules and classes as you have questions.

Online docs are available at: https://falcon.readthedocs.io

You can build the same docs locally as follows:

.. code:: bash

    $ pip install tox && tox -e docs

Once the docs have been built, you can view them by opening the following
index page in your browser. On OS X it's as simple as::

    $ open docs/_build/html/index.html

Or on Linux:

.. code:: bash

    $ xdg-open docs/_build/html/index.html

Getting Started
---------------

Here is a simple, contrived example showing how to create a Falcon-based
WSGI app (the ASGI version is included further down):

.. code:: python

    # examples/things.py

    # Let's get this party started!
    from wsgiref.simple_server import make_server

    import falcon

    # Falcon follows the REST architectural style, meaning (among
    # other things) that you think in terms of resources and state
    # transitions, which map to HTTP verbs.
    class ThingsResource:
        def on_get(self, req, resp):
            """Handles GET requests"""
            resp.status = falcon.HTTP_200  # This is the default status
            resp.content_type = falcon.MEDIA_TEXT  # Default is JSON, so override
            resp.text = ('\nTwo things awe me most, the starry sky '
                         'above me and the moral law within me.\n'
                         '\n'
                         '    ~ Immanuel Kant\n\n')

    # falcon.App instances are callable WSGI apps...
    # in larger applications the app is created in a separate file
    app = falcon.App()

    # Resources are represented by long-lived class instances
    things = ThingsResource()

    # things will handle all requests to the '/things' URL path
    app.add_route('/things', things)

    if __name__ == '__main__':
        with make_server('', 8000, app) as httpd:
            print('Serving on port 8000...')

            # Serve until process is killed
            httpd.serve_forever()

You can run the above example directly using the included wsgiref server:

.. code:: bash

    $ pip install falcon
    $ python things.py

Then, in another terminal:

.. code:: bash

    $ curl localhost:8000/things

The ASGI version of the example is similar:

.. code:: python

    # examples/things_asgi.py

    import falcon
    import falcon.asgi

    # Falcon follows the REST architectural style, meaning (among
    # other things) that you think in terms of resources and state
    # transitions, which map to HTTP verbs.
    class ThingsResource:
        async def on_get(self, req, resp):
            """Handles GET requests"""
            resp.status = falcon.HTTP_200  # This is the default status
            resp.content_type = falcon.MEDIA_TEXT  # Default is JSON, so override
            resp.text = ('\nTwo things awe me most, the starry sky '
                         'above me and the moral law within me.\n'
                         '\n'
                         '    ~ Immanuel Kant\n\n')

    # falcon.asgi.App instances are callable ASGI apps...
    # in larger applications the app is created in a separate file
    app = falcon.asgi.App()

    # Resources are represented by long-lived class instances
    things = ThingsResource()

    # things will handle all requests to the '/things' URL path
    app.add_route('/things', things)

You can run the ASGI version with uvicorn or any other ASGI server:

.. code:: bash

    $ pip install falcon uvicorn
    $ uvicorn things_asgi:app

A More Complex Example (WSGI)
-----------------------------

Here is a more involved example that demonstrates reading headers and query
parameters, handling errors, and working with request and response bodies.
Note that this example assumes that the
`requests <https://pypi.org/project/requests/>`_ package has been installed.

(For the equivalent ASGI app, see: `A More Complex Example (ASGI)`_).

.. code:: python

    # examples/things_advanced.py

    import json
    import logging
    import uuid
    from wsgiref import simple_server

    import falcon
    import requests

    class StorageEngine:

        def get_things(self, marker, limit):
            return [{'id': str(uuid.uuid4()), 'color': 'green'}]

        def add_thing(self, thing):
            thing['id'] = str(uuid.uuid4())
            return thing

    class StorageError(Exception):

        @staticmethod
        def handle(ex, req, resp, params):
            # TODO: Log the error, clean up, etc. before raising
            raise falcon.HTTPInternalServerError()

    class SinkAdapter:

        engines = {
            'ddg': 'https://duckduckgo.com',
            'y': 'https://search.yahoo.com/search',
        }

        def __call__(self, req, resp, engine):
            url = self.engines[engine]
            params = {'q': req.get_param('q', True)}
            result = requests.get(url, params=params)

            resp.status = str(result.status_code) + ' ' + result.reason
            resp.content_type = result.headers['content-type']
            resp.text = result.text

    class AuthMiddleware:

        def process_request(self, req, resp):
            token = req.get_header('Authorization')
            account_id = req.get_header('Account-ID')

            challenges = ['Token type="Fernet"']

            if token is None:
                description = ('Please provide an auth token '
                               'as part of the request.')

                raise falcon.HTTPUnauthorized(title='Auth token required',
                                              description=description,
                                              challenges=challenges,
                                              href='http://docs.example.com/auth')

            if not self._token_is_valid(token, account_id):
                description = ('The provided auth token is not valid. '
                               'Please request a new token and try again.')

                raise falcon.HTTPUnauthorized(title='Authentication required',
                                              description=description,
                                              challenges=challenges,
                                              href='http://docs.example.com/auth')

        def _token_is_valid(self, token, account_id):
            return True  # Suuuuuure it's valid...

    class RequireJSON:

        def process_request(self, req, resp):
            if not req.client_accepts_json:
                raise falcon.HTTPNotAcceptable(
                    description='This API only supports responses encoded as JSON.',
                    href='http://docs.examples.com/api/json')

            if req.method in ('POST', 'PUT'):
                if 'application/json' not in req.content_type:
                    raise falcon.HTTPUnsupportedMediaType(
                        title='This API only supports requests encoded as JSON.',
                        href='http://docs.examples.com/api/json')

    class JSONTranslator:
        # NOTE: Normally you would simply use req.media and resp.media for
        # this particular use case; this example serves only to illustrate
        # what is possible.

        def process_request(self, req, resp):
            # req.stream corresponds to the WSGI wsgi.input environ variable,
            # and allows you to read bytes from the request body.
            #
            # See also: PEP 3333
            if req.content_length in (None, 0):
                # Nothing to do
                return

            body = req.stream.read()
            if not body:
                raise falcon.HTTPBadRequest(title='Empty request body',
                                            description='A valid JSON document is required.')

            try:
                req.context.doc = json.loads(body.decode('utf-8'))

            except (ValueError, UnicodeDecodeError):
                description = ('Could not decode the request body. The '
                               'JSON was incorrect or not encoded as '
                               'UTF-8.')

                raise falcon.HTTPBadRequest(title='Malformed JSON',
                                            description=description)

        def process_response(self, req, resp, resource, req_succeeded):
            if not hasattr(resp.context, 'result'):
                return

            resp.text = json.dumps(resp.context.result)

    def max_body(limit):

        def hook(req, resp, resource, params):
            length = req.content_length
            if length is not None and length > limit:
                msg = ('The size of the request is too large. The body must not '
                       'exceed ' + str(limit) + ' bytes in length.')

                raise falcon.HTTPPayloadTooLarge(
                    title='Request body is too large', description=msg)

        return hook

    class ThingsResource:

        def __init__(self, db):
            self.db = db
            self.logger = logging.getLogger('thingsapp.' + __name__)

        def on_get(self, req, resp, user_id):
            marker = req.get_param('marker') or ''
            limit = req.get_param_as_int('limit') or 50

            try:
                result = self.db.get_things(marker, limit)
            except Exception as ex:
                self.logger.error(ex)

                description = ('Aliens have attacked our base! We will '
                               'be back as soon as we fight them off. '
                               'We appreciate your patience.')

                raise falcon.HTTPServiceUnavailable(
                    title='Service Outage',
                    description=description,
                    retry_after=30)

            # NOTE: Normally you would use resp.media for this sort of thing;
            # this example serves only to demonstrate how the context can be
            # used to pass arbitrary values between middleware components,
            # hooks, and resources.
            resp.context.result = result

            resp.set_header('Powered-By', 'Falcon')
            resp.status = falcon.HTTP_200

        @falcon.before(max_body(64 * 1024))
        def on_post(self, req, resp, user_id):
            try:
                doc = req.context.doc
            except AttributeError:
                raise falcon.HTTPBadRequest(
                    title='Missing thing',
                    description='A thing must be submitted in the request body.')

            proper_thing = self.db.add_thing(doc)

            resp.status = falcon.HTTP_201
            resp.location = '/%s/things/%s' % (user_id, proper_thing['id'])

    # Configure your WSGI server to load "things.app" (app is a WSGI callable)
    app = falcon.App(middleware=[
        AuthMiddleware(),
        RequireJSON(),
        JSONTranslator(),
    ])

    db = StorageEngine()
    things = ThingsResource(db)
    app.add_route('/{user_id}/things', things)

    # If a responder ever raises an instance of StorageError, pass control to
    # the given handler.
    app.add_error_handler(StorageError, StorageError.handle)

    # Proxy some things to another service; this example shows how you might
    # send parts of an API off to a legacy system that hasn't been upgraded
    # yet, or perhaps is a single cluster that all data centers have to share.
    sink = SinkAdapter()
    app.add_sink(sink, r'/search/(?P<engine>ddg|y)\Z')

    # Useful for debugging problems in your API; works with pdb.set_trace(). You
    # can also use Gunicorn to host your app. Gunicorn can be configured to
    # auto-restart workers when it detects a code change, and it also works
    # with pdb.
    if __name__ == '__main__':
        httpd = simple_server.make_server('127.0.0.1', 8000, app)
        httpd.serve_forever()

Again this code uses wsgiref, but you can also run the above example using
any WSGI server, such as uWSGI or Gunicorn. For example:

.. code:: bash

    $ pip install requests gunicorn
    $ gunicorn things:app

On Windows you can run Gunicorn and uWSGI via WSL, or you might try Waitress:

.. code:: bash

    $ pip install requests waitress
    $ waitress-serve --port=8000 things:app

To test this example, open another terminal and run:

.. code:: bash

    $ http localhost:8000/1/things authorization:custom-token

You can also view the application configuration from the CLI via the
``falcon-inspect-app`` script that is bundled with the framework:

.. code:: bash

    falcon-inspect-app things_advanced:app

A More Complex Example (ASGI)
-----------------------------

Here's the ASGI version of the app from above. Note that it uses the
`httpx <https://pypi.org/project/httpx/>`_ package in lieu of
`requests <https://pypi.org/project/requests/>`_.

.. code:: python

    # examples/things_advanced_asgi.py

    import json
    import logging
    import uuid

    import falcon
    import falcon.asgi
    import httpx

    class StorageEngine:

        async def get_things(self, marker, limit):
            return [{'id': str(uuid.uuid4()), 'color': 'green'}]

        async def add_thing(self, thing):
            thing['id'] = str(uuid.uuid4())
            return thing

    class StorageError(Exception):

        @staticmethod
        async def handle(ex, req, resp, params):
            # TODO: Log the error, clean up, etc. before raising
            raise falcon.HTTPInternalServerError()

    class SinkAdapter:

        engines = {
            'ddg': 'https://duckduckgo.com',
            'y': 'https://search.yahoo.com/search',
        }

        async def __call__(self, req, resp, engine):
            url = self.engines[engine]
            params = {'q': req.get_param('q', True)}

            async with httpx.AsyncClient() as client:
                result = await client.get(url, params=params)

            resp.status = result.status_code
            resp.content_type = result.headers['content-type']
            resp.text = result.text

    class AuthMiddleware:

        async def process_request(self, req, resp):
            token = req.get_header('Authorization')
            account_id = req.get_header('Account-ID')

            challenges = ['Token type="Fernet"']

            if token is None:
                description = ('Please provide an auth token '
                               'as part of the request.')

                raise falcon.HTTPUnauthorized(title='Auth token required',
                                              description=description,
                                              challenges=challenges,
                                              href='http://docs.example.com/auth')

            if not self._token_is_valid(token, account_id):
                description = ('The provided auth token is not valid. '
                               'Please request a new token and try again.')

                raise falcon.HTTPUnauthorized(title='Authentication required',
                                              description=description,
                                              challenges=challenges,
                                              href='http://docs.example.com/auth')

        def _token_is_valid(self, token, account_id):
            return True  # Suuuuuure it's valid...

    class RequireJSON:

        async def process_request(self, req, resp):
            if not req.client_accepts_json:
                raise falcon.HTTPNotAcceptable(
                    description='This API only supports responses encoded as JSON.',
                    href='http://docs.examples.com/api/json')

            if req.method in ('POST', 'PUT'):
                if 'application/json' not in req.content_type:
                    raise falcon.HTTPUnsupportedMediaType(
                        description='This API only supports requests encoded as JSON.',
                        href='http://docs.examples.com/api/json')

    class JSONTranslator:
        # NOTE: Normally you would simply use req.get_media() and resp.media for
        # this particular use case; this example serves only to illustrate
        # what is possible.

        async def process_request(self, req, resp):
            # NOTE: Test explicitly for 0, since this property could be None in
            # the case that the Content-Length header is missing (in which case we
            # can't know if there is a body without actually attempting to read
            # it from the request stream.)
            if req.content_length == 0:
                # Nothing to do
                return

            body = await req.stream.read()
            if not body:
                raise falcon.HTTPBadRequest(title='Empty request body',
                                            description='A valid JSON document is required.')

            try:
                req.context.doc = json.loads(body.decode('utf-8'))

            except (ValueError, UnicodeDecodeError):
                description = ('Could not decode the request body. The '
                               'JSON was incorrect or not encoded as '
                               'UTF-8.')

                raise falcon.HTTPBadRequest(title='Malformed JSON',
                                            description=description)

        async def process_response(self, req, resp, resource, req_succeeded):
            if not hasattr(resp.context, 'result'):
                return

            resp.text = json.dumps(resp.context.result)

    def max_body(limit):

        async def hook(req, resp, resource, params):
            length = req.content_length
            if length is not None and length > limit:
                msg = ('The size of the request is too large. The body must not '
                       'exceed ' + str(limit) + ' bytes in length.')

                raise falcon.HTTPPayloadTooLarge(
                    title='Request body is too large', description=msg)

        return hook

    class ThingsResource:

        def __init__(self, db):
            self.db = db
            self.logger = logging.getLogger('thingsapp.' + __name__)

        async def on_get(self, req, resp, user_id):
            marker = req.get_param('marker') or ''
            limit = req.get_param_as_int('limit') or 50

            try:
                result = await self.db.get_things(marker, limit)
            except Exception as ex:
                self.logger.error(ex)

                description = ('Aliens have attacked our base! We will '
                               'be back as soon as we fight them off. '
                               'We appreciate your patience.')

                raise falcon.HTTPServiceUnavailable(
                    title='Service Outage',
                    description=description,
                    retry_after=30)

            # NOTE: Normally you would use resp.media for this sort of thing;
            # this example serves only to demonstrate how the context can be
            # used to pass arbitrary values between middleware components,
            # hooks, and resources.
            resp.context.result = result

            resp.set_header('Powered-By', 'Falcon')
            resp.status = falcon.HTTP_200

        @falcon.before(max_body(64 * 1024))
        async def on_post(self, req, resp, user_id):
            try:
                doc = req.context.doc
            except AttributeError:
                raise falcon.HTTPBadRequest(
                    title='Missing thing',
                    description='A thing must be submitted in the request body.')

            proper_thing = await self.db.add_thing(doc)

            resp.status = falcon.HTTP_201
            resp.location = '/%s/things/%s' % (user_id, proper_thing['id'])

    # The app instance is an ASGI callable
    app = falcon.asgi.App(middleware=[
        # AuthMiddleware(),
        RequireJSON(),
        JSONTranslator(),
    ])

    db = StorageEngine()
    things = ThingsResource(db)
    app.add_route('/{user_id}/things', things)

    # If a responder ever raises an instance of StorageError, pass control to
    # the given handler.
    app.add_error_handler(StorageError, StorageError.handle)

    # Proxy some things to another service; this example shows how you might
    # send parts of an API off to a legacy system that hasn't been upgraded
    # yet, or perhaps is a single cluster that all data centers have to share.
    sink = SinkAdapter()
    app.add_sink(sink, r'/search/(?P<engine>ddg|y)\Z')

You can run the ASGI version with any ASGI server, such as uvicorn:

.. code:: bash

    $ pip install falcon httpx uvicorn
    $ uvicorn things_advanced_asgi:app

Contributing
------------

Thanks for your interest in the project! We welcome pull requests from
developers of all skill levels. To get started, simply fork the master branch
on GitHub to your personal account and then clone the fork into your
development environment.

If you would like to contribute but don't already have something in mind,
we invite you to take a look at the issues listed under our
`next milestone <https://github.com/falconry/falcon/milestones>`_.
If you see one you'd like to work on, please leave a quick comment so that we don't
end up with duplicated effort. Thanks in advance!

Please note that all contributors and maintainers of this project are subject to our `Code of Conduct <https://github.com/falconry/falcon/blob/master/CODEOFCONDUCT.md>`_.

Before submitting a pull request, please ensure you have added/updated
the appropriate tests (and that all existing tests still pass with your
changes), and that your coding style follows PEP 8 and doesn't cause
pyflakes to complain.

Commit messages should be formatted using `AngularJS
conventions <https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#-git-commit-guidelines>`__.

Comments follow `Google's style guide <https://google.github.io/styleguide/pyguide.html?showone=Comments#Comments>`__,
with the additional requirement of prefixing inline comments using your
GitHub nick and an appropriate prefix:

- TODO(riker): Damage report!
- NOTE(riker): Well, that's certainly good to know.
- PERF(riker): Travel time to the nearest starbase?
- APPSEC(riker): In all trust, there is the possibility for betrayal.

The core Falcon project maintainers are:

- Kurt Griffiths, Project Lead (**kgriffs** on GH, Gitter, and Twitter)
- John Vrbanac (**jmvrbanac** on GH, Gitter, and Twitter)
- Vytautas Liuolia (**vytas7** on GH and Gitter, and **vliuolia** on Twitter)
- Nick Zaccardi (**nZac** on GH and Gitter)
- Federico Caselli (**CaselIT** on GH and Gitter)

Please don't hesitate to reach out if you have any questions, or just need a
little help getting started. You can find us in
`falconry/dev <https://gitter.im/falconry/dev>`_ on Gitter.

See also: `CONTRIBUTING.md <https://github.com/falconry/falcon/blob/master/CONTRIBUTING.md>`__

Legal
-----

Copyright 2013-2024 by Individual and corporate contributors as
noted in the individual source files.

Licensed under the Apache License, Version 2.0 (the "License"); you may
not use any portion of the Falcon framework except in compliance with
the License. Contributors agree to license their work under the same
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.

.. |Docs| image:: https://readthedocs.org/projects/falcon/badge/?version=stable
    :target: https://falcon.readthedocs.io/en/stable/?badge=stable
    :alt: Falcon web framework docs
.. |Build Status| image:: https://github.com/falconry/falcon/workflows/Run%20tests/badge.svg
   :target: https://github.com/falconry/falcon/actions?query=workflow%3A%22Run+tests%22
.. |codecov.io| image:: https://codecov.io/gh/falconry/falcon/branch/master/graphs/badge.svg
   :target: http://codecov.io/gh/falconry/falcon


# `node-gyp` - Node.js native addon build tool

[![Build Status](https://github.com/nodejs/node-gyp/workflows/Tests/badge.svg?branch=main)](https://github.com/nodejs/node-gyp/actions?query=workflow%3ATests+branch%3Amain)
![npm](https://img.shields.io/npm/dm/node-gyp)

`node-gyp` is a cross-platform command-line tool written in Node.js for
compiling native addon modules for Node.js. It contains a vendored copy of the
[gyp-next](https://github.com/nodejs/gyp-next) project that was previously used
by the Chromium team and extended to support the development of Node.js native
addons.

Note that `node-gyp` is _not_ used to build Node.js itself.

All current and LTS target versions of Node.js are supported. Depending on what version of Node.js is actually installed on your system
`node-gyp` downloads the necessary development files or headers for the target version. List of stable Node.js versions can be found on [Node.js website](https://nodejs.org/en/about/previous-releases).

## Features

 * The same build commands work on any of the supported platforms
 * Supports the targeting of different versions of Node.js

## Installation

> [!Important]
> Python >= v3.12 requires `node-gyp` >= v10

You can install `node-gyp` using `npm`:

``` bash
npm install -g node-gyp
```

Depending on your operating system, you will need to install:

### On Unix

   * [A supported version of Python](https://devguide.python.org/versions/)
   * `make`
   * A proper C/C++ compiler toolchain, like [GCC](https://gcc.gnu.org)

### On macOS

   * [A supported version of Python](https://devguide.python.org/versions/)
   * `Xcode Command Line Tools` which will install `clang`, `clang++`, and `make`.
     * Install the `Xcode Command Line Tools` standalone by running `xcode-select --install`. -- OR --
     * Alternatively, if you already have the [full Xcode installed](https://developer.apple.com/xcode/download/), you can install the Command Line Tools under the menu `Xcode -> Open Developer Tool -> More Developer Tools...`.

### On Windows

Install tools with [Chocolatey](https://chocolatey.org):
``` bash
choco install python visualstudio2022-workload-vctools -y
```

Or install and configure Python and Visual Studio tools manually:

  * Install the current [version of Python](https://devguide.python.org/versions/) from the
  [Microsoft Store](https://apps.microsoft.com/store/search?publisher=Python+Software+Foundation).

   * Install Visual C++ Build Environment: For Visual Studio 2019 or later, use the `Desktop development with C++` workload from [Visual Studio Community](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=Community).  For a version older than Visual Studio 2019, install [Visual Studio Build Tools](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=BuildTools) with the `Visual C++ build tools` option.

   If the above steps didn't work for you, please visit [Microsoft's Node.js Guidelines for Windows](https://github.com/Microsoft/nodejs-guidelines/blob/master/windows-environment.md#compiling-native-addon-modules) for additional tips.

   To target native ARM64 Node.js on Windows on ARM, add the components "Visual C++ compilers and libraries for ARM64" and "Visual C++ ATL for ARM64".

   To use the native ARM64 C++ compiler on Windows on ARM, ensure that you have Visual Studio 2022 [17.4 or later](https://devblogs.microsoft.com/visualstudio/arm64-visual-studio-is-officially-here/) installed.

It's advised to install following Powershell module: [VSSetup](https://github.com/microsoft/vssetup.powershell) using `Install-Module VSSetup -Scope CurrentUser`.
This will make Visual Studio detection logic to use more flexible and accessible method, avoiding Powershell's `ConstrainedLanguage` mode.

### Configuring Python Dependency

`node-gyp` requires that you have installed a [supported version of Python](https://devguide.python.org/versions/).
If you have multiple versions of Python installed, you can identify which version
`node-gyp` should use in one of the following ways:

1. by setting the `--python` command-line option, e.g.:

``` bash
node-gyp <command> --python /path/to/executable/python
```

2. If `node-gyp` is called by way of `npm`, *and* you have multiple versions of
Python installed, then you can set the `npm_config_python` environment variable
to the appropriate path:
``` bash
export npm_config_python=/path/to/executable/python
```
    Or on Windows:
```console
py --list-paths  # To see the installed Python versions
set npm_config_python=C:\path\to\python.exe  # CMD
$Env:npm_config_python="C:\path\to\python.exe"  # PowerShell
```

3. If the `PYTHON` environment variable is set to the path of a Python executable,
then that version will be used if it is a supported version.

4. If the `NODE_GYP_FORCE_PYTHON` environment variable is set to the path of a
Python executable, it will be used instead of any of the other configured or
built-in Python search paths. If it's not a compatible version, no further
searching will be done.

### Build for Third Party Node.js Runtimes

When building modules for third-party Node.js runtimes like Electron, which have
different build configurations from the official Node.js distribution, you
should use `--dist-url` or `--nodedir` flags to specify the headers of the
runtime to build for.

Also when `--dist-url` or `--nodedir` flags are passed, node-gyp will use the
`config.gypi` shipped in the headers distribution to generate build
configurations, which is different from the default mode that would use the
`process.config` object of the running Node.js instance.

Some old versions of Electron shipped malformed `config.gypi` in their headers
distributions, and you might need to pass `--force-process-config` to node-gyp
to work around configuration errors.

## How to Use

To compile your native addon first go to its root directory:

``` bash
cd my_node_addon
```

The next step is to generate the appropriate project build files for the current
platform. Use `configure` for that:

``` bash
node-gyp configure
```

Auto-detection fails for Visual C++ Build Tools 2015, so `--msvs_version=2015`
needs to be added (not needed when run by npm as configured above):
``` bash
node-gyp configure --msvs_version=2015
```

__Note__: The `configure` step looks for a `binding.gyp` file in the current
directory to process. See below for instructions on creating a `binding.gyp` file.

Now you will have either a `Makefile` (on Unix platforms) or a `vcxproj` file
(on Windows) in the `build/` directory. Next, invoke the `build` command:

``` bash
node-gyp build
```

Now you have your compiled `.node` bindings file! The compiled bindings end up
in `build/Debug/` or `build/Release/`, depending on the build mode. At this point,
you can require the `.node` file with Node.js and run your tests!

__Note:__ To create a _Debug_ build of the bindings file, pass the `--debug` (or
`-d`) switch when running either the `configure`, `build` or `rebuild` commands.

## The `binding.gyp` file

A `binding.gyp` file describes the configuration to build your module, in a
JSON-like format. This file gets placed in the root of your package, alongside
`package.json`.

A barebones `gyp` file appropriate for building a Node.js addon could look like:

```python
{
  "targets": [
    {
      "target_name": "binding",
      "sources": [ "src/binding.cc" ]
    }
  ]
}
```

## Further reading

The **[docs](./docs/)** directory contains additional documentation on specific node-gyp topics that may be useful if you are experiencing problems installing or building addons using node-gyp.

Some additional resources for Node.js native addons and writing `gyp` configuration files:

 * ["Going Native" a nodeschool.io tutorial](http://nodeschool.io/#goingnative)
 * ["Hello World" node addon example](https://github.com/nodejs/node/tree/main/test/addons/hello-world)
 * [gyp user documentation](https://gyp.gsrc.io/docs/UserDocumentation.md)
 * [gyp input format reference](https://gyp.gsrc.io/docs/InputFormatReference.md)
 * [*"binding.gyp" files out in the wild* wiki page](./docs/binding.gyp-files-in-the-wild.md)

## Commands

`node-gyp` responds to the following commands:

| **Command**   | **Description**
|:--------------|:---------------------------------------------------------------
| `help`        | Shows the help dialog
| `build`       | Invokes `make`/`msbuild.exe` and builds the native addon
| `clean`       | Removes the `build` directory if it exists
| `configure`   | Generates project build files for the current platform
| `rebuild`     | Runs `clean`, `configure` and `build` all in a row
| `install`     | Installs Node.js header files for the given version
| `list`        | Lists the currently installed Node.js header versions
| `remove`      | Removes the Node.js header files for the given version

## Command Options

`node-gyp` accepts the following command options:

| **Command**                       | **Description**
|:----------------------------------|:------------------------------------------
| `-j n`, `--jobs n`                | Run `make` in parallel. The value `max` will use all available CPU cores
| `--target=v6.2.1`                 | Node.js version to build for (default is `process.version`)
| `--silly`, `--loglevel=silly`     | Log all progress to console
| `--verbose`, `--loglevel=verbose` | Log most progress to console
| `--silent`, `--loglevel=silent`   | Don't log anything to console
| `debug`, `--debug`                | Make Debug build (default is `Release`)
| `--release`, `--no-debug`         | Make Release build
| `-C $dir`, `--directory=$dir`     | Run command in different directory
| `--make=$make`                    | Override `make` command (e.g. `gmake`)
| `--thin=yes`                      | Enable thin static libraries
| `--arch=$arch`                    | Set target architecture (e.g. ia32)
| `--tarball=$path`                 | Get headers from a local tarball
| `--devdir=$path`                  | SDK download directory (default is OS cache directory)
| `--ensure`                        | Don't reinstall headers if already present
| `--dist-url=$url`                 | Download header tarball from custom URL
| `--proxy=$url`                    | Set HTTP(S) proxy for downloading header tarball
| `--noproxy=$urls`                 | Set urls to ignore proxies when downloading header tarball
| `--cafile=$cafile`                | Override default CA chain (to download tarball)
| `--nodedir=$path`                 | Set the path to the node source code
| `--python=$path`                  | Set path to the Python binary
| `--msvs_version=$version`         | Set Visual Studio version (Windows only)
| `--solution=$solution`            | Set Visual Studio Solution version (Windows only)
| `--force-process-config`          | Force using runtime's `process.config` object to generate `config.gypi` file

## Configuration

### Environment variables

Use the form `npm_config_OPTION_NAME` for any of the command options listed
above (dashes in option names should be replaced by underscores).

For example, to set `devdir` equal to `/tmp/.gyp`, you would:

Run this on Unix:

```bash
export npm_config_devdir=/tmp/.gyp
```

Or this on Windows:

```console
set npm_config_devdir=c:\temp\.gyp
```

### `npm` configuration for npm versions before v9

Use the form `OPTION_NAME` for any of the command options listed above.

For example, to set `devdir` equal to `/tmp/.gyp`, you would run:

```bash
npm config set [--global] devdir /tmp/.gyp
```

**Note:** Configuration set via `npm` will only be used when `node-gyp`
is run via `npm`, not when `node-gyp` is run directly.

## License

`node-gyp` is available under the MIT license. See the [LICENSE
file](LICENSE) for details.


# Vega-Altair

[![github actions](https://github.com/altair-viz/altair/workflows/build/badge.svg)](https://github.com/altair-viz/altair/actions?query=workflow%3Abuild)
[![typedlib_mypy](https://www.mypy-lang.org/static/mypy_badge.svg)](https://www.mypy-lang.org)
[![JOSS Paper](https://joss.theoj.org/papers/10.21105/joss.01057/status.svg)](https://joss.theoj.org/papers/10.21105/joss.01057)
[![PyPI - Downloads](https://img.shields.io/pypi/dm/altair)](https://pypi.org/project/altair)

**Vega-Altair** is a declarative statistical visualization library for Python. With Vega-Altair, you can spend more time understanding your data and its meaning. Vega-Altair's
API is simple, friendly and consistent and built on top of the powerful
[Vega-Lite](https://github.com/vega/vega-lite) JSON specification. This elegant
simplicity produces beautiful and effective visualizations with a minimal amount of code.

*Vega-Altair was originally developed by [Jake Vanderplas](https://github.com/jakevdp) and [Brian
Granger](https://github.com/ellisonbg) in close collaboration with the [UW
Interactive Data Lab](https://idl.cs.washington.edu/).*
*The Vega-Altair open source project is not affiliated with Altair Engineering, Inc.*

## Documentation

See [Vega-Altair's Documentation Site](https://altair-viz.github.io) as well as the [Tutorial Notebooks](https://github.com/altair-viz/altair_notebooks). You can
run the notebooks directly in your browser by clicking on one of the following badges:

[![Binder](https://beta.mybinder.org/badge.svg)](https://beta.mybinder.org/v2/gh/altair-viz/altair_notebooks/master)
[![Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/altair-viz/altair_notebooks/blob/master/notebooks/Index.ipynb)

## Example

Here is an example using Vega-Altair to quickly visualize and display a dataset with the native Vega-Lite renderer in the JupyterLab:

```python
import altair as alt

# load a simple dataset as a pandas DataFrame
from vega_datasets import data
cars = data.cars()

alt.Chart(cars).mark_point().encode(
    x='Horsepower',
    y='Miles_per_Gallon',
    color='Origin',
)
```

![Vega-Altair Visualization](https://raw.githubusercontent.com/altair-viz/altair/main/images/cars.png)

One of the unique features of Vega-Altair, inherited from Vega-Lite, is a declarative grammar of not just visualization, but _interaction_.
With a few modifications to the example above we can create a linked histogram that is filtered based on a selection of the scatter plot.

```python
import altair as alt
from vega_datasets import data

source = data.cars()

brush = alt.selection_interval()

points = alt.Chart(source).mark_point().encode(
    x='Horsepower',
    y='Miles_per_Gallon',
    color=alt.condition(brush, 'Origin', alt.value('lightgray'))
).add_params(
    brush
)

bars = alt.Chart(source).mark_bar().encode(
    y='Origin',
    color='Origin',
    x='count(Origin)'
).transform_filter(
    brush
)

points & bars
```

![Vega-Altair Visualization Gif](https://raw.githubusercontent.com/altair-viz/altair/main/images/cars_scatter_bar.gif)

## Features

* Carefully-designed, declarative Python API.
* Auto-generated internal Python API that guarantees visualizations are type-checked and
  in full conformance with the [Vega-Lite](https://github.com/vega/vega-lite)
  specification.
* Display visualizations in JupyterLab, Jupyter Notebook, Visual Studio Code, on GitHub and
  [nbviewer](https://nbviewer.jupyter.org/), and many more.
* Export visualizations to various formats such as PNG/SVG images, stand-alone HTML pages and the
[Online Vega-Lite Editor](https://vega.github.io/editor/#/).
* Serialize visualizations as JSON files.

## Installation

Vega-Altair can be installed with:
```bash
pip install altair
```

If you are using the conda package manager, the equivalent is:
```bash
conda install altair -c conda-forge
```

For full installation instructions, please see [the documentation](https://altair-viz.github.io/getting_started/installation.html).

## Getting Help

If you have a question that is not addressed in the documentation,
you can post it on [StackOverflow](https://stackoverflow.com/questions/tagged/altair) using the `altair` tag.
For bugs and feature requests, please open a [Github Issue](https://github.com/altair-viz/altair/issues).

## Development

[![Hatch project](https://img.shields.io/badge/%F0%9F%A5%9A-Hatch-4051b5.svg)](https://github.com/pypa/hatch)
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
[![pytest](https://img.shields.io/badge/logo-pytest-blue?logo=pytest&labelColor=5c5c5c&label=%20)](https://github.com/pytest-dev/pytest)

You can find the instructions on how to install the package for development in [the documentation](https://altair-viz.github.io/getting_started/installation.html).

To run the tests and linters, use

```
hatch run test
```

For information on how to contribute your developments back to the Vega-Altair repository, see
[`CONTRIBUTING.md`](https://github.com/altair-viz/altair/blob/main/CONTRIBUTING.md)

## Citing Vega-Altair

[![JOSS Paper](https://joss.theoj.org/papers/10.21105/joss.01057/status.svg)](https://joss.theoj.org/papers/10.21105/joss.01057)

If you use Vega-Altair in academic work, please consider citing https://joss.theoj.org/papers/10.21105/joss.01057 as

```bib
@article{VanderPlas2018,
    doi = {10.21105/joss.01057},
    url = {https://doi.org/10.21105/joss.01057},
    year = {2018},
    publisher = {The Open Journal},
    volume = {3},
    number = {32},
    pages = {1057},
    author = {Jacob VanderPlas and Brian Granger and Jeffrey Heer and Dominik Moritz and Kanit Wongsuphasawat and Arvind Satyanarayan and Eitan Lees and Ilia Timofeev and Ben Welsh and Scott Sievert},
    title = {Altair: Interactive Statistical Visualizations for Python},
    journal = {Journal of Open Source Software}
}
```
Please additionally consider citing the [Vega-Lite](https://vega.github.io/vega-lite/) project, which Vega-Altair is based on: https://dl.acm.org/doi/10.1109/TVCG.2016.2599030

```bib
@article{Satyanarayan2017,
    author={Satyanarayan, Arvind and Moritz, Dominik and Wongsuphasawat, Kanit and Heer, Jeffrey},
    title={Vega-Lite: A Grammar of Interactive Graphics},
    journal={IEEE transactions on visualization and computer graphics},
    year={2017},
    volume={23},
    number={1},
    pages={341-350},
    publisher={IEEE}
}
```


An ASGI web server, for Python.

---

[![Build Status](https://github.com/encode/uvicorn/workflows/Test%20Suite/badge.svg)](https://github.com/encode/uvicorn/actions)
[![Package version](https://badge.fury.io/py/uvicorn.svg)](https://pypi.python.org/pypi/uvicorn)
[![Supported Python Version](https://img.shields.io/pypi/pyversions/uvicorn.svg?color=%2334D058)](https://pypi.org/project/uvicorn)

**Documentation**: [https://www.uvicorn.org](https://www.uvicorn.org)

---

Uvicorn is an ASGI web server implementation for Python.

Until recently Python has lacked a minimal low-level server/application interface for
async frameworks. The [ASGI specification][asgi] fills this gap, and means we're now able to
start building a common set of tooling usable across all async frameworks.

Uvicorn supports HTTP/1.1 and WebSockets.

## Quickstart

Install using `pip`:

```shell
$ pip install uvicorn
```

This will install uvicorn with minimal (pure Python) dependencies.

```shell
$ pip install 'uvicorn[standard]'
```

This will install uvicorn with "Cython-based" dependencies (where possible) and other "optional extras".

In this context, "Cython-based" means the following:

- the event loop `uvloop` will be installed and used if possible.
- the http protocol will be handled by `httptools` if possible.

Moreover, "optional extras" means that:

- the websocket protocol will be handled by `websockets` (should you want to use `wsproto` you'd need to install it manually) if possible.
- the `--reload` flag in development mode will use `watchfiles`.
- windows users will have `colorama` installed for the colored logs.
- `python-dotenv` will be installed should you want to use the `--env-file` option.
- `PyYAML` will be installed to allow you to provide a `.yaml` file to `--log-config`, if desired.

Create an application, in `example.py`:

```python
async def app(scope, receive, send):
    assert scope['type'] == 'http'

    await send({
        'type': 'http.response.start',
        'status': 200,
        'headers': [
            (b'content-type', b'text/plain'),
        ],
    })
    await send({
        'type': 'http.response.body',
        'body': b'Hello, world!',
    })
```

Run the server:

```shell
$ uvicorn example:app
```

---

## Why ASGI?

Most well established Python Web frameworks started out as WSGI-based frameworks.

WSGI applications are a single, synchronous callable that takes a request and returns a response.
This doesn’t allow for long-lived connections, like you get with long-poll HTTP or WebSocket connections,
which WSGI doesn't support well.

Having an async concurrency model also allows for options such as lightweight background tasks,
and can be less of a limiting factor for endpoints that have long periods being blocked on network
I/O such as dealing with slow HTTP requests.

---

## Alternative ASGI servers

A strength of the ASGI protocol is that it decouples the server implementation
from the application framework. This allows for an ecosystem of interoperating
webservers and application frameworks.

### Daphne

The first ASGI server implementation, originally developed to power Django Channels, is [the Daphne webserver][daphne].

It is run widely in production, and supports HTTP/1.1, HTTP/2, and WebSockets.

Any of the example applications given here can equally well be run using `daphne` instead.

```
$ pip install daphne
$ daphne app:App
```

### Hypercorn

[Hypercorn][hypercorn] was initially part of the Quart web framework, before
being separated out into a standalone ASGI server.

Hypercorn supports HTTP/1.1, HTTP/2, and WebSockets.

It also supports [the excellent `trio` async framework][trio], as an alternative to `asyncio`.

```
$ pip install hypercorn
$ hypercorn app:App
```

### Mangum

[Mangum][mangum] is an adapter for using ASGI applications with AWS Lambda & API Gateway.

### Granian

[Granian][granian] is an ASGI compatible Rust HTTP server which supports HTTP/2, TLS and WebSockets.

---

Uvicorn is BSD licensed code.
Designed & crafted with care.
— 🦄  —

[asgi]: https://asgi.readthedocs.io/en/latest/
[daphne]: https://github.com/django/daphne
[hypercorn]: https://github.com/pgjones/hypercorn
[trio]: https://trio.readthedocs.io
[mangum]: https://github.com/jordaneremieff/mangum
[granian]: https://github.com/emmett-framework/granian


===========
MongoEngine
===========
:Info: MongoEngine is an ORM-like layer on top of PyMongo.
:Repository: https://github.com/MongoEngine/mongoengine
:Author: Harry Marr (http://github.com/hmarr)
:Maintainer: Stefan Wójcik (http://github.com/wojcikstefan)

.. image:: https://travis-ci.org/MongoEngine/mongoengine.svg?branch=master
  :target: https://travis-ci.org/MongoEngine/mongoengine

.. image:: https://coveralls.io/repos/github/MongoEngine/mongoengine/badge.svg?branch=master
  :target: https://coveralls.io/github/MongoEngine/mongoengine?branch=master

.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
  :target: https://github.com/ambv/black

.. image:: https://pepy.tech/badge/mongoengine/month
  :target: https://pepy.tech/project/mongoengine

.. image:: https://img.shields.io/pypi/v/mongoengine.svg
  :target: https://pypi.python.org/pypi/mongoengine

About
=====
MongoEngine is a Python Object-Document Mapper for working with MongoDB.
Documentation is available at https://mongoengine-odm.readthedocs.io - there
is currently a `tutorial <https://mongoengine-odm.readthedocs.io/tutorial.html>`_,
a `user guide <https://mongoengine-odm.readthedocs.io/guide/index.html>`_, and
an `API reference <https://mongoengine-odm.readthedocs.io/apireference.html>`_.

Supported MongoDB Versions
==========================
MongoEngine is currently tested against MongoDB v3.6, v4.0, v4.4, v5.0, v6.0 and v7.0. Future versions
should be supported as well, but aren't actively tested at the moment. Make
sure to open an issue or submit a pull request if you experience any problems
with a more recent MongoDB versions.

Installation
============
We recommend the use of `virtualenv <https://virtualenv.pypa.io/>`_ and of
`pip <https://pip.pypa.io/>`_. You can then use ``python -m pip install -U mongoengine``.
You may also have `setuptools <http://peak.telecommunity.com/DevCenter/setuptools>`_
and thus you can use ``easy_install -U mongoengine``. Another option is
`pipenv <https://docs.pipenv.org/>`_. You can then use ``pipenv install mongoengine``
to both create the virtual environment and install the package. Otherwise, you can
download the source from `GitHub <http://github.com/MongoEngine/mongoengine>`_ and
run ``python setup.py install``.

The support for Python2 was dropped with MongoEngine 0.20.0

Dependencies
============
All of the dependencies can easily be installed via `python -m pip <https://pip.pypa.io/>`_.
At the very least, you'll need these two packages to use MongoEngine:

- pymongo>=3.4

If you utilize a ``DateTimeField``, you might also use a more flexible date parser:

- dateutil>=2.1.0

If you need to use an ``ImageField`` or ``ImageGridFsProxy``:

- Pillow>=2.0.0

If you need to use signals:

- blinker>=1.3

Examples
========
Some simple examples of what MongoEngine code looks like:

.. code :: python

    from mongoengine import *
    connect('mydb')

    class BlogPost(Document):
        title = StringField(required=True, max_length=200)
        posted = DateTimeField(default=datetime.datetime.utcnow)
        tags = ListField(StringField(max_length=50))
        meta = {'allow_inheritance': True}

    class TextPost(BlogPost):
        content = StringField(required=True)

    class LinkPost(BlogPost):
        url = StringField(required=True)

    # Create a text-based post
    >>> post1 = TextPost(title='Using MongoEngine', content='See the tutorial')
    >>> post1.tags = ['mongodb', 'mongoengine']
    >>> post1.save()

    # Create a link-based post
    >>> post2 = LinkPost(title='MongoEngine Docs', url='hmarr.com/mongoengine')
    >>> post2.tags = ['mongoengine', 'documentation']
    >>> post2.save()

    # Iterate over all posts using the BlogPost superclass
    >>> for post in BlogPost.objects:
    ...     print('===', post.title, '===')
    ...     if isinstance(post, TextPost):
    ...         print(post.content)
    ...     elif isinstance(post, LinkPost):
    ...         print('Link:', post.url)
    ...

    # Count all blog posts and its subtypes
    >>> BlogPost.objects.count()
    2
    >>> TextPost.objects.count()
    1
    >>> LinkPost.objects.count()
    1

    # Count tagged posts
    >>> BlogPost.objects(tags='mongoengine').count()
    2
    >>> BlogPost.objects(tags='mongodb').count()
    1

Tests
=====
To run the test suite, ensure you are running a local instance of MongoDB on
the standard port and have ``pytest`` installed. Then, run ``pytest tests/``.

To run the test suite on every supported Python and PyMongo version, you can
use ``tox``. You'll need to make sure you have each supported Python version
installed in your environment and then:

.. code-block:: shell

    # Install tox
    $ python -m pip install tox
    # Run the test suites
    $ tox

Community
=========
- `MongoEngine Users mailing list
  <http://groups.google.com/group/mongoengine-users>`_
- `MongoEngine Developers mailing list
  <http://groups.google.com/group/mongoengine-dev>`_

Contributing
============
We welcome contributions! See the `Contribution guidelines <https://github.com/MongoEngine/mongoengine/blob/master/CONTRIBUTING.rst>`_


Python Slack SDK

The Slack platform offers several APIs to build apps. Each Slack API delivers part of the capabilities from the platform, so that you can pick just those that fit for your needs. This SDK offers a corresponding package for each of Slack’s APIs. They are small and powerful when used independently, and work seamlessly when used together, too.

**Comprehensive documentation on using the Slack Python can be found at [https://slack.dev/python-slack-sdk/](https://slack.dev/python-slack-sdk/)**

---

Whether you're building a custom app for your team, or integrating a third party service into your Slack workflows, Slack Developer Kit for Python allows you to leverage the flexibility of Python to get your project up and running as quickly as possible.

The **Python Slack SDK** allows interaction with:

- `slack_sdk.web`: for calling the [Web API methods][api-methods]
- `slack_sdk.webhook`: for utilizing the [Incoming Webhooks](https://api.slack.com/messaging/webhooks) and [`response_url`s in payloads](https://api.slack.com/interactivity/handling#message_responses)
- `slack_sdk.signature`: for [verifying incoming requests from the Slack API server](https://api.slack.com/authentication/verifying-requests-from-slack)
- `slack_sdk.socket_mode`: for receiving and sending messages over [Socket Mode](https://api.slack.com/socket-mode) connections
- `slack_sdk.audit_logs`: for utilizing [Audit Logs APIs](https://api.slack.com/admins/audit-logs)
- `slack_sdk.scim`: for utilizing [SCIM APIs](https://api.slack.com/admins/scim)
- `slack_sdk.oauth`: for implementing the [Slack OAuth flow](https://api.slack.com/authentication/oauth-v2)
- `slack_sdk.models`: for constructing [Block Kit](https://api.slack.com/block-kit) UI components using easy-to-use builders
- `slack_sdk.rtm`: for utilizing the [RTM API][rtm-docs]

If you want to use our [Events API][events-docs] and Interactivity features, please check the [Bolt for Python][bolt-python] library. Details on the Tokens and Authentication can be found in our [Auth Guide](https://slack.dev/python-slack-sdk/installation/).

## slackclient is in maintenance mode

Are you looking for [slackclient](https://pypi.org/project/slackclient/)? The website is live [here](https://slack.dev/python-slackclient/) just like before. However, the slackclient project is in maintenance mode now and this [`slack_sdk`](https://pypi.org/project/slack-sdk/) is the successor. If you have time to make a migration to slack_sdk v3, please follow [our migration guide](https://slack.dev/python-slack-sdk/v3-migration/) to ensure your app continues working after updating.

## Table of contents

* [Requirements](#requirements)
* [Installation](#installation)
* [Getting started tutorial](#getting-started-tutorial)
* [Basic Usage of the Web Client](#basic-usage-of-the-web-client)
  * [Sending a message to Slack](#sending-a-message-to-slack)
  * [Uploading files to Slack](#uploading-files-to-slack)
* [Async usage](#async-usage)
  * [WebClient as a script](#asyncwebclient-in-a-script)
  * [WebClient in a framework](#asyncwebclient-in-a-framework)
* [Advanced Options](#advanced-options)
  * [SSL](#ssl)
  * [Proxy](#proxy)
  * [DNS performance](#dns-performance)
  * [Example](#example)
* [Migrating from v1](#migrating-from-v1)
* [Support](#support)
* [Development](#development)

### Requirements

---

This library requires Python 3.6 and above. If you require Python 2, please use our [SlackClient - v1.x][slackclientv1]. If you're unsure how to check what version of Python you're on, you can check it using the following:

> **Note:** You may need to use `python3` before your commands to ensure you use the correct Python path. e.g. `python3 --version`

```bash
python --version

-- or --

python3 --version
```

### Installation

We recommend using [PyPI][pypi] to install the Slack Developer Kit for Python.

```bash
$ pip install slack_sdk
```

### Getting started tutorial

---

We've created this [tutorial](https://github.com/slackapi/python-slack-sdk/tree/main/tutorial) to build a basic Slack app in less than 10 minutes. It requires some general programming knowledge, and Python basics. It focuses on the interacting with Slack's Web and RTM API. Use it to give you an idea of how to use this SDK.

**[Read the tutorial to get started!](https://github.com/slackapi/python-slack-sdk/tree/main/tutorial)**

### Basic Usage of the Web Client

---

Slack provide a Web API that gives you the ability to build applications that interact with Slack in a variety of ways. This Development Kit is a module based wrapper that makes interaction with that API easier. We have a basic example here with some of the more common uses but a full list of the available methods are available [here][api-methods]. More detailed examples can be found in [our guide](https://slack.dev/python-slack-sdk/web/).

#### Sending a message to Slack

One of the most common use-cases is sending a message to Slack. If you want to send a message as your app, or as a user, this method can do both. In our examples, we specify the channel name, however it is recommended to use the `channel_id` where possible. Also, if your app's bot user is not in a channel yet, invite the bot user before running the code snippet (or add `chat:write.public` to Bot Token Scopes for posting in any public channels).

```python
import os
from slack_sdk import WebClient
from slack_sdk.errors import SlackApiError

client = WebClient(token=os.environ['SLACK_BOT_TOKEN'])

try:
    response = client.chat_postMessage(channel='#random', text="Hello world!")
    assert response["message"]["text"] == "Hello world!"
except SlackApiError as e:
    # You will get a SlackApiError if "ok" is False
    assert e.response["ok"] is False
    assert e.response["error"]  # str like 'invalid_auth', 'channel_not_found'
    print(f"Got an error: {e.response['error']}")
    # Also receive a corresponding status_code
    assert isinstance(e.response.status_code, int)
    print(f"Received a response status_code: {e.response.status_code}")
```

Here we also ensure that the response back from Slack is a successful one and that the message is the one we sent by using the `assert` statement.

#### Uploading files to Slack

We've changed the process for uploading files to Slack to be much easier and straight forward. You can now just include a path to the file directly in the API call and upload it that way.

```python
import os
from slack_sdk import WebClient
from slack_sdk.errors import SlackApiError

client = WebClient(token=os.environ['SLACK_BOT_TOKEN'])

try:
    filepath="./tmp.txt"
    response = client.files_upload_v2(channel='C0123456789', file=filepath)
    assert response["file"]  # the uploaded file
except SlackApiError as e:
    # You will get a SlackApiError if "ok" is False
    assert e.response["ok"] is False
    assert e.response["error"]  # str like 'invalid_auth', 'channel_not_found'
    print(f"Got an error: {e.response['error']}")
```

More details on the `files_upload_v2` method can be found [here][files_upload_v2].

### Async usage

`AsyncWebClient` in this SDK requires [AIOHttp][aiohttp] under the hood for asynchronous requests.

#### AsyncWebClient in a script

```python
import asyncio
import os
from slack_sdk.web.async_client import AsyncWebClient
from slack_sdk.errors import SlackApiError

client = AsyncWebClient(token=os.environ['SLACK_BOT_TOKEN'])

async def post_message():
    try:
        response = await client.chat_postMessage(channel='#random', text="Hello world!")
        assert response["message"]["text"] == "Hello world!"
    except SlackApiError as e:
        assert e.response["ok"] is False
        assert e.response["error"]  # str like 'invalid_auth', 'channel_not_found'
        print(f"Got an error: {e.response['error']}")

asyncio.run(post_message())
```

#### AsyncWebClient in a framework

If you are using a framework invoking the asyncio event loop like : sanic/jupyter notebook/etc.

```python
import os
from slack_sdk.web.async_client import AsyncWebClient
from slack_sdk.errors import SlackApiError

client = AsyncWebClient(token=os.environ['SLACK_BOT_TOKEN'])
# Define this as an async function
async def send_to_slack(channel, text):
    try:
        # Don't forget to have await as the client returns asyncio.Future
        response = await client.chat_postMessage(channel=channel, text=text)
        assert response["message"]["text"] == text
    except SlackApiError as e:
        assert e.response["ok"] is False
        assert e.response["error"]  # str like 'invalid_auth', 'channel_not_found'
        raise e

from aiohttp import web

async def handle_requests(request: web.Request) -> web.Response:
    text = 'Hello World!'
    if 'text' in request.query:
        text = "\t".join(request.query.getall("text"))
    try:
        await send_to_slack(channel="#random", text=text)
        return web.json_response(data={'message': 'Done!'})
    except SlackApiError as e:
        return web.json_response(data={'message': f"Failed due to {e.response['error']}"})

if __name__ == "__main__":
    app = web.Application()
    app.add_routes([web.get("/", handle_requests)])
    # e.g., http://localhost:3000/?text=foo&text=bar
    web.run_app(app, host="0.0.0.0", port=3000)
```

### Advanced Options

#### SSL

You can provide a custom SSL context or disable verification by passing the `ssl` option, supported by both the RTM and the Web client.

For async requests, see the [AIOHttp SSL documentation](https://docs.aiohttp.org/en/stable/client_advanced.html#ssl-control-for-tcp-sockets).

For sync requests, see the [urllib SSL documentation](https://docs.python.org/3/library/urllib.request.html#urllib.request.urlopen).

#### Proxy

A proxy is supported when making async requests, pass the `proxy` option, supported by both the RTM and the Web client.

For async requests, see [AIOHttp Proxy documentation](https://docs.aiohttp.org/en/stable/client_advanced.html#proxy-support).

For sync requests, setting either `HTTPS_PROXY` env variable or the `proxy` option works.

#### DNS performance

Using the async client and looking for a performance boost? Installing the optional dependencies (aiodns) may help speed up DNS resolving by the client. We've included it as an extra called "optional":
```bash
$ pip install slack_sdk[optional]
```

#### Example

```python
import os
from slack_sdk import WebClient
from ssl import SSLContext

sslcert = SSLContext()
# pip3 install proxy.py
# proxy --port 9000 --log-level d
proxyinfo = "http://localhost:9000"

client = WebClient(
    token=os.environ['SLACK_BOT_TOKEN'],
    ssl=sslcert,
    proxy=proxyinfo
)
response = client.chat_postMessage(channel="#random", text="Hello World!")
print(response)
```

### Migrating from v2

If you're migrating from slackclient v2.x of slack_sdk to v3.x, Please follow our migration guide to ensure your app continues working after updating.

**[Check out the Migration Guide here!](https://slack.dev/python-slack-sdk/v3-migration/)**

### Migrating from v1

If you're migrating from v1.x of slackclient to v2.x, Please follow our migration guide to ensure your app continues working after updating.

**[Check out the Migration Guide here!](https://github.com/slackapi/python-slack-sdk/wiki/Migrating-to-2.x)**

### Support

---

If you get stuck, we’re here to help. The following are the best ways to get assistance working through your issue:

Use our [Github Issue Tracker][gh-issues] for reporting bugs or requesting features.
Visit the [Slack Community][slack-community] for getting help using Slack Developer Kit for Python or just generally bond with your fellow Slack developers.

### Contributing

We welcome contributions from everyone! Please check out our
[Contributor's Guide](.github/contributing.md) for how to contribute in a
helpful and collaborative way.

[slackclientv1]: https://github.com/slackapi/python-slackclient/tree/v1
[api-methods]: https://api.slack.com/methods
[rtm-docs]: https://api.slack.com/rtm
[events-docs]: https://api.slack.com/events-api
[bolt-python]: https://github.com/slackapi/bolt-python
[pypi]: https://pypi.org/
[gh-issues]: https://github.com/slackapi/python-slack-sdk/issues
[slack-community]: https://slackcommunity.com/
[files_upload_v2]: https://github.com/slackapi/python-slack-sdk/releases/tag/v3.19.0
[aiohttp]: https://aiohttp.readthedocs.io/


# tmuxp

Session manager for tmux, which allows users to save and load tmux sessions through simple configuration files. Powered by [libtmux](https://github.com/tmux-python/libtmux).

[![Python Package](https://img.shields.io/pypi/v/tmuxp.svg)](https://pypi.org/project/tmuxp/)
[![Docs](https://github.com/tmux-python/tmuxp/workflows/docs/badge.svg)](https://tmuxp.git-pull.com/)
[![Build status](https://github.com/tmux-python/tmuxp/workflows/tests/badge.svg)](https://github.com/tmux-python/tmuxp/actions?query=workflow%3A%22tests%22)
[![Code Coverage](https://codecov.io/gh/tmux-python/tmuxp/branch/master/graph/badge.svg)](https://codecov.io/gh/tmux-python/tmuxp)
[![License](https://img.shields.io/github/license/tmux-python/tmuxp.svg)](https://github.com/tmux-python/tmuxp/blob/master/LICENSE)

**New to tmux?** [The Tao of tmux](https://leanpub.com/the-tao-of-tmux)
is available on Leanpub and [Amazon Kindle](http://amzn.to/2gPfRhC).
Read and browse the book for free [on the
web](https://leanpub.com/the-tao-of-tmux/read).

**Have some spare time?** Help us triage and code review and the tracker. See [issue
#290](https://github.com/tmux-python/tmuxp/discussions/290)!

# Installation

pip:

```console
$ pip install --user tmuxp
```

Homebrew:

```console
$ brew install tmuxp
```

Debian / ubuntu:

```console
$ sudo apt install tmuxp
```

Nix:

```console
$ [[ -z $(which tmux) ]] && (nix-env -i tmux && nix-env -i tmuxp) || nix-env -i tmuxp
```

Find the package for your distro on repology: <https://repology.org/project/tmuxp/versions>

Developmental releases:

- [pip](https://pip.pypa.io/en/stable/):

  ```console
  $ pip install --user --upgrade --pre tmuxp
  ```

- [pipx](https://pypa.github.io/pipx/docs/):

  ```console
  $ pipx install --suffix=@next 'tmuxp' --pip-args '\--pre' --force
  ```

  Then use `tmuxp@next load [session]`.

# Load a tmux session

Load tmux sessions via json and YAML,
[tmuxinator](https://github.com/aziz/tmuxinator) and
[teamocil](https://github.com/remiprev/teamocil) style.

```yaml
session_name: 4-pane-split
windows:
  - window_name: dev window
    layout: tiled
    shell_command_before:
      - cd ~/ # run as a first command in all panes
    panes:
      - shell_command: # pane no. 1
          - cd /var/log # run multiple commands in this pane
          - ls -al | grep \.log
      - echo second pane # pane no. 2
      - echo third pane # pane no. 3
      - echo forth pane # pane no. 4
```

Save as _mysession.yaml_, and load:

```console
$ tmuxp load ./mysession.yaml
```

Projects with _.tmuxp.yaml_ or _.tmuxp.json_ load via directory:

```console
$ tmuxp load path/to/my/project/
```

Load multiple at once (in bg, offer to attach last):

```console
$ tmuxp load mysession ./another/project/
```

Name a session:

```console
$ tmuxp load -s session_name ./mysession.yaml
```

[simple](http://tmuxp.git-pull.com/examples.html#short-hand-inline) and
[very
elaborate](http://tmuxp.git-pull.com/examples.html#super-advanced-dev-environment)
config examples

# User-level configurations

tmuxp checks for configs in user directories:

- `$TMUXP_CONFIGDIR`, if set
- `$XDG_CONFIG_HOME`, usually _$HOME/.config/tmuxp/_
- `$HOME/.tmuxp/`

Load your tmuxp config from anywhere by using the filename, assuming
_\~/.config/tmuxp/mysession.yaml_ (or _.json_):

```console
$ tmuxp load mysession
```

See [author's tmuxp configs](https://github.com/tony/tmuxp-config) and
the projects'
[tmuxp.yaml](https://github.com/tmux-python/tmuxp/blob/master/.tmuxp.yaml).

# Shell

_New in 1.6.0_:

`tmuxp shell` launches into a python console preloaded with the attached
server, session, and window in
[libtmux](https://github.com/tmux-python/libtmux) objects.

```console
$ tmuxp shell

(Pdb) server
<libtmux.server.Server object at 0x7f7dc8e69d10>
(Pdb) server.sessions
[Session($1 your_project)]
(Pdb) session
Session($1 your_project)
(Pdb) session.name
'your_project'
(Pdb) window
Window(@3 1:your_window, Session($1 your_project))
(Pdb) window.name
'your_window'
(Pdb) window.panes
[Pane(%6 Window(@3 1:your_window, Session($1 your_project)))
(Pdb) pane
Pane(%6 Window(@3 1:your_window, Session($1 your_project))
```

Supports [PEP
553](https://www.python.org/dev/peps/pep-0553/) `breakpoint()`
(including `PYTHONBREAKPOINT`). Also supports direct commands via `-c`:

```console
$ tmuxp shell -c 'print(window.name)'
my_window

$ tmuxp shell -c 'print(window.name.upper())'
MY_WINDOW
```

Read more on [tmuxp shell](https://tmuxp.git-pull.com/cli/shell.html) in
the CLI docs.

# Pre-load hook

Run custom startup scripts (such as installing project dependencies
before loading tmux. See the
[bootstrap_env.py](https://github.com/tmux-python/tmuxp/blob/master/bootstrap_env.py)
and
[before_script](http://tmuxp.git-pull.com/examples.html#bootstrap-project-before-launch)
example

# Load in detached state

You can also load sessions in the background by passing `-d` flag

# Screenshot

<img src="https://raw.githubusercontent.com/tmux-python/tmuxp/master/docs/_static/tmuxp-demo.gif" class="align-center" style="width:45.0%" alt="image" />

# Freeze a tmux session

Snapshot your tmux layout, pane paths, and window/session names.

```console
$ tmuxp freeze session-name
```

See more about [freezing
tmux](https://tmuxp.git-pull.com/cli/freeze.html) sessions.

# Convert a session file

Convert a session file from yaml to json and vice versa.

```console
$ tmuxp convert filename
```

This will prompt you for confirmation and shows you the new file that is
going to be written.

You can auto confirm the prompt. In this case no preview will be shown.

```console
$ tmuxp convert -y filename
$ tmuxp convert --yes filename
```

# Plugin System

tmuxp has a plugin system to allow for custom behavior. See more about
the [Plugin System](http://tmuxp.git-pull.com/plugin_system.html).

# Debugging Helpers

The `load` command provides a way to log output to a log file for
debugging purposes.

```console
$ tmuxp load --log-file <log-file-name> .
```

Collect system info to submit with a Github issue:

```console
$ tmuxp debug-info
------------------
environment:
    system: Linux
    arch: x86_64

# ... so on
```

# Docs / Reading material

See the [Quickstart](http://tmuxp.git-pull.com/quickstart.html).

[Documentation](http://tmuxp.git-pull.com) homepage (also in
[中文](http://tmuxp-zh.rtfd.org/))

Want to learn more about tmux itself? [Read The Tao of Tmux
online](http://tmuxp.git-pull.com/about_tmux.html).

# Donations

Your donations fund development of new features, testing and support.
Your money will go directly to maintenance and development of the
project. If you are an individual, feel free to give whatever feels
right for the value you get out of the project.

See donation options at <https://git-pull.com/support.html>.

# Project details

- tmux support: 1.8+
- python support: >= 3.8, pypy, pypy3
- Source: <https://github.com/tmux-python/tmuxp>
- Docs: <https://tmuxp.git-pull.com>
- API: <https://tmuxp.git-pull.com/api.html>
- Changelog: <https://tmuxp.git-pull.com/history.html>
- Issues: <https://github.com/tmux-python/tmuxp/issues>
- Test Coverage: <https://codecov.io/gh/tmux-python/tmuxp>
- pypi: <https://pypi.python.org/pypi/tmuxp>
- Open Hub: <https://www.openhub.net/p/tmuxp-python>
- Repology: <https://repology.org/project/tmuxp/versions>
- License: [MIT](http://opensource.org/licenses/MIT).


phonenumbers Python Library
===========================

[![Coverage Status](https://coveralls.io/repos/daviddrysdale/python-phonenumbers/badge.svg?branch=dev&service=github)](https://coveralls.io/github/daviddrysdale/python-phonenumbers?branch=dev)

This is a Python port of [Google's libphonenumber library](https://github.com/google/libphonenumber)
It supports Python 2.5-2.7 and Python 3.x (in the same codebase, with no
[2to3](http://docs.python.org/2/library/2to3.html) conversion needed).

Original Java code is Copyright (C) 2009-2015 The Libphonenumber Authors.

Release [HISTORY](https://github.com/daviddrysdale/python-phonenumbers/blob/dev/python/HISTORY.md),
derived from [upstream release notes](https://github.com/google/libphonenumber/blob/master/release_notes.txt).

[Documentation](https://daviddrysdale.github.io/python-phonenumbers/)

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

Install using [pip](https://pypi.org/project/phonenumbers/) with:
```
pip install phonenumbers
```

Example Usage
-------------

The main object that the library deals with is a `PhoneNumber` object.  You can create this from a string
representing a phone number using the `parse` function, but you also need to specify the country
that the phone number is being dialled from (unless the number is in E.164 format, which is globally
unique).

```pycon
>>> import phonenumbers
>>> x = phonenumbers.parse("+442083661177", None)
>>> print(x)
Country Code: 44 National Number: 2083661177 Leading Zero: False
>>> type(x)
<class 'phonenumbers.phonenumber.PhoneNumber'>
>>> y = phonenumbers.parse("020 8366 1177", "GB")
>>> print(y)
Country Code: 44 National Number: 2083661177 Leading Zero: False
>>> x == y
True
>>> z = phonenumbers.parse("00 1 650 253 2222", "GB")  # as dialled from GB, not a GB number
>>> print(z)
Country Code: 1 National Number: 6502532222 Leading Zero(s): False
```

The `PhoneNumber` object that `parse` produces typically still needs to be validated, to check whether
it's a *possible* number (e.g. it has the right number of digits) or a *valid* number (e.g. it's
in an assigned exchange).

```pycon
>>> z = phonenumbers.parse("+120012301", None)
>>> print(z)
Country Code: 1 National Number: 20012301 Leading Zero: False
>>> phonenumbers.is_possible_number(z)  # too few digits for USA
False
>>> phonenumbers.is_valid_number(z)
False
>>> z = phonenumbers.parse("+12001230101", None)
>>> print(z)
Country Code: 1 National Number: 2001230101 Leading Zero: False
>>> phonenumbers.is_possible_number(z)
True
>>> phonenumbers.is_valid_number(z)  # NPA 200 not used
False
```

The `parse` function will also fail completely (with a `NumberParseException`) on inputs that cannot
be uniquely parsed, or that  can't possibly be phone numbers.

```pycon
>>> z = phonenumbers.parse("02081234567", None)  # no region, no + => unparseable
Traceback (most recent call last):
  File "phonenumbers/phonenumberutil.py", line 2350, in parse
    "Missing or invalid default region.")
phonenumbers.phonenumberutil.NumberParseException: (0) Missing or invalid default region.
>>> z = phonenumbers.parse("gibberish", None)
Traceback (most recent call last):
  File "phonenumbers/phonenumberutil.py", line 2344, in parse
    "The string supplied did not seem to be a phone number.")
phonenumbers.phonenumberutil.NumberParseException: (1) The string supplied did not seem to be a phone number.
```

Once you've got a phone number, a common task is to format it in a standardized format.  There are a few
formats available (under `PhoneNumberFormat`), and the `format_number` function does the formatting.

```pycon
>>> phonenumbers.format_number(x, phonenumbers.PhoneNumberFormat.NATIONAL)
'020 8366 1177'
>>> phonenumbers.format_number(x, phonenumbers.PhoneNumberFormat.INTERNATIONAL)
'+44 20 8366 1177'
>>> phonenumbers.format_number(x, phonenumbers.PhoneNumberFormat.E164)
'+442083661177'
```

If your application has a UI that allows the user to type in a phone number, it's nice to get the formatting
applied as the user types.   The `AsYouTypeFormatter` object allows this.

```pycon
>>> formatter = phonenumbers.AsYouTypeFormatter("US")
>>> formatter.input_digit("6")
'6'
>>> formatter.input_digit("5")
'65'
>>> formatter.input_digit("0")
'650'
>>> formatter.input_digit("2")
'650 2'
>>> formatter.input_digit("5")
'650 25'
>>> formatter.input_digit("3")
'650 253'
>>> formatter.input_digit("2")
'650-2532'
>>> formatter.input_digit("2")
'(650) 253-22'
>>> formatter.input_digit("2")
'(650) 253-222'
>>> formatter.input_digit("2")
'(650) 253-2222'
```

Sometimes, you've got a larger block of text that may or may not have some phone numbers inside it.  For this,
the `PhoneNumberMatcher` object provides the relevant functionality; you can iterate over it to retrieve a
sequence of `PhoneNumberMatch` objects.  Each of these match objects holds a `PhoneNumber` object together
with information about where the match occurred in the original string.

```pycon
>>> text = "Call me at 510-748-8230 if it's before 9:30, or on 703-4800500 after 10am."
>>> for match in phonenumbers.PhoneNumberMatcher(text, "US"):
...     print(match)
...
PhoneNumberMatch [11,23) 510-748-8230
PhoneNumberMatch [51,62) 703-4800500
>>> for match in phonenumbers.PhoneNumberMatcher(text, "US"):
...     print(phonenumbers.format_number(match.number, phonenumbers.PhoneNumberFormat.E164))
...
+15107488230
+17034800500
```

You might want to get some information about the location that corresponds to a phone number.  The
`geocoder.description_for_number` does this, when possible.

```pycon
>>> from phonenumbers import geocoder
>>> ch_number = phonenumbers.parse("0431234567", "CH")
>>> geocoder.description_for_number(ch_number, "de")
'Zürich'
>>> geocoder.description_for_number(ch_number, "en")
'Zurich'
>>> geocoder.description_for_number(ch_number, "fr")
'Zurich'
>>> geocoder.description_for_number(ch_number, "it")
'Zurigo'
```

For mobile numbers in some countries, you can also find out information about which carrier
originally owned a phone number.

```pycon
>>> from phonenumbers import carrier
>>> ro_number = phonenumbers.parse("+40721234567", "RO")
>>> carrier.name_for_number(ro_number, "en")
'Vodafone'
```

You might also be able to retrieve a list of time zone names that the number potentially
belongs to.

```pycon
>>> from phonenumbers import timezone
>>> gb_number = phonenumbers.parse("+447986123456", "GB")
>>> timezone.time_zones_for_number(gb_number)
('Atlantic/Reykjavik', 'Europe/London')
```

For more information about the other functionality available from the library, look in the unit tests or in the original
[libphonenumber project](https://github.com/google/libphonenumber).

Memory Usage
------------

The library includes a lot of metadata, potentially giving a significant memory overhead.  There are two mechanisms
for dealing with this.

* The normal metadata (just over 2 MiB of generated Python code) for the core functionality of the library is loaded
  on-demand, on a region-by-region basis (i.e. the metadata for a region is only loaded on the first time it is needed).
* Metadata for extended functionality is held in separate packages, which therefore need to be explicitly
  loaded separately.  This affects:
    * The geocoding metadata (~19 MiB), which is held in `phonenumbers.geocoder` and used by the geocoding functions
      (`geocoder.description_for_number`, `geocoder.description_for_valid_number` or
      `geocoder.country_name_for_number`).
    * The carrier metadata (~1 MiB), which is held in `phonenumbers.carrier` and used by the mapping functions
      (`carrier.name_for_number` or `carrier.name_for_valid_number`).
    * The timezone metadata (~100 KiB), which is held in `phonenumbers.timezone` and used by the timezone functions
      (`time_zones_for_number` or `time_zones_for_geographical_number`).

The `phonenumberslite` version of the library does not include the geocoder, carrier and timezone packages,
which can be useful if you have problems installing the main `phonenumbers` library due to space/memory limitations.

If you need to ensure that the metadata memory use is accounted for at start of day (i.e. that a subsequent on-demand
load of metadata will not cause a pause or memory exhaustion):

* Force-load the normal metadata by calling `phonenumbers.PhoneMetadata.load_all()`.
* Force-load the extended metadata by `import`ing the appropriate packages (`phonenumbers.geocoder`,
  `phonenumbers.carrier`, `phonenumbers.timezone`).

The `phonenumberslite` version of the package does not include the geocoding, carrier and timezone metadata,
which can be useful if you have problems installing the main `phonenumbers` package due to space/memory limitations.

Static Typing
-------------

The library includes a set of type [stub files](https://www.python.org/dev/peps/pep-0484/#stub-files) to support static
type checking by library users. These stub files signal the types that should be used, and may also be of use in IDEs
which have integrated type checking functionalities.

These files are written for Python 3, and as such type checking the library with these stubs on Python 2.5-2.7 is
unsupported.

Project Layout
--------------

* The `python/` directory holds the Python code.
* The `resources/` directory is a copy of the `resources/`
  directory from
  [libphonenumber](https://github.com/google/libphonenumber/tree/master/resources).
  This is not needed to run the Python code, but is needed when upstream
  changes to the master metadata need to be incorporated.
* The `tools/` directory holds the tools that are used to process upstream
  changes to the master metadata.