Skip to main content

A straightforward Python package that functions as an HTTP(s) server

Project description

CryskuraHTTP

CryskuraHTTP Logo

CryskuraHTTP is a lightweight, customizable HTTP(s) server implemented in Python that supports basic HTTP(s) functionalities, including serving files and handling errors, with support for custom services, API calls, and authentication.

Features

CryskuraHTTP is an extension of Python's built-in http.server, with minimal dependencies. You can leverage it to implement Python HTTP services without needing to install large software or libraries. It can also be used as a file sharing tool, supporting file serving and uploading through the browser, and can be launched from the Windows right-click menu.

  • Customizable Services: Easily add custom services by extending the BaseService class.
  • Customizable API Calls: Define custom API calls with the APIService class.
  • Error Handling: Customizable error handling via the ErrorService class.
  • File Serving: Serve files from a specified directory via the FileService class.
  • File Uploading: Handle file uploads via POST requests with the FileService class.
  • WebPage Serving: Serve web pages without allowing directory listing via the PageService class.
  • Customizable Routes: Define custom routes for your services with the Route class.
  • Customizable Authentication: Implement custom authentication for your services.
  • Auto uPnP Port Forwarding: Automatically forward ports using uPnP.
  • Request Handling: Handle GET, POST, HEAD requests.
  • Resumable Downloads: Supports resumable downloads for large files when serving files.
  • Redirects: Supports 301 and 308 redirects.
  • SSL Support: Optionally enable SSL by providing a certificate file.
  • Threaded Server: Supports multi-threaded request handling for better performance.
  • Command-Line Interface: Run the server from the command line with custom settings.
  • Right Click Support: Supports right-click context menu for launching the server on Windows.

This project is not designed to replace full-scale, production-grade HTTP servers. Instead, it is ideal for small-scale web UI development or for use alongside tools like pywebview and qtwebengine. So don't expect it to handle thousands of concurrent connections or to have advanced features like load balancing or caching.

Requirements

  • Python 3.x
  • psutil library

Installation

  1. Install the package using pip:

    pip install cryskura
    
  2. You can also download whl file from GitHub Releases and install it using pip:

    pip install cryskura-1.0-py3-none-any.wh
    
  3. Clone the repository and install manually if you want to modify the source code:

    git clone https://github.com/HofNature/CryskuraHTTP.git
    cd CryskuraHTTP
    python setup.py install
    

Quick Start

Starting the Server

To start the server with default settings:

from cryskura import Server
server = HTTPServer(interface="127.0.0.1", port=8080)
server.start()

This will start the server on localhost at port 8080 and serve files from the current directory.

Or you can run the server from the command line:

cryskura --interface 127.0.0.1 --port 8080 --path /path/to/serve

This will start the server on localhost at port 8080 and serve files from /path/to/serve.

Register to Right-Click Menu

You can add the server to the right-click context menu on Windows by running:

cryskura --addRightClick # You can also use -ar as a short form

Note: If arguments like --interface, --port, --browser, etc., are provided, the server will start with the specified settings when launched from the right-click menu.

If you want to remove it from the right-click menu, run:

cryskura --removeRightClick # You can also use -rr as a short form

Note: This feature is only available on Windows. For Windows 11 24h2 and above, if Sudo is enabled, it will be called automatically; otherwise, you need to run it manually with administrator privileges.

Stopping the Server

When using the Python API, you can stop the server by calling the stop() method:

server.stop()

Note: Only the threaded server can be stopped using this method. The non-threaded server will block the thread, so it cannot be stopped by calling the stop() method. You can stop the non-threaded server by pressing Ctrl+C in the terminal.

When using the command line, you can stop the server by pressing Ctrl+C in the terminal.

Command-Line Interface

You can get help on the command-line interface by running:

cryskura --help

This will show the available options:

  • -h, --help: Show help message and exit.
  • -u, --uPnP: Enable uPnP port forwarding.
  • -v, --version: Show program's version number and exit.
  • -b, --browser: Open the browser after starting the server.
  • -ba, --browserAddress: The address to open in the browser.
  • -w, --webMode: Enable web mode, which means only files can be accessed, not directories.
  • -f, --forcePort: Force to use the specified port even if it is already in use.
  • -t, --allowUpload: Allow file upload.
  • -r, --allowResume: Allow resume download.
  • -ar, --addRightClick: Add to right-click menu.
  • -rr, --removeRightClick: Remove from right-click menu.
  • -d PATH, --path PATH: The path to the directory to serve.
  • -n NAME, --name NAME: The name of the server.
  • -p PORT, --port PORT: The port to listen on.
  • -c CERTFILE, --certfile CERTFILE: The path to the certificate file.
  • -i INTERFACE, --interface INTERFACE: The interface to listen on.
  • -j HTTP_TO_HTTPS, --http_to_https HTTP_TO_HTTPS: Port to redirect HTTP requests to HTTPS.

Using as a Python Module

Custom Configuration

You can customize the server by providing different parameters:

from cryskura import Server
from cryskura.Services import FileService,PageService,RedirectService,APIService

# Create services
fs=FileService(r"/path/to/file","/Files",allowResume=True,allowUpload=True)
rs=RedirectService("/Redirect","https://www.google.com")
ps1=PageService(r"/path/to/html/example.com","/",host="example.com")
ps2=PageService(r"/path/to/html/default","/")

# Define the API function
def APIFunc(request, path, args, headers, content, method):
    """
    A sample API function for handling API requests.

    Parameters:
    - request: The HTTP request object.
    - path: The sub-path of the request URL after the API endpoint.
    - args: The query parameters from the URL as a dictionary.
    - headers: The headers from the request as a dictionary.
    - content: The body content of the request as bytes.
    - method: The HTTP method used (e.g., "GET", "POST").

    Returns:
    - code: An integer HTTP status code (e.g., 200 for success).
    - response_headers: A dictionary of headers to include in the response.
    - response_content: The body content to send in the response as bytes.
    """
    print(f"API {method} {path} {args}")
    # Process the request and generate a response
    code = 200  # HTTP status code
    response_headers = {"Content-Type": "text/plain"}  # Response headers
    response_content = b"API Call"  # Response body content
    return code, response_headers, response_content

# Create API service
api=APIService("/API",func=APIFunc)

# Start the server
server=Server(services=[fs,rs,api,ps1,ps2],certfile="/path/to/cert.pem",uPnP=True)
server.start()

This will start the server with the following services:

  • FileService: Serves files from /path/to/file at the /Files endpoint, allowing resumable downloads and file uploads.
  • RedirectService: Redirects requests from /Redirect to https://www.google.com.
  • PageService 1: Hosts web pages located in /path/to/html/example.com and serves them at the root endpoint / only when user requests with domain example.com.
  • PageService 2: Hosts default web pages located in /path/to/html/default and serves them at the root endpoint / for all other requests.
  • APIService: Handles API calls at the /API endpoint, printing request details and responding with a plain text message.

And with the following settings:

  • SSL Support: Uses the certificate file located at /path/to/cert.pem for SSL encryption.
  • uPnP Port Forwarding: Automatically forwards ports using uPnP.

Route Priority

If multiple services have conflicting routes, the priority is determined by the order in which the services are listed in the services parameter. The service listed first will have the highest priority, and so on.

For example:

from cryskura import Server
from cryskura.Services import FileService, PageService

fs = FileService(r"/path/to/files", "/files")
ps = PageService(r"/path/to/pages", "/")

server = Server(services=[fs,ps])
server.start()

In this case, FileService will have priority over PageService for routes that conflict between the two services. So if a request is made to /files/index.html, it will be handled by FileService and not PageService.

Authentication

To implement custom authentication, you need to define an authentication function and pass it to the service that requires authentication. The authentication function should accept four parameters: cookies, path, args, and operation. It should return True if the authentication is successful, and False otherwise.

Here is an example of how to implement custom authentication:

from cryskura import Server
from cryskura.Services import FileService

# Define authentication function
def AUTHFunc(cookies, path, args, operation):
    print(f"AUTH {operation} {path} {args}")
    if args.get('passwd') == "passwd" and operation == "GET":
        return True
    elif args.get('passwd') == "admin" and operation == "POST":
        return True
    return False

# Create a file service with authentication
fs = FileService(r"/path/to/files", "/files", allowResume=True, auth_func=AUTHFunc)

# Start the server
server = Server(services=[fs])
server.start()

In this example, the AUTHFunc function checks the passwd parameter in the request arguments to authenticate GET and POST requests. If the passwd parameter is passwd for GET requests or admin for POST requests, the authentication is successful. Otherwise, the authentication fails.

You can customize the AUTHFunc function to implement your own authentication logic, such as checking cookies, headers, or other request parameters.

Custom Services

To create a custom service, extend the BaseService class and implement the required methods:

from cryskura.Services import BaseService, Route

class MyService(BaseService):
    def __init__(self):
        routes = [Route("/myservice", ["GET"], "exact")]
        super().__init__(routes)

    def handle_GET(self, request, path, args):
        request.send_response(200)
        request.send_header("Content-Type", "text/plain")
        request.end_headers()
        request.wfile.write(b"Hello from MyService!")

Using the uPnP Client

CryskuraHTTP includes a built-in uPnP client to facilitate automatic port forwarding. This can be particularly useful when running the server behind a router or firewall.

Enabling uPnP

To enable uPnP port forwarding, you can use the --uPnP flag when starting the server from the command line:

cryskura --interface 0.0.0.0 --port 8080 --path /path/to/serve --uPnP

Using uPnP in Python

You can also enable uPnP port forwarding when starting the server using the Python API:

from cryskura import Server

server = Server(interface="0.0.0.0", port=8080, uPnP=True)
server.start()

Custom uPnP Configuration

The built-in uPnP client can be used independently for custom port forwarding needs. Here’s how you can use the uPnPClient class directly in your Python code:

Initializing the uPnP Client

First, you need to initialize the uPnPClient with the desired network interface:

from cryskura import uPnP

# Initialize uPnP client for a specific interface
upnp_client = uPnP(interface="0.0.0.0")
# Use 0.0.0.0 for all IPv4 interfaces

if upnp_client.available:
    print("uPnP client initialized successfully.")
else:
    print("uPnP client is not available.")

Adding a Port Mapping

To add a port mapping, use the add_port_mapping method:

if upnp_client.available:
    success, mappings = upnp_client.add_port_mapping(
        remote_port=8080, 
        local_port=8080, 
        protocol="TCP", 
        description="CryskuraHTTP Server"
    )
    if success:
        print("Port mapping added successfully.")
        for mapping in mappings:
            print(f"Service is available at {mapping[0]}:{mapping[1]}")
    else:
        print("Failed to add port mapping.")

This will add a port mapping for port 8080 on the remote device to port 8080 on the local device using the TCP protocol. The description is just a label for the mapping, which can be used to identify it later.

Removing All Port Mappings

To remove port mappings, use the remove_port_mapping method:

if upnp_client.available:
    upnp_client.remove_port_mapping()
    print("Port mapping removed.")

This will remove all port mappings that were added by the client. It's a good practice to remove port mappings when they are no longer needed. You can place this code in a cleanup section of your script or in an exception handler to ensure that the mappings are removed even if an error occurs. For example:

try:
    Your code here...
except Exception as exception:
    upnp_client.remove_port_mapping()
    raise exception

This will ensure that the port mappings are removed even if an exception occurs during the execution of your code.

Troubleshooting uPnP

If you encounter issues with uPnP, ensure that:

  • Your router supports uPnP and has it enabled.

  • The upnpclient library is installed. You can install it using:

    pip install upnpclient
    

    or install the cryskura package with the upnp extra:

    pip install cryskura[upnp]
    
  • The network interface specified is correct and accessible.

For more detailed information on the uPnPClient class and its methods, refer to the source code in the uPnP.py file.

License

This project is licensed under the MIT License. See the LICENSE file for details.

Contributing

Contributions are welcome! Please open an issue or submit a pull request.

Contact

For any questions or suggestions, please open an issue here on GitHub.


Enjoy using CryskuraHTTP!

CryskuraHTTP

CryskuraHTTP Logo

CryskuraHTTP 是一个用 Python 实现的轻量级、可定制的 HTTP(s) 服务器,支持基本的 HTTP(s) 功能,包括文件服务和错误处理,并支持自定义服务和鉴权。

特性

CryskuraHTTP 是 Python 内置 http.server 的扩展,具有很少的依赖。您可以利用它实现 Python HTTP 服务,而无需安装大型软件或库。它还可以用作文件共享工具,支持通过浏览器进行文件下载和上传,并可通过 Windows 右键菜单启动。

  • 可定制服务:通过扩展 BaseService 类轻松添加自定义服务。
  • 可定制 API 调用:使用 APIService 类定义自定义 API 调用。
  • 错误处理:通过 ErrorService 类实现可定制的错误处理。
  • 文件服务:通过 FileService 类从指定目录提供文件服务。
  • 文件上传:通过 FileService 类处理通过 POST 请求的文件上传。
  • 网页服务:通过 PageService 类提供网页服务,而不允许用户查看目录列表。
  • 可定制路由:使用 Route 类为您的服务定义自定义路由。
  • 可定制身份验证:为您的服务实现自定义身份验证。
  • 自动 uPnP 端口转发:使用 uPnP 自动转发端口。
  • 请求处理:处理 GET、POST、HEAD 请求。
  • 可续传下载:在提供文件服务时支持大文件的可续传下载。
  • 重定向:支持 301 和 308 重定向。
  • SSL 支持:通过提供证书文件可选启用 SSL。
  • 多线程服务器:支持多线程请求处理以提高性能。
  • 命令行界面:通过命令行运行服务器并进行自定义设置。
  • 右键支持:支持在 Windows 上通过右键菜单启动服务器。

该项目并非设计用于替代全规模、生产级 HTTP 服务器。它更适合小规模的 Web UI 开发或与 pywebviewqtwebengine 等工具一起使用。因此,不要期望它能处理数千个并发连接或具有负载均衡或缓存等高级功能。

要求

  • Python 3.x
  • psutil

安装

  1. 使用 pip 安装包:

    pip install cryskura
    
  2. 您也可以从 GitHub Releases 下载 whl 文件并使用 pip 安装:

    pip install cryskura-1.0-py3-none-any.whl
    
  3. 如果您想修改源代码,可以克隆仓库并手动安装:

    git clone https://github.com/HofNature/CryskuraHTTP.git
    cd CryskuraHTTP
    python setup.py install
    

快速开始

启动服务器

使用默认设置启动服务器:

from cryskura import Server
server = HTTPServer(interface="127.0.0.1", port=8080)
server.start()

这将在 localhost 上的端口 8080 启动服务器,并从当前目录提供文件服务。

或者,您可以从命令行运行服务器:

cryskura --interface 127.0.0.1 --port 8080 --path /path/to/serve

这将在 localhost 上的端口 8080 启动服务器,并从 /path/to/serve 提供文件服务。

注册到右键菜单

您可以通过运行以下命令将服务器添加到 Windows 的右键菜单:

cryskura --addRightClick # 您也可以使用 -ar 作为简写

注意:如果提供了 --interface--port--browser 等参数,当从右键菜单启动服务器时,将使用指定的设置。

如果您想从右键菜单中移除它,请运行:

cryskura --removeRightClick # 您也可以使用 -rr 作为简写

注意:此功能仅在 Windows 上可用。对于 Windows 11 24h2 及以上版本,如果启用了 Sudo,它将自动调用;否则,您需要手动以管理员权限运行。

停止服务器

使用 Python API 时,您可以通过调用 stop() 方法停止服务器:

server.stop()

注意:只有多线程服务器可以使用此方法停止。非多线程服务器将阻塞线程,因此无法通过调用 stop() 方法停止。您可以通过在终端中按 Ctrl+C 停止非多线程服务器。

使用命令行时,您可以通过在终端中按 Ctrl+C 停止服务器。

命令行界面

您可以通过运行以下命令获取命令行界面的帮助:

cryskura --help

这将显示可用选项:

  • -h, --help:显示帮助信息并退出。
  • -u, --uPnP:启用 uPnP 端口转发。
  • -v, --version:显示程序的版本号并退出。
  • -b, --browser:启动服务器后打开浏览器。
  • -ba, --browserAddress:浏览器打开的地址。
  • -w, --webMode:启用 Web 模式,这意味着只能访问文件,不能访问目录。
  • -f, --forcePort:强制使用指定端口,即使该端口已被占用。
  • -t, --allowUpload:允许文件上传。
  • -r, --allowResume:允许续传下载。
  • -ar, --addRightClick:添加到右键菜单。
  • -rr, --removeRightClick:从右键菜单中移除。
  • -d PATH, --path PATH:要提供服务的目录路径。
  • -n NAME, --name NAME:服务器的名称。
  • -p PORT, --port PORT:监听的端口。
  • -c CERTFILE, --certfile CERTFILE:证书文件的路径。
  • -i INTERFACE, --interface INTERFACE:监听的接口。
  • -j HTTP_TO_HTTPS, --http_to_https HTTP_TO_HTTPS:将 HTTP 请求重定向到 HTTPS 的端口。

作为 Python 模块使用

自定义配置

您可以通过提供不同的参数来自定义服务器:

from cryskura import Server
from cryskura.Services import FileService, PageService, RedirectService, APIService

# 创建服务
fs = FileService(r"/path/to/file", "/Files", allowResume=True, allowUpload=True)
rs = RedirectService("/Redirect", "https://www.google.com")
ps1 = PageService(r"/path/to/html/example.com", "/", host="example.com")
ps2 = PageService(r"/path/to/html/default", "/")

# 定义 API 函数
def APIFunc(request, path, args, headers, content, method):
    """
    用于处理 API 请求的示例函数。

    参数:
    - request:HTTP 请求对象。
    - path:API 端点之后的请求 URL 子路径。
    - args:URL 中的查询参数,字典形式。
    - headers:请求头,字典形式。
    - content:请求的主体内容,字节类型。
    - method:使用的 HTTP 方法(例如 "GET"、"POST")。

    返回:
    - code:整数类型的 HTTP 状态码(例如 200 表示成功)。
    - response_headers:要包含在响应中的头信息,字典形式。
    - response_content:响应的主体内容,字节类型。
    """
    # 为演示目的,我们将简单返回一个 200 OK 状态和一个纯文本消息。
    code = 200
    response_headers = {"Content-Type": "text/plain"}
    response_content = b"API 调用"
    return code, response_headers, response_content

# 创建 API 服务
api = APIService("/API", func=APIFunc)

# 启动服务器
server = Server(services=[fs, rs, api, ps1, ps2], certfile="/path/to/cert.pem", uPnP=True)
server.start()

这将启动具有以下服务的服务器:

  • FileService:在 /Files 端点提供 /path/to/file 的文件服务,允许续传下载和文件上传。
  • RedirectService:将 /Redirect 的请求重定向到 https://www.google.com
  • PageService 1:在根端点 / 提供 /path/to/html/example.com 的网页服务,仅当用户请求的域名为 example.com 时生效。
  • PageService 2:在根端点 / 提供 /path/to/html/default 的默认网页服务,用于所有其他请求。
  • APIService:在 /API 端点处理 API 调用,打印请求详情并响应纯文本消息。

以及以下设置:

  • SSL 支持:使用位于 /path/to/cert.pem 的证书文件进行 SSL 加密。
  • uPnP 端口转发:使用 uPnP 自动转发端口。

路由优先级

如果多个服务有冲突的路由,优先级由 services 参数中服务的顺序决定。列在前面的服务优先级最高,依此类推。

例如:

from cryskura import Server
from cryskura.Services import FileService, PageService

fs = FileService(r"/path/to/files", "/files")
ps = PageService(r"/path/to/pages", "/")

server = Server(services=[fs, ps])
server.start()

在这种情况下,对于 FileServicePageService 之间冲突的路由,FileService 将优先处理。因此,如果请求 /files/index.html,将由 FileService 处理,而不是 PageService

身份验证

要实现自定义身份验证,您需要定义一个身份验证函数并将其传递给需要身份验证的服务。身份验证函数应接受四个参数:cookiespathargsoperation。如果身份验证成功,应返回 True,否则返回 False

以下是如何实现自定义身份验证的示例:

from cryskura import Server
from cryskura.Services import FileService

# 定义身份验证函数
def AUTHFunc(cookies, path, args, operation):
    print(f"AUTH {operation} {path} {args}")
    if args.get('passwd') == "passwd" and operation == "GET":
        return True
    elif args.get('passwd') == "admin" and operation == "POST":
        return True
    return False

# 创建带有身份验证的文件服务
fs = FileService(r"/path/to/files", "/files", allowResume=True, auth_func=AUTHFunc)

# 启动服务器
server = Server(services=[fs])
server.start()

在此示例中,AUTHFunc 函数检查请求参数中的 passwd 参数以验证 GET 和 POST 请求。如果 passwd 参数为 GET 请求的 passwd 或 POST 请求的 admin,则身份验证成功。否则,身份验证失败。

您可以自定义 AUTHFunc 函数以实现自己的身份验证逻辑,例如检查 cookies、头信息或其他请求参数。

自定义服务

要创建自定义服务,请扩展 BaseService 类并实现所需的方法:

from cryskura.Services import BaseService, Route

class MyService(BaseService):
    def __init__(self):
        routes = [Route("/myservice", ["GET"], "exact")]
        super().__init__(routes)

    def handle_GET(self, request, path, args):
        request.send_response(200)
        request.send_header("Content-Type", "text/plain")
        request.end_headers()
        request.wfile.write(b"Hello from MyService!")

使用 uPnP 客户端

CryskuraHTTP 包含一个内置的 uPnP 客户端,以便自动端口转发。这在路由器或防火墙后运行服务器时特别有用。

启用 uPnP

要启用 uPnP 端口转发,您可以在从命令行启动服务器时使用 --uPnP 标志:

cryskura --interface 0.0.0.0 --port 8080 --path /path/to/serve --uPnP

在 Python 中使用 uPnP

您还可以在使用 Python API 启动服务器时启用 uPnP 端口转发:

from cryskura import Server

server = Server(interface="0.0.0.0", port=8080, uPnP=True)
server.start()

自定义 uPnP 配置

内置的 uPnP 客户端可以独立使用以满足自定义端口转发需求。以下是如何在 Python 代码中直接使用 uPnPClient 类:

初始化 uPnP 客户端

首先,您需要使用所需的网络接口初始化 uPnPClient

from cryskura import uPnP

# 为特定接口初始化 uPnP 客户端
upnp_client = uPnP(interface="0.0.0.0")
# 使用 0.0.0.0 表示所有 IPv4 接口

if upnp_client.available:
    print("uPnP 客户端初始化成功。")
else:
    print("uPnP 客户端不可用。")

添加端口映射

要添加端口映射,请使用 add_port_mapping 方法:

if upnp_client.available:
    success, mappings = upnp_client.add_port_mapping(
        remote_port=8080, 
        description="CryskuraHTTP Server"
    )
    if success:
        print("端口映射添加成功。")
    else:
        print("添加端口映射失败。")

这将在远程设备的端口 8080 上添加到本地设备端口 8080 的端口映射,使用 TCP 协议。描述只是映射的标签,可以用于以后识别它。

移除所有端口映射

要移除端口映射,请使用 remove_port_mapping 方法:

if upnp_client.available:
    upnp_client.remove_port_mapping()
    print("端口映射已移除。")

这将移除客户端添加的所有端口映射。最好在不再需要时移除端口映射。您可以将此代码放在脚本的清理部分或异常处理程序中,以确保即使发生错误也能移除映射。例如:

try:
    # 您的代码...
except Exception as exception:
    upnp_client.remove_port_mapping()
    raise exception

这将确保即使在代码执行期间发生异常,也能移除端口映射。

uPnP 故障排除

如果遇到 uPnP 问题,请确保:

  • 您的路由器 支持 uPnP 并且已 启用

  • 安装了 upnpclient 库。您可以使用以下命令安装它:

    pip install upnpclient
    
  • 指定的网络接口是正确且可访问的。

有关 uPnPClient 类及其方法的详细信息,请参阅 uPnP.py 文件中的源代码。

许可证

本项目采用 MIT 许可证。有关详细信息,请参阅 LICENSE 文件。

贡献

欢迎贡献!请提交问题或拉取请求。

联系方式

如有任何问题或建议,请在 GitHub 上提交问题。


享受使用 CryskuraHTTP 吧!

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

cryskura-1.0b13.tar.gz (175.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cryskura-1.0b13-py3-none-any.whl (169.8 kB view details)

Uploaded Python 3

File details

Details for the file cryskura-1.0b13.tar.gz.

File metadata

  • Download URL: cryskura-1.0b13.tar.gz
  • Upload date:
  • Size: 175.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.11

File hashes

Hashes for cryskura-1.0b13.tar.gz
Algorithm Hash digest
SHA256 903a78d8c587d1e1cc58411bfc4360d1bec2c852da8b72c242dccaccbed42cf1
MD5 1d5eb7cd4e976a990989a6f5c1a14d8f
BLAKE2b-256 71c0ea87afade4cb28c1a0044fd045a4a8b8acef801195377a741e5f1580f81a

See more details on using hashes here.

File details

Details for the file cryskura-1.0b13-py3-none-any.whl.

File metadata

  • Download URL: cryskura-1.0b13-py3-none-any.whl
  • Upload date:
  • Size: 169.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.11

File hashes

Hashes for cryskura-1.0b13-py3-none-any.whl
Algorithm Hash digest
SHA256 918e23bd0043d0b8eaf8b0af7641a9197c5cda1c7c182d1b6b27a32738cce4e0
MD5 06e87b12a37a542bd130b44571e84b1a
BLAKE2b-256 1e314645b6864523c9fe47bc578c6c615d520efc89dcc3f800e1cc8addcf4cd0

See more details on using hashes here.

Supported by

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