remove test files

Commit d79f853 · patx · 2025-02-02T17:28:04-05:00

Changeset
d79f8532b6a4a7211f47297d2c13e9eb1fb6f2dd
Parents
c1108be1cf8169c20036b49e547e9b2611d83bef

View source at this commit

Comments

No comments yet.

Log in to comment

Diff

diff --git a/MicroPie.py b/MicroPie.py
index 3e5ddbb..7976e30 100644
--- a/MicroPie.py
+++ b/MicroPie.py
@@ -30,16 +30,23 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 """
+
 import asyncio
+import contextvars
 import inspect
 import mimetypes
 import os
 import re
 import time
-from typing import Optional, Dict, Any, Union, Tuple, List
-from urllib.parse import parse_qs
 import uuid
-import contextvars
+from typing import Any, Awaitable, BinaryIO, Callable, Dict, List, Optional, Tuple
+from urllib.parse import parse_qs
+
+try:
+    from jinja2 import Environment, FileSystemLoader
+    JINJA_INSTALLED = True
+except ImportError:
+    JINJA_INSTALLED = False
 
 try:
     from multipart import PushMultipartParser, MultipartSegment
@@ -47,117 +54,145 @@ try:
 except ImportError:
     MULTIPART_INSTALLED = False
 
-try:
-    from jinja2 import Environment, FileSystemLoader
-    JINJA_INSTALLED = True
-    import asyncio
-except ImportError:
-    JINJA_INSTALLED = False
+current_request: contextvars.ContextVar[Any] = contextvars.ContextVar("current_request")
 
-# Create a context variable to store the current request
-current_request = contextvars.ContextVar('current_request')
 
 class Request:
-    def __init__(self, scope):
-        self.scope = scope
-        self.method = scope["method"]
-        self.path_params = []
-        self.query_params = {}
-        self.body_params = {}
-        self.session = {}
-        self.files = {}
+    """Represents an HTTP request in the MicroPie framework."""
+
+    def __init__(self, scope: Dict[str, Any]) -> None:
+        """
+        Initialize a new Request instance.
+
+        Args:
+            scope: The ASGI scope dictionary for the request.
+        """
+        self.scope: Dict[str, Any] = scope
+        self.method: str = scope["method"]
+        self.path_params: List[str] = []
+        self.query_params: Dict[str, List[str]] = {}
+        self.body_params: Dict[str, List[str]] = {}
+        self.session: Dict[str, Any] = {}
+        self.files: Dict[str, Any] = {}
+
 
 class Server:
-    SESSION_TIMEOUT: int = 8 * 3600  # 8 hours
+    """ASGI server for handling HTTP requests and WebSocket connections in MicroPie."""
+    SESSION_TIMEOUT: int = 8 * 3600
 
     def __init__(self) -> None:
-        if JINJA_INSTALLED:
-            self.env = Environment(loader=FileSystemLoader("templates"))
+        """
+        Initialize a new Server instance.
 
+        If Jinja2 is installed, set up the template environment.
+        """
+        if JINJA_INSTALLED:
+            self.env: Optional[Environment] = Environment(loader=FileSystemLoader("templates"))
+        else:
+            self.env = None
         self.sessions: Dict[str, Any] = {}
 
     @property
     def request(self) -> Request:
+        """
+        Retrieve the current request from the context variable.
+
+        Returns:
+            The current Request instance.
+        """
         return current_request.get()
 
-    async def __call__(self, scope, receive, send):
+    async def __call__(
+        self,
+        scope: Dict[str, Any],
+        receive: Callable[[], Awaitable[Dict[str, Any]]],
+        send: Callable[[Dict[str, Any]], Awaitable[None]]
+    ) -> None:
+        """
+        ASGI callable interface for the server.
+
+        Args:
+            scope: The ASGI scope dictionary.
+            receive: The callable to receive ASGI events.
+            send: The callable to send ASGI events.
+        """
         await self._asgi_app(scope, receive, send)
 
-    async def _asgi_app(self, scope: Dict[str, Any], receive: Any, send: Any) -> None:
-        """ASGI application entrypoint for both HTTP and WebSockets."""
+    async def _asgi_app(
+        self,
+        scope: Dict[str, Any],
+        receive: Callable[[], Awaitable[Dict[str, Any]]],
+        send: Callable[[Dict[str, Any]], Awaitable[None]]
+    ) -> None:
+        """
+        ASGI application entry point for handling HTTP requests.
+
+        Args:
+            scope: The ASGI scope dictionary.
+            receive: The callable to receive ASGI events.
+            send: The callable to send ASGI events.
+        """
         if scope["type"] == "http":
-            request = Request(scope)
-            # Set the current request in the context variable
+            request: Request = Request(scope)
             token = current_request.set(request)
-
             try:
-                method = scope["method"]
-                path = scope["path"].lstrip("/")
-                path_parts = path.split("/") if path else []
-                func_name = path_parts[0] if path_parts else "index"
+                method: str = scope["method"]
+                path: str = scope["path"].lstrip("/")
+                path_parts: List[str] = path.split("/") if path else []
+                func_name: str = path_parts[0] if path_parts else "index"
 
-                # Ignore methods that start with an underscore
                 if func_name.startswith("_"):
                     await self._send_response(send, status_code=404, body="404 Not Found")
                     return
 
                 request.path_params = path_parts[1:] if len(path_parts) > 1 else []
-                handler_function = getattr(self, func_name, None)
+                handler_function: Optional[Callable[..., Any]] = getattr(self, func_name, None)
                 if not handler_function:
                     request.path_params = path_parts
                     handler_function = getattr(self, "index", None)
-
-                raw_query = scope.get("query_string", b"")
+                raw_query: bytes = scope.get("query_string", b"")
                 request.query_params = parse_qs(raw_query.decode("utf-8", "ignore"))
-
-                headers_dict = {
+                headers_dict: Dict[str, str] = {
                     k.decode("latin-1").lower(): v.decode("latin-1")
                     for k, v in scope.get("headers", [])
                 }
-                cookies = self._parse_cookies(headers_dict.get("cookie", ""))
-
-                session_id = cookies.get("session_id")
+                cookies: Dict[str, str] = self._parse_cookies(headers_dict.get("cookie", ""))
+                session_id: Optional[str] = cookies.get("session_id")
                 if session_id and session_id in self.sessions:
                     request.session = self.sessions[session_id]
                     request.session["last_access"] = time.time()
                 else:
                     request.session = {}
-
                 request.body_params = {}
                 request.files = {}
                 if method in ("POST", "PUT", "PATCH"):
-                    body_data = bytearray()
+                    body_data: bytearray = bytearray()
                     while True:
-                        msg = await receive()
+                        msg: Dict[str, Any] = await receive()
                         if msg["type"] == "http.request":
                             body_data += msg.get("body", b"")
                             if not msg.get("more_body"):
                                 break
-                    content_type = headers_dict.get("content-type", "")
+                    content_type: str = headers_dict.get("content-type", "")
                     if "multipart/form-data" in content_type:
-                        # Extract the boundary from the Content-Type header
-                        match = re.search(r'boundary=([^;]+)', content_type)
+                        match = re.search(r"boundary=([^;]+)", content_type)
                         if not match:
                             await self._send_response(
-                                send, status_code=400,
+                                send,
+                                status_code=400,
                                 body="400 Bad Request: Boundary not found in Content-Type header"
                             )
                             return
-                        boundary = match.group(1).encode("utf-8")  # Convert boundary to bytes
-
-                        # Create a StreamReader and feed it the body data
-                        reader = asyncio.StreamReader()
+                        boundary: bytes = match.group(1).encode("utf-8")
+                        reader: asyncio.StreamReader = asyncio.StreamReader()
                         reader.feed_data(body_data)
                         reader.feed_eof()
-
-                        # Now call _parse_multipart with the reader and the boundary
                         await self._parse_multipart(reader, boundary)
                     else:
-                        body_str = body_data.decode("utf-8", "ignore")
+                        body_str: str = body_data.decode("utf-8", "ignore")
                         request.body_params = parse_qs(body_str)
-
                 sig = inspect.signature(handler_function)
-                func_args = []
+                func_args: List[Any] = []
                 for param in sig.parameters.values():
                     if request.path_params:
                         func_args.append(request.path_params.pop(0))
@@ -175,30 +210,24 @@ class Server:
                         await self._send_response(
                             send,
                             status_code=400,
-                            body=f"400 Bad Request: Missing required parameter '{param.name}'",
+                            body=f"400 Bad Request: Missing required parameter '{param.name}'"
                         )
                         return
-
                 if handler_function == getattr(self, "index", None) and not func_args and path:
                     await self._send_response(send, status_code=404, body="404 Not Found")
                     return
-
                 try:
                     if inspect.iscoroutinefunction(handler_function):
-                        result = await handler_function(*func_args)
+                        result: Any = await handler_function(*func_args)
                     else:
                         result = handler_function(*func_args)
                 except Exception as e:
                     print(f"Error processing request: {e}")
-                    await self._send_response(
-                        send, status_code=500, body="500 Internal Server Error"
-                    )
+                    await self._send_response(send, status_code=500, body="500 Internal Server Error")
                     return
-
-                status_code = 200
-                response_body = result
+                status_code: int = 200
+                response_body: Any = result
                 extra_headers: List[Tuple[str, str]] = []
-
                 if isinstance(result, tuple):
                     if len(result) == 2:
                         status_code, response_body = result
@@ -206,16 +235,20 @@ class Server:
                         status_code, response_body, extra_headers = result
                     else:
                         await self._send_response(
-                            send, status_code=500,
+                            send,
+                            status_code=500,
                             body="500 Internal Server Error: Invalid response tuple"
                         )
                         return
-
                 if request.session:
                     session_id = cookies.get("session_id", str(uuid.uuid4()))
-                    self.sessions[session_id] = request.session  # Store session only if used
-                    extra_headers.append(("Set-Cookie", f"session_id={session_id}; Path=/; HttpOnly; SameSite=Strict"))
-
+                    self.sessions[session_id] = request.session
+                    extra_headers.append(
+                        (
+                            "Set-Cookie",
+                            f"session_id={session_id}; Path=/; HttpOnly; SameSite=Strict"
+                        )
+                    )
                 await self._send_response(
                     send,
                     status_code=status_code,
@@ -223,12 +256,20 @@ class Server:
                     extra_headers=extra_headers
                 )
             finally:
-                # Reset the context variable to avoid leaking request state
                 current_request.reset(token)
         else:
             pass
 
     def _parse_cookies(self, cookie_header: str) -> Dict[str, str]:
+        """
+        Parse the Cookie header and return a dictionary of cookie names and values.
+
+        Args:
+            cookie_header: The raw Cookie header string.
+
+        Returns:
+            A dictionary mapping cookie names to their corresponding values.
+        """
         cookies: Dict[str, str] = {}
         if not cookie_header:
             return cookies
@@ -238,73 +279,51 @@ class Server:
                 cookies[k] = v
         return cookies
 
-    async def _parse_multipart(self, reader: asyncio.StreamReader, boundary: bytes):
+    async def _parse_multipart(self, reader: asyncio.StreamReader, boundary: bytes) -> None:
         """
-        Multipart/form-data in a more streaming-friendly manner.
-        For large files, data is written to disk instead of stored in memory.
+        Parse multipart/form-data from the given reader using the specified boundary.
+
+        Args:
+            reader: An asyncio.StreamReader containing the multipart data.
+            boundary: The boundary bytes extracted from the Content-Type header.
         """
         if not MULTIPART_INSTALLED:
             raise ImportError("Multipart form data not supported. Install `multipart` via pip.")
-
         with PushMultipartParser(boundary) as parser:
-            current_field_name = None
-            current_filename = None
-            current_content_type = None
-            current_file = None  # File handle for streaming writes
-            form_value = ""
-
-            # Directory for storing uploaded files:
-            # Adjust if you want a different path or a dynamic approach inside your app.
-            upload_directory = "uploads"
-
-            # Ensure the directory exists
+            current_field_name: Optional[str] = None
+            current_filename: Optional[str] = None
+            current_content_type: Optional[str] = None
+            current_file: Optional[BinaryIO] = None
+            form_value: str = ""
+            upload_directory: str = "uploads"
             os.makedirs(upload_directory, exist_ok=True)
-
             while not parser.closed:
-                # Read data in chunks from the request stream
-                chunk = await reader.read(65536)  # 64KB per read
+                chunk: bytes = await reader.read(65536)
                 for result in parser.parse(chunk):
                     if isinstance(result, MultipartSegment):
-                        # We have a new part: form field or file
                         current_field_name = result.name
                         current_filename = result.filename
                         current_content_type = None
                         form_value = ""
-
-                        # Parse content-type if present
                         for header, value in result.headerlist:
                             if header.lower() == "content-type":
                                 current_content_type = value
-
-                        # If it's a file, open a file handle right away
                         if current_filename:
-                            safe_filename = f"{uuid.uuid4()}_{current_filename}"
-                            file_path = os.path.join(upload_directory, safe_filename)
+                            safe_filename: str = f"{uuid.uuid4()}_{current_filename}"
+                            file_path: str = os.path.join(upload_directory, safe_filename)
                             current_file = open(file_path, "wb")
-
-                        # Otherwise, treat it as a field (string value).
                         else:
                             if current_field_name not in self.request.body_params:
                                 self.request.body_params[current_field_name] = []
-
                     elif result:
-                        # This chunk is body data for the current part
                         if current_file:
-                            # If it's a file, write directly to disk
                             current_file.write(result)
                         else:
-                            # It's a form field chunk
                             form_value += result.decode("utf-8", "ignore")
                     else:
-                        # End of this part
                         if current_file:
-                            # Close out the file if we're done writing it
                             current_file.close()
                             current_file = None
-
-                            # Store reference in self.request.files so the upload handler can use it
-                            # Example structure includes just filename and content type;
-                            # no in-memory data, since we wrote it to disk.
                             if current_field_name:
                                 self.request.files[current_field_name] = {
                                     "filename": current_filename,
@@ -312,11 +331,8 @@ class Server:
                                     "saved_path": os.path.join(upload_directory, safe_filename),
                                 }
                         else:
-                            # If it was a form field, add the form value to body_params
                             if current_field_name:
                                 self.request.body_params[current_field_name].append(form_value)
-
-                        # Reset for the next part
                         current_field_name = None
                         current_filename = None
                         current_content_type = None
@@ -324,16 +340,23 @@ class Server:
 
     async def _send_response(
         self,
-        send,
+        send: Callable[[Dict[str, Any]], Awaitable[None]],
         status_code: int,
-        body,
-        extra_headers=None
-    ):
+        body: Any,
+        extra_headers: Optional[List[Tuple[str, str]]] = None
+    ) -> None:
+        """
+        Send an HTTP response using the ASGI send callable.
+
+        Args:
+            send: The ASGI send callable.
+            status_code: The HTTP status code for the response.
+            body: The response body, which may be a string, bytes, or generator.
+            extra_headers: Optional list of extra header tuples.
+        """
         if extra_headers is None:
             extra_headers = []
-
-        # Common HTTP status text
-        status_map = {
+        status_map: Dict[int, str] = {
             200: "200 OK",
             206: "206 Partial Content",
             302: "302 Found",
@@ -341,22 +364,16 @@ class Server:
             404: "404 Not Found",
             500: "500 Internal Server Error",
         }
-        status_text = status_map.get(status_code, f"{status_code} OK")
-
-        # Ensure extra headers are safe
-        sanitized_headers = []
+        status_text: str = status_map.get(status_code, f"{status_code} OK")
+        sanitized_headers: List[Tuple[str, str]] = []
         for k, v in extra_headers:
             if "\n" in k or "\r" in k or "\n" in v or "\r" in v:
                 print(f"Header injection attempt detected: {k}: {v}")
-                continue  # Skip invalid headers
+                continue
             sanitized_headers.append((k, v))
-
-        # Ensure Content-Type is set unless explicitly provided
-        has_content_type = any(h[0].lower() == "content-type" for h in sanitized_headers)
+        has_content_type: bool = any(h[0].lower() == "content-type" for h in sanitized_headers)
         if not has_content_type:
             sanitized_headers.append(("Content-Type", "text/html; charset=utf-8"))
-
-        # Send response start
         await send({
             "type": "http.response.start",
             "status": status_code,
@@ -364,8 +381,6 @@ class Server:
                 (k.encode("latin-1"), v.encode("latin-1")) for k, v in sanitized_headers
             ],
         })
-
-        # 1) Check if body is an async generator (has __aiter__)
         if hasattr(body, "__aiter__"):
             async for chunk in body:
                 if isinstance(chunk, str):
@@ -375,16 +390,8 @@ class Server:
                     "body": chunk,
                     "more_body": True
                 })
-            # Send a final empty chunk to mark the end
-            await send({
-                "type": "http.response.body",
-                "body": b"",
-                "more_body": False
-            })
+            await send({"type": "http.response.body", "body": b"", "more_body": False})
             return
-
-        # 2) Check if body is a *sync* generator (has __iter__) and
-        #    is not a plain string/bytes
         if hasattr(body, "__iter__") and not isinstance(body, (bytes, str)):
             for chunk in body:
                 if isinstance(chunk, str):
@@ -394,23 +401,14 @@ class Server:
                     "body": chunk,
                     "more_body": True
                 })
-            # Send a final empty chunk
-            await send({
-                "type": "http.response.body",
-                "body": b"",
-                "more_body": False
-            })
+            await send({"type": "http.response.body", "body": b"", "more_body": False})
             return
-
         if isinstance(body, str):
-            response_body = body.encode("utf-8")
+            response_body: bytes = body.encode("utf-8")
         elif isinstance(body, bytes):
             response_body = body
         else:
-            # Convert anything else to string then to bytes
             response_body = str(body).encode("utf-8")
-
-        # Ensure body is properly encoded
         response_body = body.encode("utf-8") if isinstance(body, str) else body
         await send({
             "type": "http.response.body",
@@ -419,7 +417,10 @@ class Server:
         })
 
     def _cleanup_sessions(self) -> None:
-        now = time.time()
+        """
+        Clean up expired sessions based on the SESSION_TIMEOUT value.
+        """
+        now: float = time.time()
         self.sessions = {
             sid: data
             for sid, data in self.sessions.items()
@@ -427,6 +428,15 @@ class Server:
         }
 
     def _redirect(self, location: str) -> Tuple[int, str]:
+        """
+        Generate an HTTP redirect response.
+
+        Args:
+            location: The URL to redirect to.
+
+        Returns:
+            A tuple containing the HTTP status code and the HTML body.
+        """
         return (
             302,
             (
@@ -438,12 +448,21 @@ class Server:
 
     async def _render_template(self, name: str, **kwargs: Any) -> str:
         """
-        Async-compatible template rendering using Jinja2.
+        Render a template asynchronously using Jinja2.
+
+        Args:
+            name: The name of the template file.
+            **kwargs: Additional keyword arguments for the template.
+
+        Returns:
+            The rendered template as a string.
         """
         if not JINJA_INSTALLED:
             raise ImportError("`_render_template` not available. Install `jinja2` via pip.")
 
-        def render_sync():
+        def render_sync() -> str:
+            assert self.env is not None
             return self.env.get_template(name).render(kwargs)
 
         return await asyncio.get_event_loop().run_in_executor(None, render_sync)
+
diff --git a/README.md b/README.md
index fe4d13c..5ac4080 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
 
 ## **Introduction**
 
-**MicroPie** is a fast, lightweight, modern Python web framework that supports asynchronous web applications. Designed with **flexibility** and **simplicity** in mind, MicroPie enables you to handle high-concurrency applications with ease while allowing natural integration with external tools like Socket.IO for real-time communication.
+**MicroPie** is a fast, lightweight, modern Python web framework that supports asynchronous web applications. Designed with **flexibility** and **simplicity** in mind, MicroPie enables you to handle high-concurrency applications with ease while allowing natural integration with external tools like Socket.IO for real-time communication. See how to get started below and check out the [API reference](https://patx.github.io/micropie/api).
 
 ### **Key Features**
 - 🔄 **Routing:** Automatic mapping of URLs to functions with support for dynamic and query parameters.
@@ -165,7 +165,7 @@ The best way to get an idea of how MicroPie works is to see it in action! Check
 - Form handling and POST requests
 - And more
 
-*Please note these are examples, showing the MicroPie API, they are not meant for producton!*
+*Please note these are examples, showing the MicroPie API, they are not meant for producton! You can see the full API documentation [here](https://patx.github.io/micropie/api).*
 ## **Why ASGI?**
 ASGI is the future of Python web development, offering:
 - **Concurrency**: Handle thousands of simultaneous connections efficiently.
diff --git a/docs/api.html b/docs/api.html
new file mode 100644
index 0000000..7e6af70
--- /dev/null
+++ b/docs/api.html
@@ -0,0 +1,161 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module MicroPie</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong>MicroPie</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/home/harrisonerd/Dropbox/Projects/micropie/MicroPie.py">/home/harrisonerd/Dropbox/Projects/micropie/MicroPie.py</a></font></td></tr></table>
+    <p><tt>MicroPie:&nbsp;A&nbsp;simple&nbsp;Python&nbsp;ultra-micro&nbsp;web&nbsp;framework&nbsp;with&nbsp;ASGI<br>
+support.&nbsp;<a href="https://patx.github.io/micropie">https://patx.github.io/micropie</a><br>
+&nbsp;<br>
+Copyright&nbsp;Harrison&nbsp;Erd<br>
+&nbsp;<br>
+Redistribution&nbsp;and&nbsp;use&nbsp;in&nbsp;source&nbsp;and&nbsp;binary&nbsp;forms,&nbsp;with&nbsp;or&nbsp;without<br>
+modification,&nbsp;are&nbsp;permitted&nbsp;provided&nbsp;that&nbsp;the&nbsp;following&nbsp;conditions&nbsp;are&nbsp;met:<br>
+&nbsp;<br>
+1.&nbsp;Redistributions&nbsp;of&nbsp;source&nbsp;code&nbsp;must&nbsp;retain&nbsp;the&nbsp;above&nbsp;copyright&nbsp;notice,<br>
+&nbsp;&nbsp;&nbsp;this&nbsp;list&nbsp;of&nbsp;conditions&nbsp;and&nbsp;the&nbsp;following&nbsp;disclaimer.<br>
+&nbsp;<br>
+2.&nbsp;Redistributions&nbsp;in&nbsp;binary&nbsp;form&nbsp;must&nbsp;reproduce&nbsp;the&nbsp;above&nbsp;copyright&nbsp;notice,<br>
+&nbsp;&nbsp;&nbsp;this&nbsp;list&nbsp;of&nbsp;conditions&nbsp;and&nbsp;the&nbsp;following&nbsp;disclaimer&nbsp;in&nbsp;the&nbsp;documentation<br>
+&nbsp;&nbsp;&nbsp;and/or&nbsp;other&nbsp;materials&nbsp;provided&nbsp;with&nbsp;the&nbsp;distribution.<br>
+&nbsp;<br>
+3.&nbsp;Neither&nbsp;the&nbsp;name&nbsp;of&nbsp;the&nbsp;copyright&nbsp;holder&nbsp;nor&nbsp;the&nbsp;names&nbsp;of&nbsp;its<br>
+&nbsp;&nbsp;&nbsp;contributors&nbsp;may&nbsp;be&nbsp;used&nbsp;to&nbsp;endorse&nbsp;or&nbsp;promote&nbsp;products&nbsp;derived&nbsp;from&nbsp;this<br>
+&nbsp;&nbsp;&nbsp;software&nbsp;without&nbsp;specific&nbsp;prior&nbsp;written&nbsp;permission.<br>
+&nbsp;<br>
+THIS&nbsp;SOFTWARE&nbsp;IS&nbsp;PROVIDED&nbsp;BY&nbsp;THE&nbsp;COPYRIGHT&nbsp;HOLDERS&nbsp;AND&nbsp;CONTRIBUTORS&nbsp;"AS<br>
+IS"&nbsp;AND&nbsp;ANY&nbsp;EXPRESS&nbsp;OR&nbsp;IMPLIED&nbsp;WARRANTIES,&nbsp;INCLUDING,&nbsp;BUT&nbsp;NOT&nbsp;LIMITED&nbsp;TO,<br>
+THE&nbsp;IMPLIED&nbsp;WARRANTIES&nbsp;OF&nbsp;MERCHANTABILITY&nbsp;AND&nbsp;FITNESS&nbsp;FOR&nbsp;A&nbsp;PARTICULAR<br>
+PURPOSE&nbsp;ARE&nbsp;DISCLAIMED.&nbsp;IN&nbsp;NO&nbsp;EVENT&nbsp;SHALL&nbsp;THE&nbsp;COPYRIGHT&nbsp;HOLDER&nbsp;OR<br>
+CONTRIBUTORS&nbsp;BE&nbsp;LIABLE&nbsp;FOR&nbsp;ANY&nbsp;DIRECT,&nbsp;INDIRECT,&nbsp;INCIDENTAL,&nbsp;SPECIAL,<br>
+EXEMPLARY,&nbsp;OR&nbsp;CONSEQUENTIAL&nbsp;DAMAGES&nbsp;(INCLUDING,&nbsp;BUT&nbsp;NOT&nbsp;LIMITED&nbsp;TO,<br>
+PROCUREMENT&nbsp;OF&nbsp;SUBSTITUTE&nbsp;GOODS&nbsp;OR&nbsp;SERVICES;&nbsp;LOSS&nbsp;OF&nbsp;USE,&nbsp;DATA,&nbsp;OR&nbsp;PROFITS;<br>
+OR&nbsp;BUSINESS&nbsp;INTERRUPTION)&nbsp;HOWEVER&nbsp;CAUSED&nbsp;AND&nbsp;ON&nbsp;ANY&nbsp;THEORY&nbsp;OF&nbsp;LIABILITY,<br>
+WHETHER&nbsp;IN&nbsp;CONTRACT,&nbsp;STRICT&nbsp;LIABILITY,&nbsp;OR&nbsp;TORT&nbsp;(INCLUDING&nbsp;NEGLIGENCE&nbsp;OR<br>
+OTHERWISE)&nbsp;ARISING&nbsp;IN&nbsp;ANY&nbsp;WAY&nbsp;OUT&nbsp;OF&nbsp;THE&nbsp;USE&nbsp;OF&nbsp;THIS&nbsp;SOFTWARE,<br>
+EVEN&nbsp;IF&nbsp;ADVISED&nbsp;OF&nbsp;THE&nbsp;POSSIBILITY&nbsp;OF&nbsp;SUCH&nbsp;DAMAGE.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+    
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="asyncio.html">asyncio</a><br>
+<a href="contextvars.html">contextvars</a><br>
+</td><td width="25%" valign=top><a href="inspect.html">inspect</a><br>
+<a href="mimetypes.html">mimetypes</a><br>
+</td><td width="25%" valign=top><a href="os.html">os</a><br>
+<a href="re.html">re</a><br>
+</td><td width="25%" valign=top><a href="time.html">time</a><br>
+<a href="uuid.html">uuid</a><br>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+    
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="builtins.html#object">builtins.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="MicroPie.html#Request">Request</a>
+</font></dt><dt><font face="helvetica, arial"><a href="MicroPie.html#Server">Server</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="Request">class <strong>Request</strong></a>(<a href="builtins.html#object">builtins.object</a>)</font></td></tr>
+    
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt><a href="#Request">Request</a>(scope:&nbsp;Dict[str,&nbsp;Any])&nbsp;-&amp;gt;&nbsp;None<br>
+&nbsp;<br>
+Represents&nbsp;an&nbsp;HTTP&nbsp;request&nbsp;in&nbsp;the&nbsp;MicroPie&nbsp;framework.<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="Request-__init__"><strong>__init__</strong></a>(self, scope: Dict[str, Any]) -&gt; None</dt><dd><tt>Initialize&nbsp;a&nbsp;new&nbsp;<a href="#Request">Request</a>&nbsp;instance.<br>
+&nbsp;<br>
+Args:<br>
+&nbsp;&nbsp;&nbsp;&nbsp;scope:&nbsp;The&nbsp;ASGI&nbsp;scope&nbsp;dictionary&nbsp;for&nbsp;the&nbsp;request.</tt></dd></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="Server">class <strong>Server</strong></a>(<a href="builtins.html#object">builtins.object</a>)</font></td></tr>
+    
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt><a href="#Server">Server</a>()&nbsp;-&amp;gt;&nbsp;None<br>
+&nbsp;<br>
+ASGI&nbsp;server&nbsp;for&nbsp;handling&nbsp;HTTP&nbsp;requests&nbsp;and&nbsp;WebSocket&nbsp;connections&nbsp;in&nbsp;MicroPie.<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt>async <a name="Server-__call__"><strong>__call__</strong></a>(self, scope: Dict[str, Any], receive: Callable[[], Awaitable[Dict[str, Any]]], send: Callable[[Dict[str, Any]], Awaitable[NoneType]]) -&gt; None</dt><dd><tt>ASGI&nbsp;callable&nbsp;interface&nbsp;for&nbsp;the&nbsp;server.<br>
+&nbsp;<br>
+Args:<br>
+&nbsp;&nbsp;&nbsp;&nbsp;scope:&nbsp;The&nbsp;ASGI&nbsp;scope&nbsp;dictionary.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;receive:&nbsp;The&nbsp;callable&nbsp;to&nbsp;receive&nbsp;ASGI&nbsp;events.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;send:&nbsp;The&nbsp;callable&nbsp;to&nbsp;send&nbsp;ASGI&nbsp;events.</tt></dd></dl>
+
+<dl><dt><a name="Server-__init__"><strong>__init__</strong></a>(self) -&gt; None</dt><dd><tt>Initialize&nbsp;a&nbsp;new&nbsp;<a href="#Server">Server</a>&nbsp;instance.<br>
+&nbsp;<br>
+If&nbsp;Jinja2&nbsp;is&nbsp;installed,&nbsp;set&nbsp;up&nbsp;the&nbsp;template&nbsp;environment.</tt></dd></dl>
+
+<hr>
+Readonly properties defined here:<br>
+<dl><dt><strong>request</strong></dt>
+<dd><tt>Retrieve&nbsp;the&nbsp;current&nbsp;request&nbsp;from&nbsp;the&nbsp;context&nbsp;variable.<br>
+&nbsp;<br>
+Returns:<br>
+&nbsp;&nbsp;&nbsp;&nbsp;The&nbsp;current&nbsp;Request&nbsp;instance.</tt></dd>
+</dl>
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<hr>
+Data and other attributes defined here:<br>
+<dl><dt><strong>SESSION_TIMEOUT</strong> = 28800</dl>
+
+<dl><dt><strong>__annotations__</strong> = {'SESSION_TIMEOUT': &lt;class 'int'&gt;}</dl>
+
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#55aa55">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Data</strong></big></font></td></tr>
+    
+<tr><td bgcolor="#55aa55"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><strong>Any</strong> = typing.Any<br>
+<strong>Awaitable</strong> = typing.Awaitable<br>
+<strong>Callable</strong> = typing.Callable<br>
+<strong>Dict</strong> = typing.Dict<br>
+<strong>JINJA_INSTALLED</strong> = True<br>
+<strong>List</strong> = typing.List<br>
+<strong>MULTIPART_INSTALLED</strong> = False<br>
+<strong>Optional</strong> = typing.Optional<br>
+<strong>Tuple</strong> = typing.Tuple<br>
+<strong>__annotations__</strong> = {'current_request': _contextvars.ContextVar[typing.Any]}<br>
+<strong>current_request</strong> = &lt;ContextVar name='current_request'&gt;</td></tr></table>
+</body></html>
\ No newline at end of file
diff --git a/docs/api/index.html b/docs/api/index.html
new file mode 100644
index 0000000..7e024c7
--- /dev/null
+++ b/docs/api/index.html
@@ -0,0 +1,7 @@
+<!doctype html>
+<html>
+<head>
+    <meta charset="utf-8">
+    <meta http-equiv="refresh" content="0; url=./MicroPie.html"/>
+</head>
+</html>
diff --git a/docs/api/search.js b/docs/api/search.js
new file mode 100644
index 0000000..1b70927
--- /dev/null
+++ b/docs/api/search.js
@@ -0,0 +1,46 @@
+window.pdocSearch = (function(){
+/** elasticlunr - http://weixsong.github.io * Copyright (C) 2017 Oliver Nightingale * Copyright (C) 2017 Wei Song * MIT Licensed */!function(){function e(e){if(null===e||"object"!=typeof e)return e;var t=e.constructor();for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);return t}var t=function(e){var n=new t.Index;return n.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),e&&e.call(n,n),n};t.version="0.9.5",lunr=t,t.utils={},t.utils.warn=function(e){return function(t){e.console&&console.warn&&console.warn(t)}}(this),t.utils.toString=function(e){return void 0===e||null===e?"":e.toString()},t.EventEmitter=function(){this.events={}},t.EventEmitter.prototype.addListener=function(){var e=Array.prototype.slice.call(arguments),t=e.pop(),n=e;if("function"!=typeof t)throw new TypeError("last argument must be a function");n.forEach(function(e){this.hasHandler(e)||(this.events[e]=[]),this.events[e].push(t)},this)},t.EventEmitter.prototype.removeListener=function(e,t){if(this.hasHandler(e)){var n=this.events[e].indexOf(t);-1!==n&&(this.events[e].splice(n,1),0==this.events[e].length&&delete this.events[e])}},t.EventEmitter.prototype.emit=function(e){if(this.hasHandler(e)){var t=Array.prototype.slice.call(arguments,1);this.events[e].forEach(function(e){e.apply(void 0,t)},this)}},t.EventEmitter.prototype.hasHandler=function(e){return e in this.events},t.tokenizer=function(e){if(!arguments.length||null===e||void 0===e)return[];if(Array.isArray(e)){var n=e.filter(function(e){return null===e||void 0===e?!1:!0});n=n.map(function(e){return t.utils.toString(e).toLowerCase()});var i=[];return n.forEach(function(e){var n=e.split(t.tokenizer.seperator);i=i.concat(n)},this),i}return e.toString().trim().toLowerCase().split(t.tokenizer.seperator)},t.tokenizer.defaultSeperator=/[\s\-]+/,t.tokenizer.seperator=t.tokenizer.defaultSeperator,t.tokenizer.setSeperator=function(e){null!==e&&void 0!==e&&"object"==typeof e&&(t.tokenizer.seperator=e)},t.tokenizer.resetSeperator=function(){t.tokenizer.seperator=t.tokenizer.defaultSeperator},t.tokenizer.getSeperator=function(){return t.tokenizer.seperator},t.Pipeline=function(){this._queue=[]},t.Pipeline.registeredFunctions={},t.Pipeline.registerFunction=function(e,n){n in t.Pipeline.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+n),e.label=n,t.Pipeline.registeredFunctions[n]=e},t.Pipeline.getRegisteredFunction=function(e){return e in t.Pipeline.registeredFunctions!=!0?null:t.Pipeline.registeredFunctions[e]},t.Pipeline.warnIfFunctionNotRegistered=function(e){var n=e.label&&e.label in this.registeredFunctions;n||t.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",e)},t.Pipeline.load=function(e){var n=new t.Pipeline;return e.forEach(function(e){var i=t.Pipeline.getRegisteredFunction(e);if(!i)throw new Error("Cannot load un-registered function: "+e);n.add(i)}),n},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(e){t.Pipeline.warnIfFunctionNotRegistered(e),this._queue.push(e)},this)},t.Pipeline.prototype.after=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._queue.indexOf(e);if(-1===i)throw new Error("Cannot find existingFn");this._queue.splice(i+1,0,n)},t.Pipeline.prototype.before=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._queue.indexOf(e);if(-1===i)throw new Error("Cannot find existingFn");this._queue.splice(i,0,n)},t.Pipeline.prototype.remove=function(e){var t=this._queue.indexOf(e);-1!==t&&this._queue.splice(t,1)},t.Pipeline.prototype.run=function(e){for(var t=[],n=e.length,i=this._queue.length,o=0;n>o;o++){for(var r=e[o],s=0;i>s&&(r=this._queue[s](r,o,e),void 0!==r&&null!==r);s++);void 0!==r&&null!==r&&t.push(r)}return t},t.Pipeline.prototype.reset=function(){this._queue=[]},t.Pipeline.prototype.get=function(){return this._queue},t.Pipeline.prototype.toJSON=function(){return this._queue.map(function(e){return t.Pipeline.warnIfFunctionNotRegistered(e),e.label})},t.Index=function(){this._fields=[],this._ref="id",this.pipeline=new t.Pipeline,this.documentStore=new t.DocumentStore,this.index={},this.eventEmitter=new t.EventEmitter,this._idfCache={},this.on("add","remove","update",function(){this._idfCache={}}.bind(this))},t.Index.prototype.on=function(){var e=Array.prototype.slice.call(arguments);return this.eventEmitter.addListener.apply(this.eventEmitter,e)},t.Index.prototype.off=function(e,t){return this.eventEmitter.removeListener(e,t)},t.Index.load=function(e){e.version!==t.version&&t.utils.warn("version mismatch: current "+t.version+" importing "+e.version);var n=new this;n._fields=e.fields,n._ref=e.ref,n.documentStore=t.DocumentStore.load(e.documentStore),n.pipeline=t.Pipeline.load(e.pipeline),n.index={};for(var i in e.index)n.index[i]=t.InvertedIndex.load(e.index[i]);return n},t.Index.prototype.addField=function(e){return this._fields.push(e),this.index[e]=new t.InvertedIndex,this},t.Index.prototype.setRef=function(e){return this._ref=e,this},t.Index.prototype.saveDocument=function(e){return this.documentStore=new t.DocumentStore(e),this},t.Index.prototype.addDoc=function(e,n){if(e){var n=void 0===n?!0:n,i=e[this._ref];this.documentStore.addDoc(i,e),this._fields.forEach(function(n){var o=this.pipeline.run(t.tokenizer(e[n]));this.documentStore.addFieldLength(i,n,o.length);var r={};o.forEach(function(e){e in r?r[e]+=1:r[e]=1},this);for(var s in r){var u=r[s];u=Math.sqrt(u),this.index[n].addToken(s,{ref:i,tf:u})}},this),n&&this.eventEmitter.emit("add",e,this)}},t.Index.prototype.removeDocByRef=function(e){if(e&&this.documentStore.isDocStored()!==!1&&this.documentStore.hasDoc(e)){var t=this.documentStore.getDoc(e);this.removeDoc(t,!1)}},t.Index.prototype.removeDoc=function(e,n){if(e){var n=void 0===n?!0:n,i=e[this._ref];this.documentStore.hasDoc(i)&&(this.documentStore.removeDoc(i),this._fields.forEach(function(n){var o=this.pipeline.run(t.tokenizer(e[n]));o.forEach(function(e){this.index[n].removeToken(e,i)},this)},this),n&&this.eventEmitter.emit("remove",e,this))}},t.Index.prototype.updateDoc=function(e,t){var t=void 0===t?!0:t;this.removeDocByRef(e[this._ref],!1),this.addDoc(e,!1),t&&this.eventEmitter.emit("update",e,this)},t.Index.prototype.idf=function(e,t){var n="@"+t+"/"+e;if(Object.prototype.hasOwnProperty.call(this._idfCache,n))return this._idfCache[n];var i=this.index[t].getDocFreq(e),o=1+Math.log(this.documentStore.length/(i+1));return this._idfCache[n]=o,o},t.Index.prototype.getFields=function(){return this._fields.slice()},t.Index.prototype.search=function(e,n){if(!e)return[];e="string"==typeof e?{any:e}:JSON.parse(JSON.stringify(e));var i=null;null!=n&&(i=JSON.stringify(n));for(var o=new t.Configuration(i,this.getFields()).get(),r={},s=Object.keys(e),u=0;u<s.length;u++){var a=s[u];r[a]=this.pipeline.run(t.tokenizer(e[a]))}var l={};for(var c in o){var d=r[c]||r.any;if(d){var f=this.fieldSearch(d,c,o),h=o[c].boost;for(var p in f)f[p]=f[p]*h;for(var p in f)p in l?l[p]+=f[p]:l[p]=f[p]}}var v,g=[];for(var p in l)v={ref:p,score:l[p]},this.documentStore.hasDoc(p)&&(v.doc=this.documentStore.getDoc(p)),g.push(v);return g.sort(function(e,t){return t.score-e.score}),g},t.Index.prototype.fieldSearch=function(e,t,n){var i=n[t].bool,o=n[t].expand,r=n[t].boost,s=null,u={};return 0!==r?(e.forEach(function(e){var n=[e];1==o&&(n=this.index[t].expandToken(e));var r={};n.forEach(function(n){var o=this.index[t].getDocs(n),a=this.idf(n,t);if(s&&"AND"==i){var l={};for(var c in s)c in o&&(l[c]=o[c]);o=l}n==e&&this.fieldSearchStats(u,n,o);for(var c in o){var d=this.index[t].getTermFrequency(n,c),f=this.documentStore.getFieldLength(c,t),h=1;0!=f&&(h=1/Math.sqrt(f));var p=1;n!=e&&(p=.15*(1-(n.length-e.length)/n.length));var v=d*a*h*p;c in r?r[c]+=v:r[c]=v}},this),s=this.mergeScores(s,r,i)},this),s=this.coordNorm(s,u,e.length)):void 0},t.Index.prototype.mergeScores=function(e,t,n){if(!e)return t;if("AND"==n){var i={};for(var o in t)o in e&&(i[o]=e[o]+t[o]);return i}for(var o in t)o in e?e[o]+=t[o]:e[o]=t[o];return e},t.Index.prototype.fieldSearchStats=function(e,t,n){for(var i in n)i in e?e[i].push(t):e[i]=[t]},t.Index.prototype.coordNorm=function(e,t,n){for(var i in e)if(i in t){var o=t[i].length;e[i]=e[i]*o/n}return e},t.Index.prototype.toJSON=function(){var e={};return this._fields.forEach(function(t){e[t]=this.index[t].toJSON()},this),{version:t.version,fields:this._fields,ref:this._ref,documentStore:this.documentStore.toJSON(),index:e,pipeline:this.pipeline.toJSON()}},t.Index.prototype.use=function(e){var t=Array.prototype.slice.call(arguments,1);t.unshift(this),e.apply(this,t)},t.DocumentStore=function(e){this._save=null===e||void 0===e?!0:e,this.docs={},this.docInfo={},this.length=0},t.DocumentStore.load=function(e){var t=new this;return t.length=e.length,t.docs=e.docs,t.docInfo=e.docInfo,t._save=e.save,t},t.DocumentStore.prototype.isDocStored=function(){return this._save},t.DocumentStore.prototype.addDoc=function(t,n){this.hasDoc(t)||this.length++,this.docs[t]=this._save===!0?e(n):null},t.DocumentStore.prototype.getDoc=function(e){return this.hasDoc(e)===!1?null:this.docs[e]},t.DocumentStore.prototype.hasDoc=function(e){return e in this.docs},t.DocumentStore.prototype.removeDoc=function(e){this.hasDoc(e)&&(delete this.docs[e],delete this.docInfo[e],this.length--)},t.DocumentStore.prototype.addFieldLength=function(e,t,n){null!==e&&void 0!==e&&0!=this.hasDoc(e)&&(this.docInfo[e]||(this.docInfo[e]={}),this.docInfo[e][t]=n)},t.DocumentStore.prototype.updateFieldLength=function(e,t,n){null!==e&&void 0!==e&&0!=this.hasDoc(e)&&this.addFieldLength(e,t,n)},t.DocumentStore.prototype.getFieldLength=function(e,t){return null===e||void 0===e?0:e in this.docs&&t in this.docInfo[e]?this.docInfo[e][t]:0},t.DocumentStore.prototype.toJSON=function(){return{docs:this.docs,docInfo:this.docInfo,length:this.length,save:this._save}},t.stemmer=function(){var e={ational:"ate",tional:"tion",enci:"ence",anci:"ance",izer:"ize",bli:"ble",alli:"al",entli:"ent",eli:"e",ousli:"ous",ization:"ize",ation:"ate",ator:"ate",alism:"al",iveness:"ive",fulness:"ful",ousness:"ous",aliti:"al",iviti:"ive",biliti:"ble",logi:"log"},t={icate:"ic",ative:"",alize:"al",iciti:"ic",ical:"ic",ful:"",ness:""},n="[^aeiou]",i="[aeiouy]",o=n+"[^aeiouy]*",r=i+"[aeiou]*",s="^("+o+")?"+r+o,u="^("+o+")?"+r+o+"("+r+")?$",a="^("+o+")?"+r+o+r+o,l="^("+o+")?"+i,c=new RegExp(s),d=new RegExp(a),f=new RegExp(u),h=new RegExp(l),p=/^(.+?)(ss|i)es$/,v=/^(.+?)([^s])s$/,g=/^(.+?)eed$/,m=/^(.+?)(ed|ing)$/,y=/.$/,S=/(at|bl|iz)$/,x=new RegExp("([^aeiouylsz])\\1$"),w=new RegExp("^"+o+i+"[^aeiouwxy]$"),I=/^(.+?[^aeiou])y$/,b=/^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/,E=/^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/,D=/^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/,F=/^(.+?)(s|t)(ion)$/,_=/^(.+?)e$/,P=/ll$/,k=new RegExp("^"+o+i+"[^aeiouwxy]$"),z=function(n){var i,o,r,s,u,a,l;if(n.length<3)return n;if(r=n.substr(0,1),"y"==r&&(n=r.toUpperCase()+n.substr(1)),s=p,u=v,s.test(n)?n=n.replace(s,"$1$2"):u.test(n)&&(n=n.replace(u,"$1$2")),s=g,u=m,s.test(n)){var z=s.exec(n);s=c,s.test(z[1])&&(s=y,n=n.replace(s,""))}else if(u.test(n)){var z=u.exec(n);i=z[1],u=h,u.test(i)&&(n=i,u=S,a=x,l=w,u.test(n)?n+="e":a.test(n)?(s=y,n=n.replace(s,"")):l.test(n)&&(n+="e"))}if(s=I,s.test(n)){var z=s.exec(n);i=z[1],n=i+"i"}if(s=b,s.test(n)){var z=s.exec(n);i=z[1],o=z[2],s=c,s.test(i)&&(n=i+e[o])}if(s=E,s.test(n)){var z=s.exec(n);i=z[1],o=z[2],s=c,s.test(i)&&(n=i+t[o])}if(s=D,u=F,s.test(n)){var z=s.exec(n);i=z[1],s=d,s.test(i)&&(n=i)}else if(u.test(n)){var z=u.exec(n);i=z[1]+z[2],u=d,u.test(i)&&(n=i)}if(s=_,s.test(n)){var z=s.exec(n);i=z[1],s=d,u=f,a=k,(s.test(i)||u.test(i)&&!a.test(i))&&(n=i)}return s=P,u=d,s.test(n)&&u.test(n)&&(s=y,n=n.replace(s,"")),"y"==r&&(n=r.toLowerCase()+n.substr(1)),n};return z}(),t.Pipeline.registerFunction(t.stemmer,"stemmer"),t.stopWordFilter=function(e){return e&&t.stopWordFilter.stopWords[e]!==!0?e:void 0},t.clearStopWords=function(){t.stopWordFilter.stopWords={}},t.addStopWords=function(e){null!=e&&Array.isArray(e)!==!1&&e.forEach(function(e){t.stopWordFilter.stopWords[e]=!0},this)},t.resetStopWords=function(){t.stopWordFilter.stopWords=t.defaultStopWords},t.defaultStopWords={"":!0,a:!0,able:!0,about:!0,across:!0,after:!0,all:!0,almost:!0,also:!0,am:!0,among:!0,an:!0,and:!0,any:!0,are:!0,as:!0,at:!0,be:!0,because:!0,been:!0,but:!0,by:!0,can:!0,cannot:!0,could:!0,dear:!0,did:!0,"do":!0,does:!0,either:!0,"else":!0,ever:!0,every:!0,"for":!0,from:!0,get:!0,got:!0,had:!0,has:!0,have:!0,he:!0,her:!0,hers:!0,him:!0,his:!0,how:!0,however:!0,i:!0,"if":!0,"in":!0,into:!0,is:!0,it:!0,its:!0,just:!0,least:!0,let:!0,like:!0,likely:!0,may:!0,me:!0,might:!0,most:!0,must:!0,my:!0,neither:!0,no:!0,nor:!0,not:!0,of:!0,off:!0,often:!0,on:!0,only:!0,or:!0,other:!0,our:!0,own:!0,rather:!0,said:!0,say:!0,says:!0,she:!0,should:!0,since:!0,so:!0,some:!0,than:!0,that:!0,the:!0,their:!0,them:!0,then:!0,there:!0,these:!0,they:!0,"this":!0,tis:!0,to:!0,too:!0,twas:!0,us:!0,wants:!0,was:!0,we:!0,were:!0,what:!0,when:!0,where:!0,which:!0,"while":!0,who:!0,whom:!0,why:!0,will:!0,"with":!0,would:!0,yet:!0,you:!0,your:!0},t.stopWordFilter.stopWords=t.defaultStopWords,t.Pipeline.registerFunction(t.stopWordFilter,"stopWordFilter"),t.trimmer=function(e){if(null===e||void 0===e)throw new Error("token should not be undefined");return e.replace(/^\W+/,"").replace(/\W+$/,"")},t.Pipeline.registerFunction(t.trimmer,"trimmer"),t.InvertedIndex=function(){this.root={docs:{},df:0}},t.InvertedIndex.load=function(e){var t=new this;return t.root=e.root,t},t.InvertedIndex.prototype.addToken=function(e,t,n){for(var n=n||this.root,i=0;i<=e.length-1;){var o=e[i];o in n||(n[o]={docs:{},df:0}),i+=1,n=n[o]}var r=t.ref;n.docs[r]?n.docs[r]={tf:t.tf}:(n.docs[r]={tf:t.tf},n.df+=1)},t.InvertedIndex.prototype.hasToken=function(e){if(!e)return!1;for(var t=this.root,n=0;n<e.length;n++){if(!t[e[n]])return!1;t=t[e[n]]}return!0},t.InvertedIndex.prototype.getNode=function(e){if(!e)return null;for(var t=this.root,n=0;n<e.length;n++){if(!t[e[n]])return null;t=t[e[n]]}return t},t.InvertedIndex.prototype.getDocs=function(e){var t=this.getNode(e);return null==t?{}:t.docs},t.InvertedIndex.prototype.getTermFrequency=function(e,t){var n=this.getNode(e);return null==n?0:t in n.docs?n.docs[t].tf:0},t.InvertedIndex.prototype.getDocFreq=function(e){var t=this.getNode(e);return null==t?0:t.df},t.InvertedIndex.prototype.removeToken=function(e,t){if(e){var n=this.getNode(e);null!=n&&t in n.docs&&(delete n.docs[t],n.df-=1)}},t.InvertedIndex.prototype.expandToken=function(e,t,n){if(null==e||""==e)return[];var t=t||[];if(void 0==n&&(n=this.getNode(e),null==n))return t;n.df>0&&t.push(e);for(var i in n)"docs"!==i&&"df"!==i&&this.expandToken(e+i,t,n[i]);return t},t.InvertedIndex.prototype.toJSON=function(){return{root:this.root}},t.Configuration=function(e,n){var e=e||"";if(void 0==n||null==n)throw new Error("fields should not be null");this.config={};var i;try{i=JSON.parse(e),this.buildUserConfig(i,n)}catch(o){t.utils.warn("user configuration parse failed, will use default configuration"),this.buildDefaultConfig(n)}},t.Configuration.prototype.buildDefaultConfig=function(e){this.reset(),e.forEach(function(e){this.config[e]={boost:1,bool:"OR",expand:!1}},this)},t.Configuration.prototype.buildUserConfig=function(e,n){var i="OR",o=!1;if(this.reset(),"bool"in e&&(i=e.bool||i),"expand"in e&&(o=e.expand||o),"fields"in e)for(var r in e.fields)if(n.indexOf(r)>-1){var s=e.fields[r],u=o;void 0!=s.expand&&(u=s.expand),this.config[r]={boost:s.boost||0===s.boost?s.boost:1,bool:s.bool||i,expand:u}}else t.utils.warn("field name in user configuration not found in index instance fields");else this.addAllFields2UserConfig(i,o,n)},t.Configuration.prototype.addAllFields2UserConfig=function(e,t,n){n.forEach(function(n){this.config[n]={boost:1,bool:e,expand:t}},this)},t.Configuration.prototype.get=function(){return this.config},t.Configuration.prototype.reset=function(){this.config={}},lunr.SortedSet=function(){this.length=0,this.elements=[]},lunr.SortedSet.load=function(e){var t=new this;return t.elements=e,t.length=e.length,t},lunr.SortedSet.prototype.add=function(){var e,t;for(e=0;e<arguments.length;e++)t=arguments[e],~this.indexOf(t)||this.elements.splice(this.locationFor(t),0,t);this.length=this.elements.length},lunr.SortedSet.prototype.toArray=function(){return this.elements.slice()},lunr.SortedSet.prototype.map=function(e,t){return this.elements.map(e,t)},lunr.SortedSet.prototype.forEach=function(e,t){return this.elements.forEach(e,t)},lunr.SortedSet.prototype.indexOf=function(e){for(var t=0,n=this.elements.length,i=n-t,o=t+Math.floor(i/2),r=this.elements[o];i>1;){if(r===e)return o;e>r&&(t=o),r>e&&(n=o),i=n-t,o=t+Math.floor(i/2),r=this.elements[o]}return r===e?o:-1},lunr.SortedSet.prototype.locationFor=function(e){for(var t=0,n=this.elements.length,i=n-t,o=t+Math.floor(i/2),r=this.elements[o];i>1;)e>r&&(t=o),r>e&&(n=o),i=n-t,o=t+Math.floor(i/2),r=this.elements[o];return r>e?o:e>r?o+1:void 0},lunr.SortedSet.prototype.intersect=function(e){for(var t=new lunr.SortedSet,n=0,i=0,o=this.length,r=e.length,s=this.elements,u=e.elements;;){if(n>o-1||i>r-1)break;s[n]!==u[i]?s[n]<u[i]?n++:s[n]>u[i]&&i++:(t.add(s[n]),n++,i++)}return t},lunr.SortedSet.prototype.clone=function(){var e=new lunr.SortedSet;return e.elements=this.toArray(),e.length=e.elements.length,e},lunr.SortedSet.prototype.union=function(e){var t,n,i;this.length>=e.length?(t=this,n=e):(t=e,n=this),i=t.clone();for(var o=0,r=n.toArray();o<r.length;o++)i.add(r[o]);return i},lunr.SortedSet.prototype.toJSON=function(){return this.toArray()},function(e,t){"function"==typeof define&&define.amd?define(t):"object"==typeof exports?module.exports=t():e.elasticlunr=t()}(this,function(){return t})}();
+    /** pdoc search index */const docs = {"version": "0.9.5", "fields": ["qualname", "fullname", "annotation", "default_value", "signature", "bases", "doc"], "ref": "fullname", "documentStore": {"docs": {"MicroPie": {"fullname": "MicroPie", "modulename": "MicroPie", "kind": "module", "doc": "<p>MicroPie: A simple Python ultra-micro web framework with ASGI\nsupport. <a href=\"https://patx.github.io/micropie\">https://patx.github.io/micropie</a></p>\n\n<p>Copyright Harrison Erd</p>\n\n<p>Redistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:</p>\n\n<ol>\n<li><p>Redistributions of source code must retain the above copyright notice,\nthis list of conditions and the following disclaimer.</p></li>\n<li><p>Redistributions in binary form must reproduce the above copyright notice,\nthis list of conditions and the following disclaimer in the documentation\nand/or other materials provided with the distribution.</p></li>\n<li><p>Neither the name of the copyright holder nor the names of its\ncontributors may be used to endorse or promote products derived from this\nsoftware without specific prior written permission.</p></li>\n</ol>\n\n<p>THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS\nIS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR\nCONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\nEXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\nPROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\nOR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\nWHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\nOTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</p>\n"}, "MicroPie.current_request": {"fullname": "MicroPie.current_request", "modulename": "MicroPie", "qualname": "current_request", "kind": "variable", "doc": "<p></p>\n", "annotation": ": _contextvars.ContextVar[typing.Any]", "default_value": "&lt;ContextVar name=&#x27;current_request&#x27;&gt;"}, "MicroPie.Request": {"fullname": "MicroPie.Request", "modulename": "MicroPie", "qualname": "Request", "kind": "class", "doc": "<p>Represents an HTTP request in the MicroPie framework.</p>\n"}, "MicroPie.Request.__init__": {"fullname": "MicroPie.Request.__init__", "modulename": "MicroPie", "qualname": "Request.__init__", "kind": "function", "doc": "<p>Initialize a new Request instance.</p>\n\n<p>Args:\n    scope: The ASGI scope dictionary for the request.</p>\n", "signature": "<span class=\"signature pdoc-code condensed\">(<span class=\"param\"><span class=\"n\">scope</span><span class=\"p\">:</span> <span class=\"n\">Dict</span><span class=\"p\">[</span><span class=\"nb\">str</span><span class=\"p\">,</span> <span class=\"n\">Any</span><span class=\"p\">]</span></span>)</span>"}, "MicroPie.Request.scope": {"fullname": "MicroPie.Request.scope", "modulename": "MicroPie", "qualname": "Request.scope", "kind": "variable", "doc": "<p></p>\n", "annotation": ": Dict[str, Any]"}, "MicroPie.Request.method": {"fullname": "MicroPie.Request.method", "modulename": "MicroPie", "qualname": "Request.method", "kind": "variable", "doc": "<p></p>\n", "annotation": ": str"}, "MicroPie.Request.path_params": {"fullname": "MicroPie.Request.path_params", "modulename": "MicroPie", "qualname": "Request.path_params", "kind": "variable", "doc": "<p></p>\n", "annotation": ": List[str]"}, "MicroPie.Request.query_params": {"fullname": "MicroPie.Request.query_params", "modulename": "MicroPie", "qualname": "Request.query_params", "kind": "variable", "doc": "<p></p>\n", "annotation": ": Dict[str, List[str]]"}, "MicroPie.Request.body_params": {"fullname": "MicroPie.Request.body_params", "modulename": "MicroPie", "qualname": "Request.body_params", "kind": "variable", "doc": "<p></p>\n", "annotation": ": Dict[str, List[str]]"}, "MicroPie.Request.session": {"fullname": "MicroPie.Request.session", "modulename": "MicroPie", "qualname": "Request.session", "kind": "variable", "doc": "<p></p>\n", "annotation": ": Dict[str, Any]"}, "MicroPie.Request.files": {"fullname": "MicroPie.Request.files", "modulename": "MicroPie", "qualname": "Request.files", "kind": "variable", "doc": "<p></p>\n", "annotation": ": Dict[str, Any]"}, "MicroPie.Server": {"fullname": "MicroPie.Server", "modulename": "MicroPie", "qualname": "Server", "kind": "class", "doc": "<p>ASGI server for handling HTTP requests and WebSocket connections in MicroPie.</p>\n"}, "MicroPie.Server.__init__": {"fullname": "MicroPie.Server.__init__", "modulename": "MicroPie", "qualname": "Server.__init__", "kind": "function", "doc": "<p>Initialize a new Server instance.</p>\n\n<p>If Jinja2 is installed, set up the template environment.</p>\n", "signature": "<span class=\"signature pdoc-code condensed\">()</span>"}, "MicroPie.Server.SESSION_TIMEOUT": {"fullname": "MicroPie.Server.SESSION_TIMEOUT", "modulename": "MicroPie", "qualname": "Server.SESSION_TIMEOUT", "kind": "variable", "doc": "<p></p>\n", "annotation": ": int", "default_value": "28800"}, "MicroPie.Server.sessions": {"fullname": "MicroPie.Server.sessions", "modulename": "MicroPie", "qualname": "Server.sessions", "kind": "variable", "doc": "<p></p>\n", "annotation": ": Dict[str, Any]"}, "MicroPie.Server.request": {"fullname": "MicroPie.Server.request", "modulename": "MicroPie", "qualname": "Server.request", "kind": "variable", "doc": "<p>Retrieve the current request from the context variable.</p>\n\n<p>Returns:\n    The current Request instance.</p>\n", "annotation": ": MicroPie.Request"}}, "docInfo": {"MicroPie": {"qualname": 0, "fullname": 1, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 260}, "MicroPie.current_request": {"qualname": 2, "fullname": 3, "annotation": 4, "default_value": 10, "signature": 0, "bases": 0, "doc": 3}, "MicroPie.Request": {"qualname": 1, "fullname": 2, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 11}, "MicroPie.Request.__init__": {"qualname": 3, "fullname": 4, "annotation": 0, "default_value": 0, "signature": 26, "bases": 0, "doc": 20}, "MicroPie.Request.scope": {"qualname": 2, "fullname": 3, "annotation": 3, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "MicroPie.Request.method": {"qualname": 2, "fullname": 3, "annotation": 2, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "MicroPie.Request.path_params": {"qualname": 3, "fullname": 4, "annotation": 2, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "MicroPie.Request.query_params": {"qualname": 3, "fullname": 4, "annotation": 3, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "MicroPie.Request.body_params": {"qualname": 3, "fullname": 4, "annotation": 3, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "MicroPie.Request.session": {"qualname": 2, "fullname": 3, "annotation": 3, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "MicroPie.Request.files": {"qualname": 2, "fullname": 3, "annotation": 3, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "MicroPie.Server": {"qualname": 1, "fullname": 2, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 14}, "MicroPie.Server.__init__": {"qualname": 3, "fullname": 4, "annotation": 0, "default_value": 0, "signature": 4, "bases": 0, "doc": 20}, "MicroPie.Server.SESSION_TIMEOUT": {"qualname": 3, "fullname": 4, "annotation": 2, "default_value": 1, "signature": 0, "bases": 0, "doc": 3}, "MicroPie.Server.sessions": {"qualname": 2, "fullname": 3, "annotation": 3, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "MicroPie.Server.request": {"qualname": 2, "fullname": 3, "annotation": 3, "default_value": 0, "signature": 0, "bases": 0, "doc": 19}}, "length": 16, "save": true}, "index": {"qualname": {"root": {"docs": {"MicroPie.Request.__init__": {"tf": 1}, "MicroPie.Server.__init__": {"tf": 1}}, "df": 2, "c": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {"MicroPie.current_request": {"tf": 1}}, "df": 1}}}}}}}, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "q": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {"MicroPie.current_request": {"tf": 1}, "MicroPie.Request": {"tf": 1}, "MicroPie.Request.__init__": {"tf": 1}, "MicroPie.Request.scope": {"tf": 1}, "MicroPie.Request.method": {"tf": 1}, "MicroPie.Request.path_params": {"tf": 1}, "MicroPie.Request.query_params": {"tf": 1}, "MicroPie.Request.body_params": {"tf": 1}, "MicroPie.Request.session": {"tf": 1}, "MicroPie.Request.files": {"tf": 1}, "MicroPie.Server.request": {"tf": 1}}, "df": 11}}}}}}}, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {"MicroPie.Request.__init__": {"tf": 1}, "MicroPie.Server.__init__": {"tf": 1}}, "df": 2}}}}, "s": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {"MicroPie.Request.scope": {"tf": 1}}, "df": 1}}}}, "e": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"MicroPie.Request.session": {"tf": 1}, "MicroPie.Server.SESSION_TIMEOUT": {"tf": 1}}, "df": 2, "s": {"docs": {"MicroPie.Server.sessions": {"tf": 1}}, "df": 1}}}}}}, "r": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"MicroPie.Server": {"tf": 1}, "MicroPie.Server.__init__": {"tf": 1}, "MicroPie.Server.SESSION_TIMEOUT": {"tf": 1}, "MicroPie.Server.sessions": {"tf": 1}, "MicroPie.Server.request": {"tf": 1}}, "df": 5}}}}}}, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "d": {"docs": {"MicroPie.Request.method": {"tf": 1}}, "df": 1}}}}}}, "p": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {"MicroPie.Request.path_params": {"tf": 1}}, "df": 1}}, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "s": {"docs": {"MicroPie.Request.path_params": {"tf": 1}, "MicroPie.Request.query_params": {"tf": 1}, "MicroPie.Request.body_params": {"tf": 1}}, "df": 3}}}}}}, "q": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "y": {"docs": {"MicroPie.Request.query_params": {"tf": 1}}, "df": 1}}}}}, "b": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "y": {"docs": {"MicroPie.Request.body_params": {"tf": 1}}, "df": 1}}}}, "f": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"MicroPie.Request.files": {"tf": 1}}, "df": 1}}}}}, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "t": {"docs": {"MicroPie.Server.SESSION_TIMEOUT": {"tf": 1}}, "df": 1}}}}}}}}}, "fullname": {"root": {"docs": {"MicroPie.Request.__init__": {"tf": 1}, "MicroPie.Server.__init__": {"tf": 1}}, "df": 2, "m": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "e": {"docs": {"MicroPie": {"tf": 1}, "MicroPie.current_request": {"tf": 1}, "MicroPie.Request": {"tf": 1}, "MicroPie.Request.__init__": {"tf": 1}, "MicroPie.Request.scope": {"tf": 1}, "MicroPie.Request.method": {"tf": 1}, "MicroPie.Request.path_params": {"tf": 1}, "MicroPie.Request.query_params": {"tf": 1}, "MicroPie.Request.body_params": {"tf": 1}, "MicroPie.Request.session": {"tf": 1}, "MicroPie.Request.files": {"tf": 1}, "MicroPie.Server": {"tf": 1}, "MicroPie.Server.__init__": {"tf": 1}, "MicroPie.Server.SESSION_TIMEOUT": {"tf": 1}, "MicroPie.Server.sessions": {"tf": 1}, "MicroPie.Server.request": {"tf": 1}}, "df": 16}}}}}}}, "e": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "d": {"docs": {"MicroPie.Request.method": {"tf": 1}}, "df": 1}}}}}}, "c": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {"MicroPie.current_request": {"tf": 1}}, "df": 1}}}}}}}, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "q": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {"MicroPie.current_request": {"tf": 1}, "MicroPie.Request": {"tf": 1}, "MicroPie.Request.__init__": {"tf": 1}, "MicroPie.Request.scope": {"tf": 1}, "MicroPie.Request.method": {"tf": 1}, "MicroPie.Request.path_params": {"tf": 1}, "MicroPie.Request.query_params": {"tf": 1}, "MicroPie.Request.body_params": {"tf": 1}, "MicroPie.Request.session": {"tf": 1}, "MicroPie.Request.files": {"tf": 1}, "MicroPie.Server.request": {"tf": 1}}, "df": 11}}}}}}}, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {"MicroPie.Request.__init__": {"tf": 1}, "MicroPie.Server.__init__": {"tf": 1}}, "df": 2}}}}, "s": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {"MicroPie.Request.scope": {"tf": 1}}, "df": 1}}}}, "e": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"MicroPie.Request.session": {"tf": 1}, "MicroPie.Server.SESSION_TIMEOUT": {"tf": 1}}, "df": 2, "s": {"docs": {"MicroPie.Server.sessions": {"tf": 1}}, "df": 1}}}}}}, "r": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"MicroPie.Server": {"tf": 1}, "MicroPie.Server.__init__": {"tf": 1}, "MicroPie.Server.SESSION_TIMEOUT": {"tf": 1}, "MicroPie.Server.sessions": {"tf": 1}, "MicroPie.Server.request": {"tf": 1}}, "df": 5}}}}}}, "p": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {"MicroPie.Request.path_params": {"tf": 1}}, "df": 1}}, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "s": {"docs": {"MicroPie.Request.path_params": {"tf": 1}, "MicroPie.Request.query_params": {"tf": 1}, "MicroPie.Request.body_params": {"tf": 1}}, "df": 3}}}}}}, "q": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "y": {"docs": {"MicroPie.Request.query_params": {"tf": 1}}, "df": 1}}}}}, "b": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "y": {"docs": {"MicroPie.Request.body_params": {"tf": 1}}, "df": 1}}}}, "f": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"MicroPie.Request.files": {"tf": 1}}, "df": 1}}}}}, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "t": {"docs": {"MicroPie.Server.SESSION_TIMEOUT": {"tf": 1}}, "df": 1}}}}}}}}}, "annotation": {"root": {"docs": {"MicroPie.current_request": {"tf": 1}, "MicroPie.Request.scope": {"tf": 1}, "MicroPie.Request.method": {"tf": 1}, "MicroPie.Request.path_params": {"tf": 1}, "MicroPie.Request.query_params": {"tf": 1}, "MicroPie.Request.body_params": {"tf": 1}, "MicroPie.Request.session": {"tf": 1}, "MicroPie.Request.files": {"tf": 1}, "MicroPie.Server.SESSION_TIMEOUT": {"tf": 1}, "MicroPie.Server.sessions": {"tf": 1}, "MicroPie.Server.request": {"tf": 1}}, "df": 11, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "x": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "s": {"docs": {"MicroPie.current_request": {"tf": 1}}, "df": 1}, "[": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "y": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"MicroPie.current_request": {"tf": 1}}, "df": 1}}}}}}}}}}}}}}}}}, "a": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "y": {"docs": {"MicroPie.current_request": {"tf": 1}, "MicroPie.Request.scope": {"tf": 1}, "MicroPie.Request.session": {"tf": 1}, "MicroPie.Request.files": {"tf": 1}, "MicroPie.Server.sessions": {"tf": 1}}, "df": 5}}}, "d": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "[": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "r": {"docs": {"MicroPie.Request.scope": {"tf": 1}, "MicroPie.Request.query_params": {"tf": 1}, "MicroPie.Request.body_params": {"tf": 1}, "MicroPie.Request.session": {"tf": 1}, "MicroPie.Request.files": {"tf": 1}, "MicroPie.Server.sessions": {"tf": 1}}, "df": 6}}}}}}}}, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "r": {"docs": {"MicroPie.Request.method": {"tf": 1}}, "df": 1}}}, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "[": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "r": {"docs": {"MicroPie.Request.path_params": {"tf": 1}, "MicroPie.Request.query_params": {"tf": 1}, "MicroPie.Request.body_params": {"tf": 1}}, "df": 3}}}}}}}}, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {"MicroPie.Server.SESSION_TIMEOUT": {"tf": 1}}, "df": 1}}}, "m": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "e": {"docs": {"MicroPie.Server.request": {"tf": 1}}, "df": 1}}}}}}}}, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "q": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {"MicroPie.Server.request": {"tf": 1}}, "df": 1}}}}}}}}}, "default_value": {"root": {"2": {"8": {"8": {"0": {"0": {"docs": {"MicroPie.Server.SESSION_TIMEOUT": {"tf": 1}}, "df": 1}, "docs": {}, "df": 0}, "docs": {}, "df": 0}, "docs": {}, "df": 0}, "docs": {}, "df": 0}, "docs": {"MicroPie.current_request": {"tf": 1.4142135623730951}}, "df": 1, "l": {"docs": {}, "df": 0, "t": {"docs": {"MicroPie.current_request": {"tf": 1}}, "df": 1}}, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "x": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {"MicroPie.current_request": {"tf": 1}}, "df": 1}}}}}}}}}, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {"MicroPie.current_request": {"tf": 1}}, "df": 1}}}}}}}, "n": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {"MicroPie.current_request": {"tf": 1}}, "df": 1}}}}, "x": {"2": {"7": {"docs": {"MicroPie.current_request": {"tf": 1.4142135623730951}}, "df": 1}, "docs": {}, "df": 0}, "docs": {}, "df": 0}, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "q": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {"MicroPie.current_request": {"tf": 1}}, "df": 1}}}}}}}, "g": {"docs": {}, "df": 0, "t": {"docs": {"MicroPie.current_request": {"tf": 1}}, "df": 1}}}}, "signature": {"root": {"docs": {"MicroPie.Request.__init__": {"tf": 4.69041575982343}, "MicroPie.Server.__init__": {"tf": 2}}, "df": 2, "s": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {"MicroPie.Request.__init__": {"tf": 1}}, "df": 1}}}}, "t": {"docs": {}, "df": 0, "r": {"docs": {"MicroPie.Request.__init__": {"tf": 1}}, "df": 1}}}, "d": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {"MicroPie.Request.__init__": {"tf": 1}}, "df": 1}}}}, "a": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "y": {"docs": {"MicroPie.Request.__init__": {"tf": 1}}, "df": 1}}}}}, "bases": {"root": {"docs": {}, "df": 0}}, "doc": {"root": {"docs": {"MicroPie": {"tf": 5.477225575051661}, "MicroPie.current_request": {"tf": 1.7320508075688772}, "MicroPie.Request": {"tf": 1.7320508075688772}, "MicroPie.Request.__init__": {"tf": 2.449489742783178}, "MicroPie.Request.scope": {"tf": 1.7320508075688772}, "MicroPie.Request.method": {"tf": 1.7320508075688772}, "MicroPie.Request.path_params": {"tf": 1.7320508075688772}, "MicroPie.Request.query_params": {"tf": 1.7320508075688772}, "MicroPie.Request.body_params": {"tf": 1.7320508075688772}, "MicroPie.Request.session": {"tf": 1.7320508075688772}, "MicroPie.Request.files": {"tf": 1.7320508075688772}, "MicroPie.Server": {"tf": 1.7320508075688772}, "MicroPie.Server.__init__": {"tf": 2.449489742783178}, "MicroPie.Server.SESSION_TIMEOUT": {"tf": 1.7320508075688772}, "MicroPie.Server.sessions": {"tf": 1.7320508075688772}, "MicroPie.Server.request": {"tf": 2.449489742783178}}, "df": 16, "m": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "o": {"docs": {"MicroPie": {"tf": 1}}, "df": 1, "p": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "e": {"docs": {"MicroPie": {"tf": 1}, "MicroPie.Request": {"tf": 1}, "MicroPie.Server": {"tf": 1}}, "df": 3}}}}}}}, "o": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}}}}}}}, "e": {"docs": {}, "df": 0, "t": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}, "r": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "y": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}}}}}}}}}}, "u": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {"MicroPie": {"tf": 1.4142135623730951}}, "df": 1}}}, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "s": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}}}, "y": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}, "a": {"docs": {"MicroPie": {"tf": 1.4142135623730951}, "MicroPie.Request.__init__": {"tf": 1}, "MicroPie.Server.__init__": {"tf": 1}}, "df": 3, "s": {"docs": {"MicroPie": {"tf": 1}}, "df": 1, "g": {"docs": {}, "df": 0, "i": {"docs": {"MicroPie": {"tf": 1}, "MicroPie.Request.__init__": {"tf": 1}, "MicroPie.Server": {"tf": 1}}, "df": 3}}}, "n": {"docs": {"MicroPie.Request": {"tf": 1}}, "df": 1, "d": {"docs": {"MicroPie": {"tf": 2.8284271247461903}, "MicroPie.Server": {"tf": 1}}, "df": 2, "/": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}, "y": {"docs": {"MicroPie": {"tf": 2}}, "df": 1}}, "r": {"docs": {}, "df": 0, "e": {"docs": {"MicroPie": {"tf": 1.7320508075688772}}, "df": 1}, "i": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}, "g": {"docs": {}, "df": 0, "s": {"docs": {"MicroPie.Request.__init__": {"tf": 1}}, "df": 1}}}, "b": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {"MicroPie": {"tf": 1.4142135623730951}}, "df": 1}}}}, "d": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}}}, "s": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}, "u": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "t": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}, "b": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}}}}, "c": {"docs": {}, "df": 0, "h": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}, "o": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {"MicroPie": {"tf": 1.4142135623730951}}, "df": 1}}}}, "f": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "w": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {"MicroPie": {"tf": 1.7320508075688772}}, "df": 1}}}}}}}, "p": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}, "a": {"docs": {}, "df": 0, "l": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}}, "h": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "l": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}, "e": {"docs": {}, "df": 0, "r": {"docs": {"MicroPie.Server": {"tf": 1}, "MicroPie.Server.__init__": {"tf": 1}}, "df": 2}}}}, "t": {"docs": {"MicroPie.Server.__init__": {"tf": 1}}, "df": 1}}, "t": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {"MicroPie.Request.__init__": {"tf": 1.4142135623730951}}, "df": 1}}}}}, "p": {"docs": {}, "df": 0, "y": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}, "s": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}}}}}, "r": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"MicroPie": {"tf": 1.7320508075688772}}, "df": 1}}}}}, "m": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}, "d": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "s": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}, "c": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}}}}, "f": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "s": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}}}}}, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}}, "o": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "y": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}}}}}}}, "u": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}, "s": {"docs": {}, "df": 0, "e": {"docs": {"MicroPie": {"tf": 1.7320508075688772}}, "df": 1, "d": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}, "p": {"docs": {"MicroPie.Server.__init__": {"tf": 1}}, "df": 1}}, "w": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "b": {"docs": {"MicroPie": {"tf": 1}}, "df": 1, "s": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "k": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {"MicroPie.Server": {"tf": 1}}, "df": 1}}}}}}}}, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {"MicroPie": {"tf": 1.7320508075688772}}, "df": 1, "o": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "t": {"docs": {"MicroPie": {"tf": 1.4142135623730951}}, "df": 1}}}}}}, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}}, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"MicroPie": {"tf": 1.4142135623730951}}, "df": 1}}}}}}}}, "y": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}, "h": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}}}, "f": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "w": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "k": {"docs": {"MicroPie": {"tf": 1}, "MicroPie.Request": {"tf": 1}}, "df": 2}}}}}}}, "o": {"docs": {}, "df": 0, "m": {"docs": {"MicroPie": {"tf": 1}, "MicroPie.Server.request": {"tf": 1}}, "df": 2}}}, "o": {"docs": {}, "df": 0, "r": {"docs": {"MicroPie": {"tf": 1.4142135623730951}, "MicroPie.Request.__init__": {"tf": 1}, "MicroPie.Server": {"tf": 1}}, "df": 3, "m": {"docs": {"MicroPie": {"tf": 1}}, "df": 1, "s": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}, "l": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "w": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"MicroPie": {"tf": 1.7320508075688772}}, "df": 1}}}}}}}}, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "s": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}}}, "h": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "p": {"docs": {"MicroPie.Request": {"tf": 1}, "MicroPie.Server": {"tf": 1}}, "df": 2, "s": {"docs": {}, "df": 0, ":": {"docs": {}, "df": 0, "/": {"docs": {}, "df": 0, "/": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "x": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}}}}}}}, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}}, "n": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"MicroPie.Server": {"tf": 1}}, "df": 1}}}}}}}, "o": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"MicroPie": {"tf": 1.4142135623730951}}, "df": 1, "s": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}, "w": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}}}, "g": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "b": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}, "o": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "s": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "/": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "e": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}}}}}}, "n": {"docs": {"MicroPie": {"tf": 2.449489742783178}, "MicroPie.Request": {"tf": 1}, "MicroPie.Server": {"tf": 1}}, "df": 3, "c": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"MicroPie": {"tf": 1.7320508075688772}}, "df": 1}}}}}}, "i": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}}}}, "d": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}}, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}}}}}}, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "z": {"docs": {}, "df": 0, "e": {"docs": {"MicroPie.Request.__init__": {"tf": 1}, "MicroPie.Server.__init__": {"tf": 1}}, "df": 2}}}}}}}}, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {"MicroPie.Request.__init__": {"tf": 1}, "MicroPie.Server.__init__": {"tf": 1}, "MicroPie.Server.request": {"tf": 1}}, "df": 3}}}, "l": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"MicroPie.Server.__init__": {"tf": 1}}, "df": 1}}}}}}}}, "t": {"docs": {}, "df": 0, "s": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}, "s": {"docs": {"MicroPie": {"tf": 1.4142135623730951}, "MicroPie.Server.__init__": {"tf": 1}}, "df": 2}, "m": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"MicroPie": {"tf": 1.4142135623730951}}, "df": 1}}}}}}, "f": {"docs": {"MicroPie": {"tf": 1}, "MicroPie.Server.__init__": {"tf": 1}}, "df": 2}}, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "y": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "t": {"docs": {"MicroPie": {"tf": 2.449489742783178}}, "df": 1}}}}}}}, "n": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "s": {"docs": {"MicroPie": {"tf": 1.7320508075688772}}, "df": 1}}}}}}}, "t": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "s": {"docs": {"MicroPie": {"tf": 1.7320508075688772}}, "df": 1}}}}}}}, "a": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}, "e": {"docs": {}, "df": 0, "x": {"docs": {}, "df": 0, "t": {"docs": {"MicroPie.Server.request": {"tf": 1}}, "df": 1}}}}, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "q": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}}}}}}, "n": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "s": {"docs": {"MicroPie.Server": {"tf": 1}}, "df": 1}}}}}}}}}, "d": {"docs": {}, "df": 0, "e": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}, "a": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {"MicroPie.Server.request": {"tf": 1.4142135623730951}}, "df": 1}}}}}}}, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "d": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}, "n": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}, "v": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {"MicroPie.Server.__init__": {"tf": 1}}, "df": 1}}}}}}}}}}, "x": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "s": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}, "e": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "y": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}}}}, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {"MicroPie": {"tf": 1}}, "df": 1, "t": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"MicroPie": {"tf": 1}}, "df": 1, "s": {"docs": {"MicroPie": {"tf": 1.4142135623730951}}, "df": 1}}}}}}}}}}}}}, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {"MicroPie.Server.request": {"tf": 1}}, "df": 1}}}}}, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "s": {"docs": {"MicroPie.Server.request": {"tf": 1}}, "df": 1}}}}}, "p": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}, "e": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "s": {"docs": {"MicroPie.Request": {"tf": 1}}, "df": 1}}}}}}}}, "q": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {"MicroPie.Request": {"tf": 1}, "MicroPie.Request.__init__": {"tf": 1.4142135623730951}, "MicroPie.Server.request": {"tf": 1.4142135623730951}}, "df": 3, "s": {"docs": {"MicroPie.Server": {"tf": 1}}, "df": 1}}}}}}}}, "b": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "y": {"docs": {"MicroPie": {"tf": 1.4142135623730951}}, "df": 1}}}}}, "e": {"docs": {"MicroPie": {"tf": 1.4142135623730951}}, "df": 1}, "y": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}, "u": {"docs": {}, "df": 0, "t": {"docs": {"MicroPie": {"tf": 1.4142135623730951}}, "df": 1}, "s": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "s": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}}}}, "o": {"docs": {}, "df": 0, "r": {"docs": {"MicroPie": {"tf": 3.1622776601683795}}, "df": 1}, "f": {"docs": {"MicroPie": {"tf": 3.605551275463989}}, "df": 1}, "t": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"MicroPie": {"tf": 1}}, "df": 1, "w": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}}}}, "n": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}, "u": {"docs": {}, "df": 0, "t": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}, "t": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}, "e": {"docs": {"MicroPie": {"tf": 3.872983346207417}, "MicroPie.Request": {"tf": 1}, "MicroPie.Request.__init__": {"tf": 1.4142135623730951}, "MicroPie.Server.__init__": {"tf": 1}, "MicroPie.Server.request": {"tf": 1.7320508075688772}}, "df": 5, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "y": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}, "i": {"docs": {}, "df": 0, "s": {"docs": {"MicroPie": {"tf": 2.23606797749979}}, "df": 1}}}, "o": {"docs": {"MicroPie": {"tf": 1.7320508075688772}}, "df": 1, "r": {"docs": {}, "df": 0, "t": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}, "e": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {"MicroPie.Server.__init__": {"tf": 1}}, "df": 1}}}}}}}}, "n": {"docs": {}, "df": 0, "o": {"docs": {"MicroPie": {"tf": 1}}, "df": 1, "t": {"docs": {"MicroPie": {"tf": 1.4142135623730951}}, "df": 1, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {"MicroPie": {"tf": 1.4142135623730951}}, "df": 1}}}}, "r": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}, "e": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}, "g": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}}}}, "w": {"docs": {"MicroPie.Request.__init__": {"tf": 1}, "MicroPie.Server.__init__": {"tf": 1}}, "df": 2}}, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {"MicroPie": {"tf": 1}}, "df": 1, "s": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {"MicroPie": {"tf": 1.4142135623730951}}, "df": 1}}, "m": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"MicroPie": {"tf": 1.4142135623730951}}, "df": 1}}}}}, "a": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}, "i": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "y": {"docs": {"MicroPie": {"tf": 1.4142135623730951}}, "df": 1}}}}}}}}, "o": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "s": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}, "d": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"MicroPie": {"tf": 1.4142135623730951}}, "df": 1}, "d": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}}}, "t": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}}}}}}, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}, "c": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "y": {"docs": {"MicroPie.Request.__init__": {"tf": 1}}, "df": 1}}}}}}}}}, "o": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}}}}}}}}, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}}, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "e": {"docs": {"MicroPie": {"tf": 1}}, "df": 1, "s": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}}, "t": {"docs": {}, "df": 0, "a": {"docs": {"MicroPie": {"tf": 1}}, "df": 1}}}}, "j": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "j": {"docs": {}, "df": 0, "a": {"2": {"docs": {"MicroPie.Server.__init__": {"tf": 1}}, "df": 1}, "docs": {}, "df": 0}}}}}, "v": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"MicroPie.Server.request": {"tf": 1}}, "df": 1}}}}}}}}}}}, "pipeline": ["trimmer"], "_isPrebuiltIndex": true};
+
+    // mirrored in build-search-index.js (part 1)
+    // Also split on html tags. this is a cheap heuristic, but good enough.
+    elasticlunr.tokenizer.setSeperator(/[\s\-.;&_'"=,()]+|<[^>]*>/);
+
+    let searchIndex;
+    if (docs._isPrebuiltIndex) {
+        console.info("using precompiled search index");
+        searchIndex = elasticlunr.Index.load(docs);
+    } else {
+        console.time("building search index");
+        // mirrored in build-search-index.js (part 2)
+        searchIndex = elasticlunr(function () {
+            this.pipeline.remove(elasticlunr.stemmer);
+            this.pipeline.remove(elasticlunr.stopWordFilter);
+            this.addField("qualname");
+            this.addField("fullname");
+            this.addField("annotation");
+            this.addField("default_value");
+            this.addField("signature");
+            this.addField("bases");
+            this.addField("doc");
+            this.setRef("fullname");
+        });
+        for (let doc of docs) {
+            searchIndex.addDoc(doc);
+        }
+        console.timeEnd("building search index");
+    }
+
+    return (term) => searchIndex.search(term, {
+        fields: {
+            qualname: {boost: 4},
+            fullname: {boost: 2},
+            annotation: {boost: 2},
+            default_value: {boost: 2},
+            signature: {boost: 2},
+            bases: {boost: 2},
+            doc: {boost: 1},
+        },
+        expand: true
+    });
+})();
\ No newline at end of file
diff --git a/examples/socketio/webtrc/MicroPie.py b/examples/socketio/webtrc/MicroPie.py
deleted file mode 100644
index d505062..0000000
--- a/examples/socketio/webtrc/MicroPie.py
+++ /dev/null
@@ -1,442 +0,0 @@
-"""
-MicroPie: A simple Python ultra-micro web framework with ASGI
-support. https://patx.github.io/micropie
-
-Copyright Harrison Erd
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-1. Redistributions of source code must retain the above copyright notice,
-   this list of conditions and the following disclaimer.
-
-2. Redistributions in binary form must reproduce the above copyright notice,
-   this list of conditions and the following disclaimer in the documentation
-   and/or other materials provided with the distribution.
-
-3. Neither the name of the copyright holder nor the names of its
-   contributors may be used to endorse or promote products derived from this
-   software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
-CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
-EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-"""
-import asyncio
-import inspect
-import mimetypes
-import os
-import re
-import time
-from typing import Optional, Dict, Any, Union, Tuple, List
-from urllib.parse import parse_qs
-import uuid
-import contextvars
-
-from multipart import PushMultipartParser, MultipartSegment
-
-try:
-    from jinja2 import Environment, FileSystemLoader
-    JINJA_INSTALLED = True
-    import asyncio
-except ImportError:
-    JINJA_INSTALLED = False
-
-# Create a context variable to store the current request
-current_request = contextvars.ContextVar('current_request')
-
-class Request:
-    def __init__(self, scope):
-        self.scope = scope
-        self.method = scope["method"]
-        self.path_params = []
-        self.query_params = {}
-        self.body_params = {}
-        self.session = {}
-        self.files = {}
-
-class Server:
-    SESSION_TIMEOUT: int = 8 * 3600  # 8 hours
-
-    def __init__(self) -> None:
-        if JINJA_INSTALLED:
-            self.env = Environment(loader=FileSystemLoader("templates"))
-
-        self.sessions: Dict[str, Any] = {}
-
-    @property
-    def request(self) -> Request:
-        return current_request.get()
-
-    async def __call__(self, scope, receive, send):
-        await self._asgi_app(scope, receive, send)
-
-    async def _asgi_app(self, scope: Dict[str, Any], receive: Any, send: Any) -> None:
-        """ASGI application entrypoint for both HTTP and WebSockets."""
-        if scope["type"] == "http":
-            request = Request(scope)
-            # Set the current request in the context variable
-            token = current_request.set(request)
-
-            try:
-                method = scope["method"]
-                path = scope["path"].lstrip("/")
-                path_parts = path.split("/") if path else []
-                func_name = path_parts[0] if path_parts else "index"
-
-                # Ignore methods that start with an underscore
-                if func_name.startswith("_"):
-                    await self._send_response(send, status_code=404, body="404 Not Found")
-                    return
-
-                request.path_params = path_parts[1:] if len(path_parts) > 1 else []
-                handler_function = getattr(self, func_name, None)
-                if not handler_function:
-                    request.path_params = path_parts
-                    handler_function = getattr(self, "index", None)
-
-                raw_query = scope.get("query_string", b"")
-                request.query_params = parse_qs(raw_query.decode("utf-8", "ignore"))
-
-                headers_dict = {
-                    k.decode("latin-1").lower(): v.decode("latin-1")
-                    for k, v in scope.get("headers", [])
-                }
-                cookies = self._parse_cookies(headers_dict.get("cookie", ""))
-
-                session_id = cookies.get("session_id")
-                if session_id and session_id in self.sessions:
-                    request.session = self.sessions[session_id]
-                    request.session["last_access"] = time.time()
-                else:
-                    request.session = {}
-
-                request.body_params = {}
-                request.files = {}
-                if method in ("POST", "PUT", "PATCH"):
-                    body_data = bytearray()
-                    while True:
-                        msg = await receive()
-                        if msg["type"] == "http.request":
-                            body_data += msg.get("body", b"")
-                            if not msg.get("more_body"):
-                                break
-                    content_type = headers_dict.get("content-type", "")
-                    if "multipart/form-data" in content_type:
-                        # Extract the boundary from the Content-Type header
-                        match = re.search(r'boundary=([^;]+)', content_type)
-                        if not match:
-                            await self._send_response(
-                                send, status_code=400,
-                                body="400 Bad Request: Boundary not found in Content-Type header"
-                            )
-                            return
-                        boundary = match.group(1).encode("utf-8")  # Convert boundary to bytes
-
-                        # Create a StreamReader and feed it the body data
-                        reader = asyncio.StreamReader()
-                        reader.feed_data(body_data)
-                        reader.feed_eof()
-
-                        # Now call _parse_multipart with the reader and the boundary
-                        await self._parse_multipart(reader, boundary)
-                    else:
-                        body_str = body_data.decode("utf-8", "ignore")
-                        request.body_params = parse_qs(body_str)
-
-                sig = inspect.signature(handler_function)
-                func_args = []
-                for param in sig.parameters.values():
-                    if request.path_params:
-                        func_args.append(request.path_params.pop(0))
-                    elif param.name in request.query_params:
-                        func_args.append(request.query_params[param.name][0])
-                    elif param.name in request.body_params:
-                        func_args.append(request.body_params[param.name][0])
-                    elif param.name in request.files:
-                        func_args.append(request.files[param.name])
-                    elif param.name in request.session:
-                        func_args.append(request.session[param.name])
-                    elif param.default is not param.empty:
-                        func_args.append(param.default)
-                    else:
-                        await self._send_response(
-                            send,
-                            status_code=400,
-                            body=f"400 Bad Request: Missing required parameter '{param.name}'",
-                        )
-                        return
-
-                if handler_function == getattr(self, "index", None) and not func_args and path:
-                    await self._send_response(send, status_code=404, body="404 Not Found")
-                    return
-
-                try:
-                    if inspect.iscoroutinefunction(handler_function):
-                        result = await handler_function(*func_args)
-                    else:
-                        result = handler_function(*func_args)
-                except Exception as e:
-                    print(f"Error processing request: {e}")
-                    await self._send_response(
-                        send, status_code=500, body="500 Internal Server Error"
-                    )
-                    return
-
-                status_code = 200
-                response_body = result
-                extra_headers: List[Tuple[str, str]] = []
-
-                if isinstance(result, tuple):
-                    if len(result) == 2:
-                        status_code, response_body = result
-                    elif len(result) == 3:
-                        status_code, response_body, extra_headers = result
-                    else:
-                        await self._send_response(
-                            send, status_code=500,
-                            body="500 Internal Server Error: Invalid response tuple"
-                        )
-                        return
-
-                if request.session:
-                    session_id = cookies.get("session_id", str(uuid.uuid4()))
-                    self.sessions[session_id] = request.session  # Store session only if used
-                    extra_headers.append(("Set-Cookie", f"session_id={session_id}; Path=/; HttpOnly; SameSite=Strict"))
-
-                await self._send_response(
-                    send,
-                    status_code=status_code,
-                    body=response_body,
-                    extra_headers=extra_headers
-                )
-            finally:
-                # Reset the context variable to avoid leaking request state
-                current_request.reset(token)
-        else:
-            pass
-
-    def _parse_cookies(self, cookie_header: str) -> Dict[str, str]:
-        cookies: Dict[str, str] = {}
-        if not cookie_header:
-            return cookies
-        for cookie in cookie_header.split(";"):
-            if "=" in cookie:
-                k, v = cookie.strip().split("=", 1)
-                cookies[k] = v
-        return cookies
-
-    async def _parse_multipart(self, reader: asyncio.StreamReader, boundary: bytes):
-        """
-        Demonstrates handling multipart/form-data in a more streaming-friendly manner.
-        For large files, data is written to disk instead of stored in memory.
-        """
-        with PushMultipartParser(boundary) as parser:
-            current_field_name = None
-            current_filename = None
-            current_content_type = None
-            current_file = None  # File handle for streaming writes
-            form_value = ""
-
-            # Directory for storing uploaded files:
-            # Adjust if you want a different path or a dynamic approach inside your app.
-            upload_directory = "uploads"
-
-            # Ensure the directory exists
-            os.makedirs(upload_directory, exist_ok=True)
-
-            while not parser.closed:
-                # Read data in chunks from the request stream
-                chunk = await reader.read(65536)  # 64KB per read
-                for result in parser.parse(chunk):
-                    if isinstance(result, MultipartSegment):
-                        # We have a new part: form field or file
-                        current_field_name = result.name
-                        current_filename = result.filename
-                        current_content_type = None
-                        form_value = ""
-
-                        # Parse content-type if present
-                        for header, value in result.headerlist:
-                            if header.lower() == "content-type":
-                                current_content_type = value
-
-                        # If it's a file, open a file handle right away
-                        if current_filename:
-                            safe_filename = f"{uuid.uuid4()}_{current_filename}"
-                            file_path = os.path.join(upload_directory, safe_filename)
-                            current_file = open(file_path, "wb")
-
-                        # Otherwise, treat it as a field (string value).
-                        else:
-                            if current_field_name not in self.request.body_params:
-                                self.request.body_params[current_field_name] = []
-
-                    elif result:
-                        # This chunk is body data for the current part
-                        if current_file:
-                            # If it's a file, write directly to disk
-                            current_file.write(result)
-                        else:
-                            # It's a form field chunk
-                            form_value += result.decode("utf-8", "ignore")
-                    else:
-                        # End of this part
-                        if current_file:
-                            # Close out the file if we're done writing it
-                            current_file.close()
-                            current_file = None
-
-                            # Store reference in self.request.files so the upload handler can use it
-                            # Example structure includes just filename and content type;
-                            # no in-memory data, since we wrote it to disk.
-                            if current_field_name:
-                                self.request.files[current_field_name] = {
-                                    "filename": current_filename,
-                                    "content_type": current_content_type or "application/octet-stream",
-                                    "saved_path": os.path.join(upload_directory, safe_filename),
-                                }
-                        else:
-                            # If it was a form field, add the form value to body_params
-                            if current_field_name:
-                                self.request.body_params[current_field_name].append(form_value)
-
-                        # Reset for the next part
-                        current_field_name = None
-                        current_filename = None
-                        current_content_type = None
-                        form_value = ""
-
-    async def _send_response(
-        self,
-        send,
-        status_code: int,
-        body,
-        extra_headers=None
-    ):
-        if extra_headers is None:
-            extra_headers = []
-
-        # Common HTTP status text
-        status_map = {
-            200: "200 OK",
-            206: "206 Partial Content",
-            302: "302 Found",
-            403: "403 Forbidden",
-            404: "404 Not Found",
-            500: "500 Internal Server Error",
-        }
-        status_text = status_map.get(status_code, f"{status_code} OK")
-
-        # Ensure extra headers are safe
-        sanitized_headers = []
-        for k, v in extra_headers:
-            if "\n" in k or "\r" in k or "\n" in v or "\r" in v:
-                print(f"Header injection attempt detected: {k}: {v}")
-                continue  # Skip invalid headers
-            sanitized_headers.append((k, v))
-
-        # Ensure Content-Type is set unless explicitly provided
-        has_content_type = any(h[0].lower() == "content-type" for h in sanitized_headers)
-        if not has_content_type:
-            sanitized_headers.append(("Content-Type", "text/html; charset=utf-8"))
-
-        # Send response start
-        await send({
-            "type": "http.response.start",
-            "status": status_code,
-            "headers": [
-                (k.encode("latin-1"), v.encode("latin-1")) for k, v in sanitized_headers
-            ],
-        })
-
-        # 1) Check if body is an async generator (has __aiter__)
-        if hasattr(body, "__aiter__"):
-            async for chunk in body:
-                if isinstance(chunk, str):
-                    chunk = chunk.encode("utf-8")
-                await send({
-                    "type": "http.response.body",
-                    "body": chunk,
-                    "more_body": True
-                })
-            # Send a final empty chunk to mark the end
-            await send({
-                "type": "http.response.body",
-                "body": b"",
-                "more_body": False
-            })
-            return
-
-        # 2) Check if body is a *sync* generator (has __iter__) and
-        #    is not a plain string/bytes
-        if hasattr(body, "__iter__") and not isinstance(body, (bytes, str)):
-            for chunk in body:
-                if isinstance(chunk, str):
-                    chunk = chunk.encode("utf-8")
-                await send({
-                    "type": "http.response.body",
-                    "body": chunk,
-                    "more_body": True
-                })
-            # Send a final empty chunk
-            await send({
-                "type": "http.response.body",
-                "body": b"",
-                "more_body": False
-            })
-            return
-
-        if isinstance(body, str):
-            response_body = body.encode("utf-8")
-        elif isinstance(body, bytes):
-            response_body = body
-        else:
-            # Convert anything else to string then to bytes
-            response_body = str(body).encode("utf-8")
-
-        # Ensure body is properly encoded
-        response_body = body.encode("utf-8") if isinstance(body, str) else body
-        await send({
-            "type": "http.response.body",
-            "body": response_body,
-            "more_body": False
-        })
-
-    def _cleanup_sessions(self) -> None:
-        now = time.time()
-        self.sessions = {
-            sid: data
-            for sid, data in self.sessions.items()
-            if data.get("last_access", now) + self.SESSION_TIMEOUT > now
-        }
-
-    def _redirect(self, location: str) -> Tuple[int, str]:
-        return (
-            302,
-            (
-                "<html><head>"
-                f"<meta http-equiv='refresh' content='0;url={location}'>"
-                "</head></html>"
-            ),
-        )
-
-    async def _render_template(self, name: str, **kwargs: Any) -> str:
-        """
-        Async-compatible template rendering using Jinja2.
-        """
-        if not JINJA_INSTALLED:
-            raise ImportError("Jinja2 is not installed.")
-
-        def render_sync():
-            return self.env.get_template(name).render(kwargs)
-
-        return await asyncio.get_event_loop().run_in_executor(None, render_sync)
diff --git a/setup.py b/setup.py
index 23f1958..0cbcd86 100644
--- a/setup.py
+++ b/setup.py
@@ -25,7 +25,7 @@ Links
 from distutils.core import setup
 
 setup(name="MicroPie",
-    version="0.9.1",
+    version="0.9.2",
     description="A ultra micro web framework w/ Jinja2.",
     long_description=__doc__,
     author="Harrison Erd",