# Copyright (C) Weimin Wang
# This file is distributed under the same license as the PyWebIO package.
#
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
# Pikhosh <pikhosh@gmail.com>, 2022.
msgid ""
msgstr ""
"Project-Id-Version: PyWebIO 1.5.2\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-02-26 16:35+0330\n"
"PO-Revision-Date: 2022-02-28 12:30+0330\n"
"Last-Translator: Pikhosh <pikhosh@gmail.com>\n"
"Language-Team: Persian <>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"
"Language: fa\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Lokalize 21.12.2\n"

#: ../../advanced.rst:2
msgid "Advanced topic"
msgstr "موضوع پیشرفته"

#: ../../advanced.rst:4
msgid "This section will introduce the advanced features of PyWebIO."
msgstr ""

#: ../../advanced.rst:10
msgid "Start multiple applications with start_server()"
msgstr ""

#: ../../advanced.rst:12
msgid ""
"`start_server() <pywebio.platform.tornado.start_server>` accepts a "
"function as PyWebIO application. In addition, `start_server() "
"<pywebio.platform.tornado.start_server>` also accepts a list of "
"application function or a dictionary of it to start multiple "
"applications. You can use `pywebio.session.go_app() "
"<pywebio.session.go_app>` or `put_link() <pywebio.output.put_link>` to "
"jump between application::"
msgstr ""

#: ../../advanced.rst:17
msgid ""
"def task_1():\n"
"    put_text('task_1')\n"
"    put_buttons(['Go task 2'], [lambda: go_app('task_2')])\n"
"\n"
"def task_2():\n"
"    put_text('task_2')\n"
"    put_buttons(['Go task 1'], [lambda: go_app('task_1')])\n"
"\n"
"def index():\n"
"    put_link('Go task 1', app='task_1')  # Use `app` parameter to specify"
" the task name\n"
"    put_link('Go task 2', app='task_2')\n"
"\n"
"# equal to `start_server({'index': index, 'task_1': task_1, 'task_2': "
"task_2})`\n"
"start_server([index, task_1, task_2])"
msgstr ""

#: ../../advanced.rst:32
msgid ""
"When the first parameter of `start_server() "
"<pywebio.platform.tornado.start_server>` is a dictionary, whose key is "
"application name and value is application function. When it is a list, "
"PyWebIO will use function name as application name."
msgstr ""

#: ../../advanced.rst:35
msgid ""
"You can select which application to access through the ``app`` URL "
"parameter (for example, visit ``http://host:port/?app=foo`` to access the"
" ``foo`` application), By default, the ``index`` application is opened "
"when no ``app`` URL parameter provided. When the ``index`` application "
"doesn't exist, PyWebIO will provide a default index application."
msgstr ""

#: ../../advanced.rst:44
msgid "Integration with web framework"
msgstr ""

#: ../../advanced.rst:46
msgid ""
"The PyWebIO application can be integrated into an existing Python Web "
"project, the PyWebIO application and the Web project share a web "
"framework. PyWebIO currently supports integration with Flask, Tornado, "
"Django, aiohttp and FastAPI(Starlette) web frameworks."
msgstr ""

#: ../../advanced.rst:50
msgid "The integration methods of those web frameworks are as follows:"
msgstr ""

#: ../../advanced.rst:54
msgid "Tornado"
msgstr ""

#: ../../advanced.rst:58
msgid "**Tornado**"
msgstr ""

#: ../../advanced.rst:60
msgid ""
"Use `pywebio.platform.tornado.webio_handler()` to get the "
"`WebSocketHandler "
"<https://www.tornadoweb.org/en/stable/websocket.html#tornado.websocket.WebSock"
"etHandler>`_"
" class for running PyWebIO applications in Tornado::"
msgstr ""

#: ../../advanced.rst:64
msgid ""
"import tornado.ioloop\n"
"import tornado.web\n"
"from pywebio.platform.tornado import webio_handler\n"
"\n"
"class MainHandler(tornado.web.RequestHandler):\n"
"    def get(self):\n"
"        self.write(\"Hello, world\")\n"
"\n"
"if __name__ == \"__main__\":\n"
"    application = tornado.web.Application([\n"
"        (r\"/\", MainHandler),\n"
"        (r\"/tool\", webio_handler(task_func)),  # `task_func` is PyWebIO"
" task function\n"
"    ])\n"
"    application.listen(port=80, address='localhost')\n"
"    tornado.ioloop.IOLoop.current().start()"
msgstr ""

#: ../../advanced.rst:81
msgid ""
"In above code, we add a routing rule to bind the ``WebSocketHandler`` of "
"the PyWebIO application to the ``/tool`` path. After starting the Tornado"
" server, you can visit ``http://localhost/tool`` to open the PyWebIO "
"application."
msgstr ""

#: ../../advanced.rst:86
msgid ""
"PyWebIO uses the WebSocket protocol to communicate with the browser in "
"Tornado. If your Tornado application is behind a reverse proxy (such as "
"Nginx), you may need to configure the reverse proxy to support the "
"WebSocket protocol. :ref:`Here <nginx_ws_config>` is an example of Nginx "
"WebSocket configuration."
msgstr ""

#: ../../advanced.rst:90
msgid "Flask"
msgstr ""

#: ../../advanced.rst:94
msgid "**Flask**"
msgstr ""

#: ../../advanced.rst:96
msgid ""
"Use `pywebio.platform.flask.webio_view()` to get the view function for "
"running PyWebIO applications in Flask::"
msgstr ""

#: ../../advanced.rst:98
msgid ""
"from pywebio.platform.flask import webio_view\n"
"from flask import Flask\n"
"\n"
"app = Flask(__name__)\n"
"\n"
"# `task_func` is PyWebIO task function\n"
"app.add_url_rule('/tool', 'webio_view', webio_view(task_func),\n"
"            methods=['GET', 'POST', 'OPTIONS'])  # need GET,POST and "
"OPTIONS methods\n"
"\n"
"app.run(host='localhost', port=80)"
msgstr ""

#: ../../advanced.rst:110
msgid ""
"In above code, we add a routing rule to bind the view function of the "
"PyWebIO application to the ``/tool`` path. After starting the Flask "
"application, visit ``http://localhost/tool`` to open the PyWebIO "
"application."
msgstr ""

#: ../../advanced.rst:113
msgid "Django"
msgstr ""

#: ../../advanced.rst:117
msgid "**Django**"
msgstr ""

#: ../../advanced.rst:119
msgid ""
"Use `pywebio.platform.django.webio_view()` to get the view function for "
"running PyWebIO applications in Django::"
msgstr ""

#: ../../advanced.rst:121
msgid ""
"# urls.py\n"
"\n"
"from django.urls import path\n"
"from pywebio.platform.django import webio_view\n"
"\n"
"# `task_func` is PyWebIO task function\n"
"webio_view_func = webio_view(task_func)\n"
"\n"
"urlpatterns = [\n"
"    path(r\"tool\", webio_view_func),\n"
"]"
msgstr ""

#: ../../advanced.rst:134
msgid ""
"In above code, we add a routing rule to bind the view function of the "
"PyWebIO application to the ``/tool`` path. After starting the Django "
"server, visit ``http://localhost/tool`` to open the PyWebIO application"
msgstr ""

#: ../../advanced.rst:137
msgid "aiohttp"
msgstr ""

#: ../../advanced.rst:141
msgid "**aiohttp**"
msgstr ""

#: ../../advanced.rst:143
msgid ""
"Use `pywebio.platform.aiohttp.webio_handler()` to get the `Request "
"Handler <https://docs.aiohttp.org/en/stable/web_quickstart.html#aiohttp-"
"web-handler>`_ coroutine for running PyWebIO applications in aiohttp::"
msgstr ""

#: ../../advanced.rst:147
msgid ""
"from aiohttp import web\n"
"from pywebio.platform.aiohttp import webio_handler\n"
"\n"
"app = web.Application()\n"
"# `task_func` is PyWebIO task function\n"
"app.add_routes([web.get('/tool', webio_handler(task_func))])\n"
"\n"
"web.run_app(app, host='localhost', port=80)"
msgstr ""

#: ../../advanced.rst:156
msgid ""
"After starting the aiohttp server, visit ``http://localhost/tool`` to "
"open the PyWebIO application"
msgstr ""

#: ../../advanced.rst:160
msgid ""
"PyWebIO uses the WebSocket protocol to communicate with the browser in "
"aiohttp. If your aiohttp server is behind a reverse proxy (such as "
"Nginx), you may need to configure the reverse proxy to support the "
"WebSocket protocol. :ref:`Here <nginx_ws_config>` is an example of Nginx "
"WebSocket configuration."
msgstr ""

#: ../../advanced.rst:165
msgid "FastAPI/Starlette"
msgstr ""

#: ../../advanced.rst:169
msgid "**FastAPI/Starlette**"
msgstr ""

#: ../../advanced.rst:171
msgid ""
"Use `pywebio.platform.fastapi.webio_routes()` to get the "
"FastAPI/Starlette routes for running PyWebIO applications. You can mount "
"the routes to your FastAPI/Starlette app."
msgstr ""

#: ../../advanced.rst:174
msgid "FastAPI::"
msgstr ""

#: ../../advanced.rst:176
msgid ""
"from fastapi import FastAPI\n"
"from pywebio.platform.fastapi import webio_routes\n"
"\n"
"app = FastAPI()\n"
"\n"
"@app.get(\"/app\")\n"
"def read_main():\n"
"   return {\"message\": \"Hello World from main app\"}\n"
"\n"
"# `task_func` is PyWebIO task function\n"
"app.mount(\"/tool\", FastAPI(routes=webio_routes(task_func)))"
msgstr ""

#: ../../advanced.rst:188
msgid "Starlette::"
msgstr ""

#: ../../advanced.rst:190
msgid ""
"from starlette.applications import Starlette\n"
"from starlette.responses import JSONResponse\n"
"from starlette.routing import Route, Mount\n"
"from pywebio.platform.fastapi import webio_routes\n"
"\n"
"async def homepage(request):\n"
"   return JSONResponse({'hello': 'world'})\n"
"\n"
"app = Starlette(routes=[\n"
"   Route('/', homepage),\n"
"   Mount('/tool', routes=webio_routes(task_func))  # `task_func` is "
"PyWebIO task function\n"
"])"
msgstr ""

#: ../../advanced.rst:203
msgid ""
"After starting the server by using ``uvicorn <module>:app`` , visit "
"``http://localhost:8000/tool/`` to open the PyWebIO application"
msgstr ""

#: ../../advanced.rst:205
msgid ""
"See also: `FastAPI doc <https://fastapi.tiangolo.com/advanced/sub-"
"applications/>`_ , `Starlette doc <https://www.starlette.io/routing"
"/#submounting-routes>`_"
msgstr ""

#: ../../advanced.rst:209
msgid ""
"PyWebIO uses the WebSocket protocol to communicate with the browser in "
"FastAPI/Starlette. If your server is behind a reverse proxy (such as "
"Nginx), you may need to configure the reverse proxy to support the "
"WebSocket protocol. :ref:`Here <nginx_ws_config>` is an example of Nginx "
"WebSocket configuration."
msgstr ""

#: ../../advanced.rst:217
msgid "Notes"
msgstr ""

#: ../../advanced.rst:218
msgid "**Deployment in production**"
msgstr ""

#: ../../advanced.rst:220
msgid ""
"In your production system, you may want to deploy the web applications "
"with some WSGI/ASGI servers such as uWSGI, Gunicorn, and Uvicorn. Since "
"PyWebIO applications store session state in memory of process, when you "
"use HTTP-based sessions (Flask and Django) and spawn multiple workers to "
"handle requests, the request may be dispatched to a process that does not"
" hold the session to which the request belongs. So you can only start one"
" worker to handle requests when using Flask or Django backend."
msgstr ""

#: ../../advanced.rst:225
msgid ""
"If you still want to use multiple processes to increase concurrency, one "
"way is to use Uvicorn+FastAPI, or you can also start multiple "
"Tornado/aiohttp processes and add external load balancer (such as HAProxy"
" or nginx) before them. Those backends use the WebSocket protocol to "
"communicate with the browser in PyWebIO, so there is no the issue as "
"described above."
msgstr ""

#: ../../advanced.rst:229
msgid "**Static resources Hosting**"
msgstr ""

#: ../../advanced.rst:231
msgid ""
"By default, the front-end of PyWebIO gets required static resources from "
"CDN. If you want to deploy PyWebIO applications in an offline "
"environment, you need to host static files by yourself, and set the "
"``cdn`` parameter of ``webio_view()`` or ``webio_handler()`` to "
"``False``."
msgstr ""

#: ../../advanced.rst:235
msgid ""
"When setting ``cdn=False`` , you need to host the static resources in the"
" same directory as the PyWebIO application. In addition, you can also "
"pass a string to ``cdn`` parameter to directly set the URL of PyWebIO "
"static resources directory."
msgstr ""

#: ../../advanced.rst:238
msgid ""
"The path of the static file of PyWebIO is stored in "
"``pywebio.STATIC_PATH``, you can use the command ``python3 -c \"import "
"pywebio; print(pywebio.STATIC_PATH)\"`` to print it out."
msgstr ""

#: ../../advanced.rst:243
msgid ""
"``start_server()`` and ``path_deploy()`` also support ``cdn`` parameter, "
"if it is set to ``False``, the static resource will be hosted in local "
"server automatically, without manual hosting."
msgstr ""

#: ../../advanced.rst:250
msgid "Coroutine-based session"
msgstr ""

#: ../../advanced.rst:251
msgid ""
"In most cases, you don’t need the coroutine-based session. All functions "
"or methods in PyWebIO that are only used for coroutine sessions are "
"specifically noted in the document."
msgstr ""

#: ../../advanced.rst:254
msgid ""
"PyWebIO's session is based on thread by default. Each time a user opens a"
" session connection to the server, PyWebIO will start a thread to run the"
" task function. In addition to thread-based sessions, PyWebIO also "
"provides coroutine-based sessions. Coroutine-based sessions accept "
"coroutine functions as task functions."
msgstr ""

#: ../../advanced.rst:258
msgid ""
"The session based on the coroutine is a single-thread model, which means "
"that all sessions run in a single thread. For IO-bound tasks, coroutines "
"take up fewer resources than threads and have performance comparable to "
"threads. In addition, the context switching of the coroutine is "
"predictable, which can reduce the need for program synchronization and "
"locking, and can effectively avoid most critical section problems."
msgstr ""

#: ../../advanced.rst:264
msgid "Using coroutine session"
msgstr ""

#: ../../advanced.rst:266
msgid ""
"To use coroutine-based session, you need to use the ``async`` keyword to "
"declare the task function as a coroutine function, and use the ``await`` "
"syntax to call the PyWebIO input function:"
msgstr ""

#: ../../advanced.rst:269
#, python-format
msgid ""
" from pywebio.input import *\n"
" from pywebio.output import *\n"
" from pywebio import start_server\n"
"\n"
" async def say_hello():\n"
"     name = await input(\"what's your name?\")\n"
"     put_text('Hello, %s' % name)\n"
"\n"
" start_server(say_hello, auto_open_webbrowser=True)"
msgstr ""

#: ../../advanced.rst:283
msgid ""
"In the coroutine task function, you can also use ``await`` to call other "
"coroutines or (`awaitable objects <https://docs.python.org/3/library"
"/asyncio-task.html#asyncio-awaitables>`_) in the standard library "
"`asyncio <https://docs.python.org/3/library/asyncio.html>`_:"
msgstr ""

#: ../../advanced.rst:287
msgid ""
" import asyncio\n"
" from pywebio import start_server\n"
"\n"
" async def hello_word():\n"
"     put_text('Hello ...')\n"
"     await asyncio.sleep(1)  # await awaitable objects in asyncio\n"
"     put_text('... World!')\n"
"\n"
" async def main():\n"
"     await hello_word()  # await coroutine\n"
"     put_text('Bye, bye')\n"
"\n"
" start_server(main, auto_open_webbrowser=True)"
msgstr ""

#: ../../advanced.rst:306
msgid ""
"In coroutine-based session, all input functions defined in the "
":doc:`pywebio.input </input>` module need to use ``await`` syntax to get "
"the return value. Forgetting to use ``await`` will be a common error when"
" using coroutine-based session."
msgstr ""

#: ../../advanced.rst:309
msgid ""
"Other functions that need to use ``await`` syntax in the coroutine "
"session are:"
msgstr ""

#: ../../advanced.rst:311
msgid ""
"`pywebio.session.run_asyncio_coroutine(coro_obj) "
"<pywebio.session.run_asyncio_coroutine>`"
msgstr ""

#: ../../advanced.rst:312
msgid "`pywebio.session.eval_js(expression) <pywebio.session.eval_js>`"
msgstr ""

#: ../../advanced.rst:316
msgid ""
"Although the PyWebIO coroutine session is compatible with the ``awaitable"
" objects`` in the standard library ``asyncio``, the ``asyncio`` library "
"is not compatible with the ``awaitable objects`` in the PyWebIO coroutine"
" session."
msgstr ""

#: ../../advanced.rst:319
msgid ""
"That is to say, you can't pass PyWebIO ``awaitable objects`` to the "
"``asyncio`` functions that accept ``awaitable objects``. For example, the"
" following calls are **not supported** ::"
msgstr ""

#: ../../advanced.rst:322
msgid ""
"await asyncio.shield(pywebio.input())\n"
"await asyncio.gather(asyncio.sleep(1), pywebio.session.eval_js('1+1'))\n"
"task = asyncio.create_task(pywebio.input())"
msgstr ""

#: ../../advanced.rst:329
msgid "Concurrency in coroutine-based sessions"
msgstr ""

#: ../../advanced.rst:331
msgid ""
"In coroutine-based session, you can start new thread, but you cannot call"
" PyWebIO interactive functions in it (`register_thread() "
"<pywebio.session.register_thread>` is not available in coroutine "
"session). But you can use `run_async(coro) <pywebio.session.run_async>` "
"to execute a coroutine object asynchronously, and PyWebIO interactive "
"functions can be used in the new coroutine:"
msgstr ""

#: ../../advanced.rst:336
msgid ""
" from pywebio import start_server\n"
" from pywebio.session import run_async\n"
"\n"
" async def counter(n):\n"
"     for i in range(n):\n"
"         put_text(i)\n"
"         await asyncio.sleep(1)\n"
"\n"
" async def main():\n"
"     run_async(counter(10))\n"
"     put_text('Main coroutine function exited.')\n"
"\n"
"\n"
" start_server(main, auto_open_webbrowser=True)"
msgstr ""

#: ../../advanced.rst:355
msgid ""
"`run_async(coro) <pywebio.session.run_async>` returns a `TaskHandler "
"<pywebio.session.coroutinebased.TaskHandler>`, which can be used to query"
" the running status of the coroutine or close the coroutine."
msgstr ""

#: ../../advanced.rst:359
msgid "Close of session"
msgstr ""

#: ../../advanced.rst:361
msgid ""
"Similar to thread-based session, when user close the browser page, the "
"session will be closed."
msgstr ""

#: ../../advanced.rst:363
msgid ""
"After the browser page closed, PyWebIO input function calls that have not"
" yet returned in the current session will cause `SessionClosedException "
"<pywebio.exceptions.SessionClosedException>`, and subsequent calls to "
"PyWebIO interactive functions will cause `SessionNotFoundException "
"<pywebio.exceptions.SessionNotFoundException>` or `SessionClosedException"
" <pywebio.exceptions.SessionClosedException>`."
msgstr ""

#: ../../advanced.rst:368
msgid ""
"`defer_call(func) <pywebio.session.defer_call>` also available in "
"coroutine session."
msgstr ""

#: ../../advanced.rst:373
msgid "Integration with Web Framework"
msgstr ""

#: ../../advanced.rst:375
msgid ""
"The PyWebIO application that using coroutine-based session can also be "
"integrated to the web framework."
msgstr ""

#: ../../advanced.rst:377
msgid ""
"However, there are some limitations when using coroutine-based sessions "
"to integrate into Flask or Django:"
msgstr ""

#: ../../advanced.rst:379
msgid ""
"First, when ``await`` the coroutine objects/awaitable objects in the "
"``asyncio`` module, you need to use `run_asyncio_coroutine() "
"<pywebio.session.run_asyncio_coroutine>` to wrap the coroutine object."
msgstr ""

#: ../../advanced.rst:382
msgid ""
"Secondly, you need to start a new thread to run the event loop before "
"starting a Flask/Django server."
msgstr ""

#: ../../advanced.rst:384
msgid "Example of coroutine-based session integration into Flask:"
msgstr ""

#: ../../advanced.rst:386
msgid ""
" import asyncio\n"
" import threading\n"
" from flask import Flask, send_from_directory\n"
" from pywebio import STATIC_PATH\n"
" from pywebio.output import *\n"
" from pywebio.platform.flask import webio_view\n"
" from pywebio.platform import run_event_loop\n"
" from pywebio.session import run_asyncio_coroutine\n"
"\n"
" async def hello_word():\n"
"     put_text('Hello ...')\n"
"     await run_asyncio_coroutine(asyncio.sleep(1))  # can't just \"await "
"asyncio.sleep(1)\"\n"
"     put_text('... World!')\n"
"\n"
" app = Flask(__name__)\n"
" app.add_url_rule('/hello', 'webio_view', webio_view(hello_word),\n"
"                             methods=['GET', 'POST', 'OPTIONS'])\n"
"\n"
" # thread to run event loop\n"
" threading.Thread(target=run_event_loop, daemon=True).start()\n"
" app.run(host='localhost', port=80)"
msgstr ""

#: ../../advanced.rst:411
msgid ""
"Finally, coroutine-based session is not available in the script mode. You"
" always need to use ``start_server()`` to run coroutine task function or "
"integrate it to a web framework."
msgstr ""

