Skip to main content

Hosting local servers easily, smooth as butter.

Project description

lynq

Lynq for Python is an open-source python framework that allows developers to host servers absurdly easily (we're talking 1-line easily) And this isn't even an exaggeration! Once you have Lynq imported, the world is basically in your hands.

Let's look at the most configurable and advanced way to host servers using Lynq, and move our way down the ladder to the easiest way. First though, let's see how you can get lynq on your own system. Or you can skip this part.

Install Guide

Methods

1. Use pip

DISCLAIMER: This method requires pip to be installed on your system.

  • Open any command line terminal like powershell, cmd, git bash etc.
  • Run this command: pip install lynq.
  • Done! You now have the newest version of Lynq installed locally on your system.
  • Want to upgrade? Run pip install lynq --upgrade to automatically download the newest version released currently released on pip.
  • Use pip show lynq to view info and version about lynq on your local system.
  • Use pip uninstall lynq to uninstall lynq from your local system.

2. Clone from GitHub

DISCLAIMER: This method requires the git CLI to be installed on your system.

  • Open any command line terminal like powershell, cmd, git bash etc.
  • Run this command: git clone https://github.com/elemenom/lynq.git.
  • Complete! Please note that this only creates a directory of lynq, so you may need to run this is each project you need lynq for.
  • Updating and uninstalling is done using rm ./lynq/*; rm -r ./lynq; git clone https://github.com/elemenom/lynq.git and rm ./lynq/*; rm -r ./lynq in Windows PowerShell respectively.

3. Download a release from GitHub

DISCLAIMER: This method requires any modern web browser to be installed on your system.

4. Build from source

  • You can view the source code for lynq on GitHub

ConfigurableLynqServer Class Documentation

The ConfigurableLynqServer class is an extension of the LynqServer class that adds flexibility and configurability to the basic HTTP server setup. This class allows the server to be configured either via a JSON configuration file, command-line arguments, or default values. Below is a detailed explanation of its functionality and components.

Overview

The ConfigurableLynqServer class is designed to provide a customizable HTTP server setup by allowing configuration through multiple sources:

  1. Configuration File: A JSON file containing server settings.
  2. Command-line Arguments: Options provided via the command line to override or set specific settings.
  3. Default Values: Fallbacks for when no other configuration is provided.

Class Definition

class ConfigurableLynqServer(LynqServer):
    def __init__(self, config_file: Optional[str] = None, directory: Optional[str] = None, handler: Optional[Type[http.server.BaseHTTPRequestHandler]] = None):
        config = self.load_config(config_file)
        port = config.get("port", 8000)  # Default to int
        directory = directory or config.get("directory")
        super().__init__(port, directory, handler)

    @staticmethod
    def load_config(config_file: Optional[str]) -> dict:
        if config_file and Path(config_file).exists():
            with open(config_file, 'r') as f:
                try:
                    config = json.load(f)
                    logger.info(f"Loaded configuration from {config_file}")
                    return config
                except json.JSONDecodeError as e:
                    logger.error(f"Error parsing config file: {e}")
        else:
            logger.warning(f"No valid config file found. Using default settings.")
        return {}

    @staticmethod
    def parse_args() -> argparse.Namespace:
        parser = argparse.ArgumentParser(description="Start a local HTTP server.")
        parser.add_argument('--port', type=int, default=8000, help="Port number to run the server on")
        parser.add_argument('--config', type=str, help="Path to configuration file")
        parser.add_argument('--directory', type=str, help="Directory to serve files from")
        return parser.parse_args()

Constructor: __init__

Parameters

  • config_file: An optional string representing the path to a JSON configuration file. If provided, this file is used to set the server's port and directory.

  • directory: An optional string representing the directory from which files will be served. If not provided, it defaults to the directory specified in the configuration file or remains None.

  • handler: An optional HTTP request handler class. If not specified, a default handler is used.

Functionality

  1. Load Configuration: The constructor calls the load_config method to load settings from the provided configuration file (if any).

  2. Port Setup: The server port is determined by checking the loaded configuration for a "port" key. If absent, it defaults to 8000.

  3. Directory Setup: The directory is set based on the provided argument or from the configuration file if the argument is None.

  4. Superclass Initialization: The constructor calls the superclass (LynqServer) constructor with the determined port, directory, and handler.

Methods

load_config(config_file: Optional[str]) -> dict

Description

This static method attempts to load a configuration file in JSON format.

Parameters

  • config_file: A string representing the path to the configuration file. It can be None if no file is provided.

Returns

  • A dictionary containing the configuration settings. If the file doesn't exist or can't be parsed, an empty dictionary is returned.

Functionality

  1. File Existence Check: The method checks if the provided configuration file path exists.

  2. File Parsing: If the file exists, it attempts to parse it as JSON. Errors during parsing are logged, and an empty dictionary is returned.

  3. Fallback: If the file doesn't exist or cannot be loaded, a warning is logged, and the method returns an empty dictionary.

parse_args() -> argparse.Namespace

Description

This static method parses command-line arguments to provide additional configuration options for the server.

Returns

  • An argparse.Namespace object containing the parsed arguments.

Arguments

  • --port: The port number on which the server should run. Defaults to 8000.

  • --config: The path to the configuration file.

  • --directory: The directory to serve files from.

Usage

This method is typically called when running the server script from the command line, allowing users to override defaults or configuration file settings directly.

Usage Example

if __name__ == "__main__":
    args = ConfigurableLynqServer.parse_args()
    server = ConfigurableLynqServer(config_file=args.config, directory=args.directory)
    server.serve_forever()

In this example:

  1. Command-line arguments are parsed.
  2. A ConfigurableLynqServer instance is created using the parsed arguments.
  3. The server is started, serving files from the specified directory and listening on the specified port.

Summary

The ConfigurableLynqServer class offers a flexible way to configure and run an HTTP server. By leveraging configuration files, command-line arguments, and defaults, it provides a robust mechanism to tailor server behavior to various needs.

ConfigurableLynqServer is a great choice for experienced programmers that know what they're doing

LynqServer Class Documentation

The LynqServer class provides a basic, customizable HTTP server capable of serving files from a specified directory. It leverages Python’s http.server and socketserver modules to handle HTTP requests and manage the server’s lifecycle. Below is a detailed explanation of its functionality and components.

Overview

The LynqServer class is designed to facilitate the creation and management of a simple HTTP server. It provides functionality to:

  • Initialize the server with a specific port and directory.
  • Create a custom request handler.
  • Start and stop the server.
  • Automatically open a web browser pointing to the server’s URL.

Class Definition

class LynqServer:
    def __init__(self, port: int, directory: Optional[str] = None, handler: Optional[Type[http.server.BaseHTTPRequestHandler]] = None):
        self.port: int = port
        self.directory: Path = Path(directory) if directory else Path.cwd()
        self.handler: Type[http.server.BaseHTTPRequestHandler] = handler or self._create_handler()
        try:
            self.httpd: socketserver.TCPServer = socketserver.TCPServer(("localhost", self.port), self.handler)
            self.httpd.directory = str(self.directory)  # Set directory for the server
            logger.info(f"Server initialized on port {self.port} with directory {self.directory}")
        except OSError as e:
            logger.error(f"Could not start server on port {self.port}: {e}")
            raise

    def _create_handler(self) -> Type[http.server.BaseHTTPRequestHandler]:
        class CustomHandler(http.server.SimpleHTTPRequestHandler):
            def translate_path(self, path: str) -> str:
                # Removes query parameters, etc., from the URL path
                path = path.split('?', 1)[0]
                path = path.split('#', 1)[0]
                path = Path(path).relative_to('/')

                # Combine the requested path with the server's directory
                full_path = self.server.directory / path

                # Resolve the final absolute path
                return str(full_path.resolve())
        return CustomHandler

    def _start_server(self) -> None:
        server_thread: threading.Thread = threading.Thread(target=self.httpd.serve_forever)
        server_thread.daemon = True
        server_thread.start()
        logger.info(f"Server started on port {self.port}")

    def open(self) -> None:
        self._start_server()
        url = f"http://localhost:{self.port}"
        logger.info(f"Opening browser at {url}")
        webbrowser.open(url)

    def _stop_server(self) -> None:
        self.httpd.shutdown()
        self.httpd.server_close()
        logger.info(f"Server on port {self.port} stopped")

    def close(self) -> None:
        self._stop_server()

Constructor: __init__

Parameters

  • port: An integer specifying the port number on which the server will listen.

  • directory: An optional string representing the directory from which the server will serve files. If not provided, it defaults to the current working directory (Path.cwd()).

  • handler: An optional HTTP request handler class. If not specified, a custom handler is created using the _create_handler method.

Functionality

  1. Port Initialization: The port is set based on the provided argument.

  2. Directory Initialization: The directory is set to the provided path or defaults to the current working directory.

  3. Request Handler: The server uses the provided handler or a custom handler created by _create_handler.

  4. Server Setup: The server is initialized with the socketserver.TCPServer class, binding it to localhost on the specified port and using the configured request handler.

  5. Error Handling: If the server fails to start (e.g., due to the port being in use), an error is logged, and an OSError is raised.

Methods

_create_handler() -> Type[http.server.BaseHTTPRequestHandler]

Description

This private method creates and returns a custom request handler class based on http.server.SimpleHTTPRequestHandler.

Functionality

  • Path Translation: The translate_path method is overridden to clean the URL path by removing query parameters and fragments. It then combines the cleaned path with the server’s base directory to determine the absolute file path to be served.

_start_server() -> None

Description

This private method starts the server in a background thread, allowing it to serve requests indefinitely without blocking the main thread.

Functionality

  • Threading: The server runs in a daemon thread, meaning it will automatically stop when the main program exits.

  • Logging: A message is logged when the server starts successfully.

open() -> None

Description

This method starts the server and opens the default web browser to the server's URL.

Functionality

  • Start Server: The server is started using _start_server.

  • Open Browser: The server's URL (http://localhost:{port}) is opened in the default web browser.

_stop_server() -> None

Description

This private method stops the server gracefully by shutting it down and closing the server socket.

Functionality

  • Shutdown: The server's request-handling loop is stopped.

  • Close Socket: The server socket is closed, freeing up the port.

  • Logging: A message is logged indicating that the server has been stopped.

close() -> None

Description

This method is a public interface to stop the server by calling _stop_server.

Functionality

  • Stop Server: The server is stopped and cleaned up.

Usage Example

if __name__ == "__main__":
    server = LynqServer(port=8000, directory="/path/to/serve")
    server.open()
    # The server is now running and serving files
    try:
        while True:
            pass  # Keep the main thread alive
    except KeyboardInterrupt:
        server.close()  # Stop the server on Ctrl+C

In this example:

  1. The server is initialized with a specific port and directory.
  2. The server is started, and the default web browser opens to the server's URL.
  3. The server runs indefinitely until interrupted (e.g., via Ctrl+C), after which it stops gracefully.

Summary

The LynqServer class provides a simple and customizable way to create an HTTP server. With built-in methods for server management and a customizable request handler, it is well-suited for scenarios requiring a lightweight and configurable web server.

LynqServer is a great choice for intermediate programmers that know how this works, but aren't quite experienced enough to tackle ConfigurableLynqServer

launch Function Documentation

The launch function is a utility function that simplifies the process of starting a LynqServer instance. It is designed to quickly initialize, start, and manage the lifecycle of a basic HTTP server with minimal setup.

Function Definition

def launch(port: Optional[int] = None, directory: Optional[str] = None) -> None:
    server: LynqServer = LynqServer(port or 8000, directory or ".")

    try:
        server.open()
        input("\033[1;93mPress enter to exit your Lynq server...\n\033[0m")

    finally:
        server.close()

Parameters

  • port: An optional integer specifying the port number on which the server will listen. If not provided, the function defaults to port 8000.

  • directory: An optional string specifying the directory from which the server will serve files. If not provided, the function defaults to the current directory (".").

Functionality

  1. Server Initialization:

    • The function initializes a LynqServer instance using the provided port and directory arguments.
    • If either argument is not provided, it falls back to the default values: port 8000 and the current directory (".").
  2. Server Startup:

    • The server.open() method is called to start the server.
    • This method also opens the default web browser to the server's URL (http://localhost:{port}).
  3. User Prompt:

    • The function waits for user input with a prompt: "Press enter to exit your Lynq server...".
    • The prompt is displayed in yellow text to stand out in the console.
  4. Server Shutdown:

    • Regardless of how the function exits (either after user input or due to an exception), the server is properly closed by calling server.close().
    • This ensures that the server shuts down gracefully and the port is released.

Usage Example

if __name__ == "__main__":
    launch(port=8080, directory="/path/to/serve")

In this example:

  • The launch function is called with a specific port (8080) and directory (/path/to/serve).
  • The server starts and serves files from the specified directory.
  • The function waits for the user to press enter, after which the server shuts down.

Summary

The launch function provides a convenient way to start and manage a LynqServer instance with minimal code. It handles the server’s lifecycle, from initialization to shutdown, and includes user interaction to control when the server should stop running. This makes it an ideal entry point for scripts that need to quickly start a basic HTTP server.

launch() is a great choice for beginners, or basically anybody who just wants to open a server really quickly and efficiently.

Summary

As you saw from the above documentation, Lynq for Python is a quick, efficient web framework that is insanely easy to master, features many different levels of difficulty to appeal to different skill-levels of programmers, and overall is great at it's job; hosting local servers easily, as smooth as butter.

  • All Lynq servers (no matter the type) will run until the heat death of the universe (unless you press enter to exit them manually)

Lynq x MSIE

You can now host custom instances of internet explorer that very easily allow you to remotely interact with them using their COM objects.

DISCLAIMER: We are not partnered with Microsoft or any other company, all material is open source.

InternetExplorerInstance Class Documentation

The InternetExplorerInstance class provides a high-level interface for controlling Internet Explorer instances via PowerShell commands. This class allows for launching a new Internet Explorer window, navigating to specific URLs, and refreshing the browser window. It utilizes the PowerShell COM object model to interact with Internet Explorer.

Overview

The InternetExplorerInstance class is designed to facilitate browser automation with Internet Explorer, using PowerShell scripts executed through Python’s subprocess module. This class is particularly useful for scripting and testing environments where Internet Explorer is required.

Class Definition

class InternetExplorerInstance:
    def __init__(self) -> None:
        self.pwie: Callable = lambda cmd: pwsh(f"$ie = New-Object -ComObject \"InternetExplorer.Application\"; {cmd}")

    def open(self) -> None:
        self.pwie("$ie.Visible = $true")
        logger.info("Launched new internet explorer instance")

    def navigate(self, link: Optional[str]) -> None:
        self.pwie(f"$ie.Navigate({repr(link) or 'http://localhost'})")
        logger.info(f"Navigated internet explorer into {link}")

    def refresh(self) -> None:
        self.pwie("$ie.Refresh()")
        logger.info("Refresh internet explorer")

Methods

__init__() -> None

Description

The constructor initializes an instance of InternetExplorerInstance.

Functionality

  • PowerShell Command Wrapper: Defines a self.pwie lambda function to run PowerShell commands that create a new Internet Explorer COM object. This lambda function calls the pwsh function with the appropriate PowerShell command string.

open() -> None

Description

Launches a new Internet Explorer instance and makes it visible.

Functionality

  • PowerShell Command: Executes a PowerShell command to make the Internet Explorer instance visible.

  • Logging: Logs an informational message indicating that a new Internet Explorer instance has been launched.

navigate(link: Optional[str]) -> None

Description

Navigates the Internet Explorer instance to a specified URL.

Parameters

  • link: An optional string representing the URL to navigate to. If None, it defaults to http://localhost.

Functionality

  • PowerShell Command: Executes a PowerShell command to navigate to the specified URL.

  • Logging: Logs an informational message indicating the URL to which the browser is navigating.

refresh() -> None

Description

Refreshes the current page in the Internet Explorer instance.

Functionality

  • PowerShell Command: Executes a PowerShell command to refresh the current page.

  • Logging: Logs an informational message indicating that the Internet Explorer instance is being refreshed.

Dependencies

  • PowerShell: Required to execute PowerShell commands.
  • Internet Explorer: The class specifically targets Internet Explorer via its COM object model.
  • Python Libraries:
    • subprocess.run: To execute PowerShell commands from Python.
    • logging: To provide logging functionality.

Example Usage

if __name__ == "__main__":
    ie = InternetExplorerInstance()
    ie.open()  # Launches a new Internet Explorer instance
    ie.navigate("https://www.example.com")  # Navigates to "https://www.example.com"
    ie.refresh()  # Refreshes the current page

In this example:

  1. An InternetExplorerInstance object is created.
  2. The open method is called to launch a new Internet Explorer window.
  3. The navigate method is used to direct the browser to a specific URL.
  4. The refresh method is invoked to refresh the page.

Summary

The InternetExplorerInstance class provides a Python interface to automate Internet Explorer using PowerShell. It supports opening a new browser window, navigating to URLs, and refreshing the page. This class is useful in scenarios where Internet Explorer needs to be controlled programmatically, particularly in testing or automation tasks.

Microsoft Internet Explorer is deprecated, but it's still a handy tool to view local servers (via localhost), and Lynq let's you do that quickly and easily.

New features in Lynq for Python 2.0

P.E.B.L (Python Embedded Building Language) Documentation

P.E.B.L (Python Embedded Building Language) is a lightweight and flexible framework designed to facilitate the dynamic generation and serving of HTML content within a Python environment. It integrates seamlessly with the Lynq ecosystem, leveraging the power of LynqServer and ConfigurableLynqServer to deliver web content directly to the user.

Overview

P.E.B.L provides a streamlined interface for creating and managing web pages from within Python scripts. It supports a tag-based structure for building HTML components, enabling users to embed HTML directly in Python with ease. The core component of P.E.B.L is the PeblApp class, which manages the generation of HTML files and interacts with Lynq servers to serve this content.

Key Components

1. PeblApp Class

The PeblApp class is the heart of P.E.B.L. It manages the lifecycle of an HTML page, from creation to serving, within a LynqServer environment.

  • Initialization (__init__):

    def __init__(self, name: str, server: LynqServer | ConfigurableLynqServer | None = None) -> None:
    
    • name: The name of the HTML file to be created (without the .html extension).
    • server: An instance of LynqServer, ConfigurableLynqServer, or None. If provided, this server will be used to serve the generated HTML content.

    Example:

    app = PeblApp(name="index", server=my_server)
    
  • Tag Creation (tag):

    def tag(self, type_: str, args: Optional[str] = None) -> Any:
    
    • type_: The type of HTML tag to be generated (e.g., div, p, a).
    • args: Optional attributes or content for the tag.

    This method returns a TagObject which can be further manipulated or directly inserted into the HTML document.

    Example:

    app.tag("div", "class='container'")
    
  • Single Line Insertion (singular):

    def singular(self, ln: str) -> None:
    
    • ln: A string representing a single line of HTML to be appended to the HTML file.

    This method allows for quick insertion of raw HTML content into the document.

    Example:

    app.singular("<h1>Welcome to P.E.B.L!</h1>")
    
  • Exiting Context (__exit__):

    def __exit__(self, *_) -> None:
    

    Automatically invoked when the PeblApp instance exits a context manager. This method ensures that the generated HTML content is passed to the server for serving.

    Example:

    with PeblApp(name="index", server=my_server) as app:
        app.singular("<p>Hello, World!</p>")
    
  • Pass to Server (pass_to_server):

    def pass_to_server(self) -> None:
    

    This method handles passing the generated HTML file to the provided server instance and launching it. If no server is provided, an error is logged, and an exception is raised.

    Example:

    app.pass_to_server()
    

Usage Example

Here's a basic example of using P.E.B.L to generate and serve an HTML page:

from lynq.server import LynqServer
from lynq.app import PeblApp

# Create a LynqServer instance
server = LynqServer(port=8080, directory=".")

# Initialize the PeblApp with the server
with PeblApp(name="index", server=server) as app:
    app.singular("<h1>Hello from P.E.B.L!</h1>")
    app.singular("<p>This is a dynamically generated page.</p>")

Error Handling

  • If no server is provided when attempting to pass the script to a server, an error is logged, and an exception is raised.

    Example Error:

    logger.error("Cannot pass pebl script to server when no server was provided.")
    
  • The HTML file is automatically removed after it has been served to prevent unnecessary clutter, ensuring a clean working directory.

Integration with Lynq

P.E.B.L integrates tightly with Lynq, allowing for a fluid workflow where HTML content can be generated and served within the same Python environment. It leverages the existing LynqServer and ConfigurableLynqServer classes for this purpose.

This documentation covers the basics of working with P.E.B.L, including the main class PeblApp, its methods, and typical usage patterns. For more advanced features or extensions, refer to the full Lynq documentation or explore additional components within the lynq.app module.

Lynq 2.0 Logging with External Terminal Setup

Overview

Lynq 2.0 introduces an upgraded logging system that allows for more flexible and powerful logging configurations, including the ability to log to an external terminal or console. This enhancement provides developers with better control over logging output, making it easier to monitor and debug applications in real-time.

Key Features

  1. Enhanced Logging Flexibility: Configure logging to output to an external terminal, allowing real-time monitoring of log messages.
  2. Customizable Log Formats: Define custom formats for log messages to suit different needs and preferences.
  3. Advanced Logging Levels: Utilize different logging levels (e.g., DEBUG, INFO, WARNING, ERROR, CRITICAL) for more granular control over what gets logged.
  4. Integration with External Terminal: Redirect log output to an external terminal for easier access and visibility.

Setup and Configuration

1. Initial Configuration

Lynq 2.0’s logging system can be configured using the logging module in Python. To set up logging to an external terminal, you need to configure the logging handlers appropriately.

2. Configure Logging to an External Terminal

To direct logs to an external terminal, follow these steps:

a. Import the Required Modules
import logging
import sys
b. Set Up the Logging Configuration

You can configure logging to output to an external terminal by using the StreamHandler provided by Python's logging module. This handler can be set up to write log messages to sys.stdout, which is the standard output stream often connected to the terminal.

def setuplogging():
    # Create a logger
    logger = logging.getLogger()
    logger.setLevel(logging.DEBUG)  # Set the root logger level

    # Create a stream handler to output to the terminal
    handler = logging.StreamHandler(sys.stdout)
    handler.setLevel(logging.DEBUG)  # Set the handler level

    # Create a formatter and set it for the handler
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    handler.setFormatter(formatter)

    # Add the handler to the logger
    logger.addHandler(handler)
c. Use the Logger in Your Application

After setting up logging, you can use the logger in your application code to log messages:

def main():
    setuplogging()
    
    logger = logging.getLogger(__name__)
    
    logger.debug("This is a debug message")
    logger.info("This is an info message")
    logger.warning("This is a warning message")
    logger.error("This is an error message")
    logger.critical("This is a critical message")
    
if __name__ == "__main__":
    main()

3. Customizing Log Output

You can further customize the logging output by modifying the Formatter in the setuplogging function. For example, you can include additional information like module names or line numbers.

Example Formatter Customization
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(module)s - %(lineno)d - %(message)s')

4. Integration with External Terminal Applications

For enhanced integration, you might use external terminal applications or tools that support real-time log monitoring. Ensure that the terminal is set to receive logs from the standard output.

Example: Running a Script in a Terminal

Run your script in a terminal to see the log output directly:

python your_script.py

Troubleshooting

  • No Logs Appearing: Ensure that the terminal or console you are using is configured correctly to display standard output.
  • Incorrect Log Levels: Verify that the logging levels set in setuplogging match the levels you are using in your code.
  • Formatting Issues: If log messages appear incorrectly formatted, check the Formatter configuration in the setuplogging function.

Summary

Lynq 2.0’s upgraded logging system provides a robust solution for directing log output to an external terminal, enhancing real-time monitoring and debugging capabilities. By configuring the StreamHandler to use sys.stdout, you can easily integrate logging into your terminal-based workflows and customize the logging output to meet your needs.

For more advanced configurations and additional features, refer to the Python logging documentation and explore Lynq's logging capabilities further.

Lynq Server Launch Documentation

Overview

Lynq provides functionality to launch servers with ease through the directlaunch and launch functions. These functions facilitate starting and stopping LynqServer or ConfigurableLynqServer instances, handling user interaction and server management in a streamlined manner.

Functions Overview

directlaunch

The directlaunch function sets up and starts a basic LynqServer instance, using default values if no specific configuration is provided.

Function Signature
def directlaunch(port: Optional[int] = None, directory: Optional[str] = None) -> None:
Parameters
  • port (Optional[int]): The port number on which the server will listen. Defaults to 8000 if not provided.
  • directory (Optional[str]): The directory from which to serve files. Defaults to the current working directory (".") if not provided.
Functionality
  1. Initialization: Creates an instance of LynqServer with the specified port and directory.
  2. Starting the Server: Calls the open method to start the server.
  3. User Interaction: Waits for user input to keep the server running. The prompt message is styled in yellow to indicate the user should press Enter to exit.
  4. Stopping the Server: Ensures the server is properly closed after exiting the user prompt.
Example Usage
# Launch a LynqServer on port 8080 serving from the current directory
directlaunch(port=8080)

launch

The launch function starts a server instance, which can be either a LynqServer or a ConfigurableLynqServer. It is more flexible than directlaunch as it accepts any server that adheres to the expected interface.

Function Signature
def launch(server: LynqServer | ConfigurableLynqServer):
Parameters
  • server (LynqServer | ConfigurableLynqServer): An instance of LynqServer or ConfigurableLynqServer that will be started.
Functionality
  1. Starting the Server: Calls the open method on the provided server instance to start it.
  2. User Interaction: Waits for user input to keep the server running. The prompt message is styled in yellow to indicate the user should press Enter to exit.
  3. Stopping the Server: Ensures the server is properly closed after exiting the user prompt.
Example Usage
from lynq.server import LynqServer
from lynq.customserver import ConfigurableLynqServer

# Create a LynqServer instance
server = LynqServer(port=8080, directory=".")

# Launch the server
launch(server)

# Create a ConfigurableLynqServer instance with custom settings
config_server = ConfigurableLynqServer(config_file="config.json")

# Launch the configurable server
launch(config_server)

Error Handling

  • No Server Provided: Ensure that a valid LynqServer or ConfigurableLynqServer instance is passed to launch. Otherwise, an exception may be raised.

  • Port Conflicts: If the specified port is already in use, an OSError or similar exception may be encountered when trying to start the server.

  • Directory Issues: Ensure the specified directory exists and is accessible. Incorrect paths may lead to errors when attempting to serve files.

Summary

The directlaunch and launch functions provide straightforward methods for starting and stopping Lynq servers. directlaunch is a simple wrapper around LynqServer, while launch offers flexibility by accepting any compatible server instance. Both functions ensure that the server runs interactively, waiting for user input to gracefully shut down.

The directlaunch function is a rename of the OG launch function, which has been repurposed to run already created servers with the same treatement as directlaunched ones

Hey! This is Elekk! I hope you enjoy this new release of Lynq for Python. As you may know, this is an entirely solo open-source project I've been working on. If you have Any_ issues, suggestions, or feedback, please open an issue!

New features in Lynq v3

  • Bug fixes
  • P.E.B.L has default supported tags; so instead of app.tag("html", "arguments"), you can write app.html("arguments")
  • P.E.B.L apps are now created using the appnode decorator from lynq.app.app
  • External logging has been changed to run in the terminal you started the server from.
  • More logging
  • Better clean up
  • Many P.E.B.L improvements
  • No more log file
  • Warn count has been removed
  • Other QoL changes

New features in Lynq v4

  • Bug fixes
  • Support for Basin config files
  • Various improvements and updates to the README.md file
  • Better launcher mechanics
  • Basin now comes bundled in with the base release of Lynq v4.0.0 for Python and up
  • Other QoL changes
  • Improved app node
  • Improved type annotations and types
  • Global type for all LynqServer-like objects: LynqServerOrRelatedObjects from lynqserverorrelated
  • The pizza is in the oven :>

New features in Lynq v5

Changelog

  • MANY bug fixes
  • Imports in backend files are now harder to get confused by
  • Performance enhancements
  • More Basin features
  • BetterPebl 1 and 2 are fullt implemented
  • Cool changes
  • P.E.B.L and Basin apps are supercharged with new features and are now created using the @app() .export and @basinapp() .export decorators respectively.

lynqconfig

  • You can now create a file in the same directory as the importing file(s) (the file(s) that are importing lynq) which will change some properties of how lynq works.
  • Make sure to include ALL options or lynq will use defaults for everything. Any options you don't want to modify, just set them to None.
# lynqconfig.py

import logging

LOGGER = None
# This can be a logger object or 'None' for default logger.

LOGGINGCONFIG = {
    "filename": "mylog.log"
}
# Additional arguments for the default logger. 'LOGGER' must be 'None' for this to take effect.

LOGGINGLEVEL = logging.DEBUG
# Modify the 'level' argument for the default logger. 'LOGGER' must be 'None' for this to take effect.

LOGGINGFORMAT = "%(asctime)s, %(levelname)s, %(message)s"
# Modify the 'format' argument for the default logger. 'LOGGER' must be 'None' for this to take effect.

CLEANPYCACHE = False
# This is a new feature in lynq v5. Lynq can now automatically remove all __pycache__ files in the lynq directory. This makes development much easier as it removes the need for manual deletion. Leaving this off might make lynq run slightly faster. Default is 'False'.
  • More options will be added in the future.
  • You can also clean pycache from lynq manually by running python -m lynq._utils._lynq.manualcleanup in your command terminal.

_config

  • _config.py is the backend file that manages lynqconfig.py and the entire logging system. It is not importable*

*learn more at the 'what are _ prefixes' section.

_utils

  • _utils is like the closet of useful stuff lynq uses to run how it does. It is not importable*

*learn more at the 'what are _ prefixes' section.

what are _ prefixes

  • If something from lynq is prefixed with '_', this can be an item from a file (for ex. function or variable), it is not importable, which means you should not import them to your own projects. These items could potentially harm your computer if they aren't handled properly, and it's overall a bad idea and unintended to import them.

VERSION.md

Just a short markdown file indicating the current running lynq version and how to upgrade.

Where the heck is lynq/server.py???

  • All server-related files (server, customserver and basinserver) have been moved to the lynq.server package.
  • lynq.server is now located in lynq.server.standard
  • lynq.customserver is now located in lynq.server.custom
  • lynq.basinserver is now located in lynq.server.basin

New features in Lynq v6

Changelog

  • Lynq is A LOT more memory-efficient
  • Less files for navigation
  • All servers (LynqServer, ConfigurableLynqServer and BasinLynqServer) are now all in one module: lynq.server
  • app and basinapp can now both be accessed in the lynq.app module

Complete reworking of PEBL apps

  • PEBL apps have been reworked and are much more object oriented now.

Defining a PEBL app

# index.py

from lynq.app import app
from lynq.server import LynqServer

@app(LynqServer(
    port=8000,
    directory="./"
)) .export .standard
def my_pebl_app(self, name: str, age: int) -> None:
    with self.head() as head:
        ... # Code here

    with self.body() as body:
        with body.p() as p:
            p.singular("Your name is {}, you are {} years old.".format(name, age))

In the above example, we create an app called index.

DISCLAIMER: The name of the function/app DOES matter! It defines the name of your app, and therefore the HTML file assigned to it. It is recomended to use index for your main app. The name of the python file does not impact anything.

Now we have an app, but how do we pass it to it's server?

Spoiler: This has also been reworked

# main.py

from index import index

index(name="Bob", age=20) .launch()

How it works:

  • The decorator app and basinapp are classes, so passing the server or basin path respectively are actually passed to app.__init__. Then, app.export is a custom "Shallow Blank Slate Object" (SBSO) which is also a memory-efficient way to store small classes in memory. After export is the "Export Method". Export methods change the way your PEBL app displays. The only export method implemented in Lynq PEBL so far is standard. This implements elements normally, like everyone is used to. More export methods will be implemented later on.
  • In the main.py file, the index function is imported, but it's no longer a function because of the decorator. What we're calling .launch() on is actually a StandardAppExportObject; an object in charge of passing your apps to their dedicated LynqServer in Lynq v6.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

lynq-9.6.tar.gz (86.6 kB view hashes)

Uploaded Source

Built Distribution

lynq-9.6-py3-none-any.whl (100.3 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page