A lightweight Flask utility library providing validation, authentication decorators, and database helpers.
Project description
๐ ๏ธ Ol_Utills
A lightweight Flask utility library for validation, authentication, security, and database helpers.
โจ Features
- Input Validation โ Password, email, and phone number validation using battle-tested regex patterns.
- Auth Decorators โ Drop-in
@login_requiredand@admin_requireddecorators for Flask routes. - Response Helpers โ Standardized
success_responseanderror_responsefor consistent API output. - Security โ Rate limiting (Redis-backed), input/file sanitization, bcrypt password hashing & verification.
- Database Helpers โ Quick-connect utilities for SQLite, PostgreSQL, and Redis.
- Zero Config โ Works out of the box with any Flask app.
๐๏ธ Architecture Overview
graph LR
A["๐ ๏ธ Ol_Utills"] --> B["๐ val"]
A --> C["๐ก๏ธ req"]
A --> D["๐ฆ res"]
A --> E["๐๏ธ Connections"]
A --> F["๐ security"]
B --> B1["chk_p โ Password"]
B --> B2["chk_e โ Email"]
B --> B3["chk_ph โ Phone"]
C --> C1["@login_required"]
C --> C2["@admin_required"]
D --> D1["success_response"]
D --> D2["error_response"]
E --> E1["SQLite"]
E --> E2["PostgreSQL"]
E --> E3["Redis"]
F --> F1["@rate_limit"]
F --> F2["Sanitizes"]
F --> F3["hash"]
F --> F4["verify"]
style A fill:#4f46e5,stroke:#4338ca,color:#fff
style B fill:#0891b2,stroke:#0e7490,color:#fff
style C fill:#059669,stroke:#047857,color:#fff
style D fill:#d97706,stroke:#b45309,color:#fff
style E fill:#7c3aed,stroke:#6d28d9,color:#fff
style F fill:#e11d48,stroke:#be123c,color:#fff
๐ฆ Installation
pip install ol-utills flask
Requirements
| Dependency | Purpose |
|---|---|
flask |
Session management & JSON responses |
psycopg2 |
PostgreSQL connectivity |
redis |
Redis connectivity & rate limiting |
bcrypt |
Secure password hashing |
Note:
sqlite3andreare part of the Python standard library and do not need to be installed.
Supported Python Versions
- Python 3.8 and above
๐ Quick Start
from Ol_Utills import val, req, res, Connections, security
# Validate an email
if val.chk_e("user@example.com"):
print("Valid email!")
# Connect to a SQLite database
conn, db = Connections.sqlite("app.db")
db.execute("SELECT * FROM users")
# Hash a password
hashed = security.hash("MySecureP@ss1")
print(security.verify("MySecureP@ss1", hashed)) # True
๐ Detailed Documentation
Table of Contents
- val โ Validation
- req โ Authentication Decorators
- res โ Response Helpers
- Connections โ Database Connections
- security โ Security Utilities
- Full Flask App Example
val โ Validation
The val class provides static methods for validating common user inputs using regular expressions. All methods return True on success and None on failure, making them easy to use in conditional checks.
flowchart LR
Input["๐ฅ User Input"] --> Val{"val method"}
Val -->|"chk_p"| P["Password Regex"]
Val -->|"chk_e"| E["Email Regex"]
Val -->|"chk_ph"| Ph["Phone Regex"]
P --> Result{"Match?"}
E --> Result
Ph --> Result
Result -->|"โ
Yes"| True["Returns True"]
Result -->|"โ No"| None["Returns None"]
style Input fill:#f8fafc,stroke:#94a3b8,color:#334155
style True fill:#22c55e,stroke:#16a34a,color:#fff
style None fill:#ef4444,stroke:#dc2626,color:#fff
val.chk_p(password)
Validates password strength against a robust regex pattern.
| Details | |
|---|---|
| Parameter | password (str) โ The password string to validate |
| Returns | True if valid, None if invalid |
Password Rules:
The password must satisfy all of the following criteria:
- โ Minimum 7 characters long (6 + 1 trailing non-whitespace)
- โ
At least 1 uppercase letter (
A-Z) - โ
At least 1 lowercase letter (
a-z) - โ
At least 1 digit (
0-9) - โ Must not contain whitespace
- โ The last character must be a non-whitespace character
Note: Special characters (e.g.
@,#,!) are allowed but not required.
Examples:
from Ol_Utills import val
# โ
Valid passwords
val.chk_p("MyP@ss1234") # True โ uppercase, lowercase, digit, special char
val.chk_p("Hello1x") # True โ meets all minimum criteria
val.chk_p("Abcdef1") # True โ exactly 7 chars, has upper, lower, digit
# โ Invalid passwords
val.chk_p("weak") # None โ too short, no uppercase, no digit
val.chk_p("alllowercase1") # None โ no uppercase letter
val.chk_p("ALLUPPERCASE1") # None โ no lowercase letter
val.chk_p("NoDigits!") # None โ no digit
val.chk_p("Ab1") # None โ too short
Usage in a Flask route:
from flask import Flask, request, jsonify
from Ol_Utills import val
app = Flask(__name__)
@app.route('/register', methods=['POST'])
def register():
password = request.form.get('password')
if not val.chk_p(password):
return jsonify({
"error": "Password must be 7+ chars with at least 1 uppercase, 1 lowercase, and 1 digit."
}), 400
# Proceed with registration...
return jsonify({"message": "Registration successful"}), 201
val.chk_e(email)
Validates an email address against the RFC 2822 specification using a comprehensive regex pattern.
| Details | |
|---|---|
| Parameter | email (str) โ The email address string to validate |
| Returns | True if valid, None if invalid |
Validation Covers:
- โ
Standard emails:
user@example.com - โ
Subdomains:
user@mail.example.com - โ
Plus addressing:
user+tag@example.com - โ
Dots in local part:
first.last@example.com - โ
Quoted strings:
"unusual@chars"@example.com - โ Missing
@symbol - โ Missing domain
- โ Spaces in unquoted local parts
- โ Control characters
Examples:
from Ol_Utills import val
# โ
Valid emails
val.chk_e("user@example.com") # True
val.chk_e("first.last@company.co.uk") # True
val.chk_e("user+filter@gmail.com") # True
val.chk_e("admin@192.168.1.1") # True
# โ Invalid emails
val.chk_e("not-an-email") # None โ no @ symbol
val.chk_e("@missing-local.com") # None โ no local part
val.chk_e("spaces in@email.com") # None โ spaces not allowed
val.chk_e("") # None โ empty string
val.chk_ph(phone)
Validates international phone numbers.
| Details | |
|---|---|
| Parameter | phone (str) โ The phone number string to validate |
| Returns | True if valid, None if invalid |
Supported Formats:
- โ
International:
+1-555-555-5555 - โ
With parentheses:
(555) 555-5555 - โ
With dots:
555.555.5555 - โ
With spaces:
+44 20 7946 0958 - โ
Plain digits:
5555555555
Examples:
from Ol_Utills import val
val.chk_ph("+1-800-555-0199") # True
val.chk_ph("(555) 123-4567") # True
val.chk_ph("+44 20 7946 0958") # True
req โ Authentication Decorators
The req class provides Flask route decorators for session-based authentication. These decorators wrap your view functions and check the Flask session object before allowing access.
How It Works:
flowchart TD
A["๐ Client Request"] --> B["Flask Route"]
B --> C{"Decorator Check"}
C -->|"@login_required"| D{"session logged == True?"}
C -->|"@admin_required"| E{"session admin == True?"}
D -->|"โ
Yes"| F["โ
Execute View Function"]
D -->|"โ No"| G["๐ซ Return 401 error_response"]
E -->|"โ
Yes"| F
E -->|"โ No"| G
F --> H["๐ค Return Response to Client"]
G --> H
style A fill:#f8fafc,stroke:#94a3b8,color:#334155
style F fill:#22c55e,stroke:#16a34a,color:#fff
style G fill:#ef4444,stroke:#dc2626,color:#fff
style H fill:#3b82f6,stroke:#2563eb,color:#fff
@req.login_required
Restricts a Flask route to authenticated (logged-in) users only.
| Details | |
|---|---|
| Session Key | session['logged'] |
| Required Value | True (boolean) |
| On Success | Executes the decorated view function normally |
| On Failure | Returns res.error_response('Unauthorized', 401) |
Prerequisites:
You must set session['logged'] = True somewhere in your login logic (e.g., after verifying credentials).
Example:
from flask import Flask, session, request, jsonify
from Ol_Utills import req
app = Flask(__name__)
app.secret_key = 'your-secret-key'
# Login route โ sets session
@app.route('/login', methods=['POST'])
def login():
username = request.form.get('username')
password = request.form.get('password')
# ... verify credentials against database ...
session['logged'] = True # โ Required for @login_required
session['username'] = username # โ Optional: store user info
return jsonify({"message": "Logged in successfully"})
# Protected route โ requires login
@app.route('/dashboard')
@req.login_required
def dashboard():
return jsonify({"message": "Welcome to your dashboard"})
# Logout route โ clears session
@app.route('/logout')
def logout():
session.pop('logged', None)
return jsonify({"message": "Logged out"})
Behavior:
| Scenario | session['logged'] |
Result |
|---|---|---|
| User is logged in | True |
View function runs normally |
| User is not logged in | Missing or False |
Returns error_response('Unauthorized', 401) |
| Session expired | Missing | Returns error_response('Unauthorized', 401) |
@req.admin_required
Restricts a Flask route to admin users only. Works the same as @login_required but checks a different session key.
| Details | |
|---|---|
| Session Key | session['admin'] |
| Required Value | True (boolean) |
| On Success | Executes the decorated view function normally |
| On Failure | Returns res.error_response('Unauthorized', 401) |
Example:
# Admin login โ sets admin session
@app.route('/admin/login', methods=['POST'])
def admin_login():
# ... verify admin credentials ...
session['logged'] = True # for general auth
session['admin'] = True # โ Required for @admin_required
return jsonify({"message": "Admin logged in"})
# Admin-only route
@app.route('/admin/users')
@req.admin_required
def manage_users():
return jsonify({"users": ["user1", "user2", "user3"]})
Stacking Decorators:
You can combine both decorators for routes that require login and admin access:
@app.route('/admin/settings')
@req.login_required
@req.admin_required
def admin_settings():
return jsonify({"settings": "..."})
Tip: When stacking,
@req.login_requiredshould be the outermost decorator (listed first) so the login check runs before the admin check.
res โ Response Helpers
The res class provides utilities for building standardized JSON API responses, ensuring a consistent format across all your endpoints.
res.success_response(data)
Returns a standardized success JSON response with HTTP status 200.
| Details | |
|---|---|
| Parameter | data (any) โ The data payload to include |
| Returns | (jsonify({'data': data}), 200) โ Flask response tuple |
Example:
from Ol_Utills import res
# In a Flask route
@app.route('/users')
def get_users():
users = [{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}]
return res.success_response(users)
# Response: {"data": [{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}]}, 200
res.error_response(message, code)
Returns a standardized error JSON response with a custom HTTP status code.
| Details | |
|---|---|
| Parameters | message (str) โ Error message to return |
code (int) โ HTTP status code (e.g. 400, 404, 500) |
|
| Returns | (jsonify({'error': message}), code) โ Flask response tuple |
Example:
from Ol_Utills import res
@app.route('/users/<int:user_id>')
def get_user(user_id):
user = find_user(user_id)
if not user:
return res.error_response("User not found", 404)
# Response: {"error": "User not found"}, 404
return res.success_response(user)
Connections โ Database Connections
The Connections class provides quick-connect helper functions for database setup. Each method opens a connection and returns a (connection, cursor) tuple.
flowchart LR
App["๐ Flask App"] --> DB{"Connections helper"}
DB -->|".sqlite"| SQ["๐ SQLite File"]
DB -->|".postgresql"| PG["๐ PostgreSQL Server"]
DB -->|".C_redis"| RD["๐ด Redis Server"]
SQ --> SQC["sqlite3.connect"]
PG --> PGC["psycopg2.connect"]
RD --> RDC["redis.Redis"]
SQC --> Tuple["๐ (conn, cursor)"]
PGC --> Tuple
RDC --> Client["๐ Redis client"]
Tuple --> Ops["execute / fetchall / fetchone / commit"]
Client --> ROps["get / set / incr / expire"]
style App fill:#f8fafc,stroke:#94a3b8,color:#334155
style SQ fill:#0891b2,stroke:#0e7490,color:#fff
style PG fill:#4f46e5,stroke:#4338ca,color:#fff
style RD fill:#dc2626,stroke:#b91c1c,color:#fff
style Tuple fill:#22c55e,stroke:#16a34a,color:#fff
style Client fill:#22c55e,stroke:#16a34a,color:#fff
Important:
Connections.sqlite()andConnections.postgresql()now return a (connection, cursor) tuple instead of just a cursor. Useconnforcommit()/close(), anddbfor queries.
Connections.sqlite(database)
Opens a connection to a SQLite database file and returns a (connection, cursor) tuple.
| Details | |
|---|---|
| Parameter | database (str) โ Path to the SQLite database file. If the file doesn't exist, SQLite will create it automatically. |
| Returns | (sqlite3.Connection, sqlite3.Cursor) โ A tuple of connection and cursor objects |
Examples:
from Ol_Utills import Connections
# Connect to (or create) a database
conn, db = Connections.sqlite("app.db")
# Create a table
db.execute("""
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT NOT NULL UNIQUE,
email TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
""")
conn.commit() # Use conn for commit
# Insert a record
db.execute(
"INSERT INTO users (username, email) VALUES (?, ?)",
("john_doe", "john@example.com")
)
conn.commit()
# Query records
db.execute("SELECT * FROM users")
users = db.fetchall()
for user in users:
print(user)
# Close when done
conn.close()
Connections.postgresql(database, user, password, host)
Opens a connection to a PostgreSQL database and returns a (connection, cursor) tuple.
| Details | |
|---|---|
| Parameters | |
database (str) |
Name of the PostgreSQL database |
user (str) |
Database username |
password (str) |
Database password |
host (str) |
Database host address (e.g. "localhost", "db.example.com") |
| Returns | (psycopg2.Connection, psycopg2.Cursor) โ A tuple of connection and cursor objects |
| Requires | psycopg2 package (pip install psycopg2-binary) |
Examples:
from Ol_Utills import Connections
# Connect to PostgreSQL
conn, db = Connections.postgresql(
database="myapp",
user="admin",
password="secure_password",
host="localhost"
)
# Create a table
db.execute("""
CREATE TABLE IF NOT EXISTS products (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
price DECIMAL(10, 2),
in_stock BOOLEAN DEFAULT TRUE
)
""")
conn.commit()
# Insert a record
db.execute(
"INSERT INTO products (name, price) VALUES (%s, %s)",
("Widget", 19.99)
)
conn.commit()
# Query records
db.execute("SELECT * FROM products WHERE in_stock = %s", (True,))
products = db.fetchall()
Important: PostgreSQL uses
%sfor parameter placeholders, while SQLite uses?.
Connections.C_redis(host, port, password, socket_timeout)
Creates a connection to a Redis server and returns a Redis client instance.
| Details | |
|---|---|
| Parameters | |
host (str) |
Redis server host (default: "localhost") |
port (int) |
Redis server port (default: 6379) |
password (str or None) |
Redis password (default: None) |
socket_timeout (int) |
Connection timeout in seconds (default: 5) |
| Returns | redis.Redis client instance (with decode_responses=True) |
| Requires | redis package (pip install redis) |
Examples:
from Ol_Utills import Connections
# Connect to Redis with defaults
r = Connections.C_redis()
# Connect with custom settings
r = Connections.C_redis(
host="redis.example.com",
port=6380,
password="my_redis_pass",
socket_timeout=10
)
# Use the Redis client
r.set("greeting", "hello")
print(r.get("greeting")) # "hello"
r.incr("counter")
print(r.get("counter")) # "1"
security โ Security Utilities
The security class provides essential security tools: Redis-backed rate limiting, input/file sanitization, and bcrypt password hashing with verification.
graph LR
S["๐ security"] --> RL["@rate_limit"]
S --> SN["Sanitizes"]
S --> HS["hash"]
S --> VR["verify"]
RL --> RL1["Redis-backed"]
RL --> RL2["Per-IP tracking"]
RL --> RL3["429 on exceed"]
SN --> SN1["File sanitization"]
SN --> SN2["Text sanitization"]
HS --> HS1["bcrypt hashing"]
VR --> VR1["bcrypt verification"]
style S fill:#e11d48,stroke:#be123c,color:#fff
style RL fill:#f97316,stroke:#ea580c,color:#fff
style SN fill:#8b5cf6,stroke:#7c3aed,color:#fff
style HS fill:#0891b2,stroke:#0e7490,color:#fff
style VR fill:#059669,stroke:#047857,color:#fff
@security.rate_limit(max_requests, window_seconds, r)
A decorator that adds Redis-backed rate limiting to Flask routes. Tracks requests per client IP address.
| Details | |
|---|---|
| Parameters | |
max_requests (int) |
Maximum allowed requests per window (default: 20) |
window_seconds (int) |
Time window in seconds (default: 60) |
r (Redis client or None) |
Optional Redis client; auto-connects via Connections.C_redis() if None |
| On Limit Exceeded | Returns 429 Too Many Requests JSON response |
| Requires | A running Redis server |
Example:
from flask import Flask
from Ol_Utills import security, Connections
app = Flask(__name__)
# Using default settings (20 requests per 60 seconds, auto Redis connection)
@app.route('/api/data')
@security.rate_limit()
def get_data():
return {"data": "some data"}
# Custom limits with explicit Redis connection
r = Connections.C_redis(host="redis.example.com")
@app.route('/api/sensitive')
@security.rate_limit(max_requests=5, window_seconds=30, r=r)
def sensitive_endpoint():
return {"data": "sensitive data"}
How It Works:
| Step | Action |
|---|---|
| 1 | Client IP is extracted from the request |
| 2 | A Redis counter for that IP is incremented |
| 3 | On first request, a TTL (time-to-live) is set on the key |
| 4 | If the counter exceeds max_requests, a 429 response is returned |
| 5 | After the window expires, the counter resets automatically |
Note: If Redis is unavailable, the decorator gracefully falls through and allows the request.
security.Sanitizes(type, file, text)
Strips HTML tags from files or text input to prevent XSS and injection attacks.
| Details | |
|---|---|
| Parameters | |
type (str) |
"file" to sanitize a file, or any other value for text sanitization |
file (str or None) |
File path to sanitize (required when type="file") |
text (str) |
Text input to sanitize (default: "text") |
| Returns | File path (str) if file mode, sanitized text (str) if text mode |
Examples:
from Ol_Utills import security
# Sanitize text input
clean = security.Sanitizes('text', text='Hello <script>alert("xss")</script> World')
print(clean) # "Hello alert("xss") World"
# Sanitize a file in-place
security.Sanitizes('file', file='user_upload.csv')
# Removes all HTML tags from the file content and rewrites it
security.hash(password)
Hashes a password using bcrypt with an auto-generated salt.
| Details | |
|---|---|
| Parameter | password (str) โ The plaintext password to hash |
| Returns | bytes โ The bcrypt hashed password |
| Requires | bcrypt package (pip install bcrypt) |
Example:
from Ol_Utills import security
hashed = security.hash("MySecureP@ss1")
print(hashed) # b'$2b$12$...'
# Store `hashed` in your database
security.verify(password, hashed)
Verifies a plaintext password against a bcrypt hash.
| Details | |
|---|---|
| Parameters | password (str) โ The plaintext password to check |
hashed (bytes) โ The bcrypt hash to compare against |
|
| Returns | True if the password matches, False otherwise |
| Requires | bcrypt package (pip install bcrypt) |
Example:
from Ol_Utills import security
hashed = security.hash("MySecureP@ss1")
# โ
Correct password
security.verify("MySecureP@ss1", hashed) # True
# โ Wrong password
security.verify("WrongPassword1", hashed) # False
Full Registration/Login Flow:
from flask import Flask, request, jsonify
from Ol_Utills import security, Connections, val
app = Flask(__name__)
conn, db = Connections.sqlite("app.db")
@app.route('/register', methods=['POST'])
def register():
password = request.form.get('password')
if not val.chk_p(password):
return jsonify({"error": "Weak password"}), 400
hashed = security.hash(password)
db.execute("INSERT INTO users (password) VALUES (?)", (hashed,))
conn.commit()
return jsonify({"message": "Registered"}), 201
@app.route('/login', methods=['POST'])
def login():
password = request.form.get('password')
db.execute("SELECT password FROM users WHERE id = 1")
stored_hash = db.fetchone()[0]
if security.verify(password, stored_hash):
return jsonify({"message": "Login successful"})
return jsonify({"error": "Invalid credentials"}), 401
๐ง Full Flask App Example
A complete example showing all library features working together:
sequenceDiagram
participant C as ๐ Client
participant F as ๐ Flask App
participant V as ๐ val
participant D as ๐๏ธ Connections
participant S as ๐ก๏ธ session
participant R as ๐ด Redis
participant B as ๐ bcrypt
Note over C,B: Registration Flow
C->>F: POST /register
F->>V: val.chk_e(email)
V-->>F: True / None
F->>V: val.chk_p(password)
V-->>F: True / None
F->>B: security.hash(password)
B-->>F: hashed password
F->>D: Connections.sqlite("app.db")
D-->>F: (conn, cursor)
F->>D: INSERT INTO users
F-->>C: 201 Created
Note over C,B: Login Flow
C->>F: POST /login
F->>R: rate_limit check
R-->>F: allowed โ
F->>D: SELECT FROM users
D-->>F: user record
F->>B: security.verify(password, hash)
B-->>F: True โ
F->>S: session["logged"] = True
F-->>C: Login successful
Note over C,B: Protected Route
C->>F: GET /dashboard
F->>R: rate_limit check
R-->>F: allowed โ
F->>S: Check session["logged"]
S-->>F: True โ
F-->>C: Dashboard data
from flask import Flask, session, request, jsonify
from Ol_Utills import val, req, res, Connections, security
app = Flask(__name__)
app.secret_key = 'your-secret-key-here'
# Initialize database
conn, db = Connections.sqlite("app.db")
db.execute("""
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT UNIQUE,
email TEXT,
password BLOB,
is_admin BOOLEAN DEFAULT 0
)
""")
conn.commit()
@app.route('/register', methods=['POST'])
def register():
email = request.form.get('email')
password = request.form.get('password')
username = request.form.get('username')
# Validate email
if not val.chk_e(email):
return res.error_response("Invalid email format", 400)
# Validate password strength
if not val.chk_p(password):
return res.error_response(
"Password must be 7+ chars with uppercase, lowercase, and a digit", 400
)
# Hash password before storing
hashed = security.hash(password)
# Insert user into database
try:
db.execute(
"INSERT INTO users (username, email, password) VALUES (?, ?, ?)",
(username, email, hashed)
)
conn.commit()
except Exception as e:
return res.error_response(str(e), 500)
return res.success_response({"message": "User registered successfully"})
@app.route('/login', methods=['POST'])
@security.rate_limit(max_requests=10, window_seconds=60)
def login():
username = request.form.get('username')
password = request.form.get('password')
db.execute("SELECT * FROM users WHERE username = ?", (username,))
user = db.fetchone()
if user and security.verify(password, user[3]):
session['logged'] = True
session['username'] = username
if user[4]: # is_admin column
session['admin'] = True
return res.success_response({"message": "Login successful"})
return res.error_response("Invalid credentials", 401)
@app.route('/dashboard')
@req.login_required
def dashboard():
return res.success_response({
"message": f"Welcome, {session.get('username')}!",
"role": "admin" if session.get('admin') else "user"
})
@app.route('/admin/panel')
@req.admin_required
def admin_panel():
db.execute("SELECT id, username, email FROM users")
users = db.fetchall()
return res.success_response({"users": users})
@app.route('/logout')
def logout():
session.clear()
return res.success_response({"message": "Logged out"})
if __name__ == '__main__':
app.run(debug=True)
๐งช Running Tests
cd tests
python test.py
๐ค Contributing
Contributions are welcome! Here's how to get started:
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
๐ License
Distributed under the MIT License. See LICENSE for more information.
Made with โค๏ธ by OverLimit (OL)
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ol_utills-0.7.1.tar.gz.
File metadata
- Download URL: ol_utills-0.7.1.tar.gz
- Upload date:
- Size: 28.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0b01677a8c52f4af4e3fbb63343df35c24c63d411575dc94f4a02736cd0d9a7e
|
|
| MD5 |
45ec52afce2b7e5df789d47bd2559672
|
|
| BLAKE2b-256 |
2166d469c7dd81141abaeff2b1219846f7175fc1912c837b4562278b28864dca
|
Provenance
The following attestation bundles were made for ol_utills-0.7.1.tar.gz:
Publisher:
publish.yml on OverLimit-OL/Ol_Utills
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ol_utills-0.7.1.tar.gz -
Subject digest:
0b01677a8c52f4af4e3fbb63343df35c24c63d411575dc94f4a02736cd0d9a7e - Sigstore transparency entry: 1182773436
- Sigstore integration time:
-
Permalink:
OverLimit-OL/Ol_Utills@de5e2201d351aa3df1a42cd5dc8156a204f0a237 -
Branch / Tag:
refs/tags/v0.7.0 - Owner: https://github.com/OverLimit-OL
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@de5e2201d351aa3df1a42cd5dc8156a204f0a237 -
Trigger Event:
release
-
Statement type:
File details
Details for the file ol_utills-0.7.1-py3-none-any.whl.
File metadata
- Download URL: ol_utills-0.7.1-py3-none-any.whl
- Upload date:
- Size: 13.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cba5f43ac95cd39bed61ad7e7efac2bea4a7cca3df973ef60cc02f1e28228998
|
|
| MD5 |
1ba216aeeb71e920ddbcd7169ad6b33f
|
|
| BLAKE2b-256 |
3d53f1e21c0cdc81a5c76d7bc4368a4adb5db8adae772bb15752da0650168c5a
|
Provenance
The following attestation bundles were made for ol_utills-0.7.1-py3-none-any.whl:
Publisher:
publish.yml on OverLimit-OL/Ol_Utills
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ol_utills-0.7.1-py3-none-any.whl -
Subject digest:
cba5f43ac95cd39bed61ad7e7efac2bea4a7cca3df973ef60cc02f1e28228998 - Sigstore transparency entry: 1182773447
- Sigstore integration time:
-
Permalink:
OverLimit-OL/Ol_Utills@de5e2201d351aa3df1a42cd5dc8156a204f0a237 -
Branch / Tag:
refs/tags/v0.7.0 - Owner: https://github.com/OverLimit-OL
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@de5e2201d351aa3df1a42cd5dc8156a204f0a237 -
Trigger Event:
release
-
Statement type: