A lightweight Flask utility library providing validation, authentication decorators, and database helpers.
Project description
๐ ๏ธ Ol_Utills
A lightweight Flask utility library for validation, authentication, 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. - Database Helpers โ Quick-connect utilities for SQLite and PostgreSQL.
- 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["๐๏ธ database"]
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"]
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
๐ฆ Installation
pip install ol-utills
Requirements
| Dependency | Purpose |
|---|---|
flask |
Session management & JSON responses |
psycopg2 |
PostgreSQL connectivity |
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, database
# Validate an email
if val.chk_e("user@example.com"):
print("Valid email!")
# Connect to a SQLite database
db = database.sqlite("app.db")
db.execute("SELECT * FROM users")
๐ Detailed Documentation
Table of Contents
- val โ Validation
- req โ Authentication Decorators
- res โ Response Helpers
- database โ Database Connections
- 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 empty jsonify 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 an empty JSON response via jsonify() |
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 empty jsonify() response |
| Session expired | Missing | Returns empty jsonify() response |
@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 an empty JSON response via jsonify() |
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
๐ Coming Soon โ This module is under active development.
The res class will provide utilities for building standardized JSON API responses.
| Method | Description | Status |
|---|---|---|
res.success_response(data) |
Returns a standardized success JSON response | ๐ Planned |
res.error_response(message, code) |
Returns a standardized error JSON response | ๐ Planned |
Planned usage:
from Ol_Utills import res
# Success response
return res.success_response({"user": "john"})
# Expected: {"status": "success", "data": {"user": "john"}}
# Error response
return res.error_response("Not found", 404)
# Expected: {"status": "error", "message": "Not found"}, 404
database โ Database Connections
The database class provides quick-connect helper functions for database setup. Each method opens a connection and returns a cursor object ready for executing queries.
flowchart LR
App["๐ Flask App"] --> DB{"database helper"}
DB -->|".sqlite"| SQ["๐ SQLite File"]
DB -->|".postgresql"| PG["๐ PostgreSQL Server"]
SQ --> SQC["sqlite3.connect"]
PG --> PGC["psycopg2.connect"]
SQC --> Cursor["๐ Cursor"]
PGC --> Cursor
Cursor --> Ops["execute / fetchall / fetchone"]
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 Cursor fill:#22c55e,stroke:#16a34a,color:#fff
database.sqlite(database)
Opens a connection to a SQLite database file and returns a cursor.
| Details | |
|---|---|
| Parameter | database (str) โ Path to the SQLite database file. If the file doesn't exist, SQLite will create it automatically. |
| Returns | sqlite3.Cursor โ A cursor object for executing SQL queries |
Examples:
from Ol_Utills import database
# Connect to (or create) a database
db = database.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
)
""")
# Insert a record
db.execute(
"INSERT INTO users (username, email) VALUES (?, ?)",
("john_doe", "john@example.com")
)
db.connection.commit() # Don't forget to commit!
# Query records
db.execute("SELECT * FROM users")
users = db.fetchall()
for user in users:
print(user)
# Query a single record
db.execute("SELECT * FROM users WHERE username = ?", ("john_doe",))
user = db.fetchone()
Use with Flask:
from flask import Flask, g
from Ol_Utills import database
app = Flask(__name__)
def get_db():
if 'db' not in g:
g.db = database.sqlite("app.db")
return g.db
@app.route('/users')
def list_users():
db = get_db()
db.execute("SELECT * FROM users")
return jsonify(db.fetchall())
database.postgresql(database, user, password, host)
Opens a connection to a PostgreSQL database and returns a cursor.
| 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.cursor โ A cursor object for executing SQL queries |
| Requires | psycopg2 package (pip install psycopg2-binary) |
Examples:
from Ol_Utills import database
# Connect to PostgreSQL
db = database.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
)
""")
db.connection.commit()
# Insert a record
db.execute(
"INSERT INTO products (name, price) VALUES (%s, %s)",
("Widget", 19.99)
)
db.connection.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?.
๐ง 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 ๐๏ธ database
participant S as ๐ก๏ธ session
Note over C,S: 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->>D: database.sqlite("app.db")
D-->>F: cursor
F->>D: INSERT INTO users
F-->>C: 201 Created
Note over C,S: Login Flow
C->>F: POST /login
F->>D: SELECT FROM users
D-->>F: user record
F->>S: session["logged"] = True
F-->>C: Login successful
Note over C,S: Protected Route
C->>F: GET /dashboard
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, database
app = Flask(__name__)
app.secret_key = 'your-secret-key-here'
# Initialize database
db = database.sqlite("app.db")
db.execute("""
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT UNIQUE,
email TEXT,
password TEXT,
is_admin BOOLEAN DEFAULT 0
)
""")
db.connection.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 jsonify({"error": "Invalid email format"}), 400
# Validate password strength
if not val.chk_p(password):
return jsonify({
"error": "Password must be 7+ chars with uppercase, lowercase, and a digit"
}), 400
# Insert user into database
db = database.sqlite("app.db")
try:
db.execute(
"INSERT INTO users (username, email, password) VALUES (?, ?, ?)",
(username, email, password)
)
db.connection.commit()
except Exception as e:
return jsonify({"error": str(e)}), 500
return jsonify({"message": "User registered successfully"}), 201
@app.route('/login', methods=['POST'])
def login():
username = request.form.get('username')
password = request.form.get('password')
db = database.sqlite("app.db")
db.execute(
"SELECT * FROM users WHERE username = ? AND password = ?",
(username, password)
)
user = db.fetchone()
if user:
session['logged'] = True
session['username'] = username
if user[4]: # is_admin column
session['admin'] = True
return jsonify({"message": "Login successful"})
return jsonify({"error": "Invalid credentials"}), 401
@app.route('/dashboard')
@req.login_required
def dashboard():
return jsonify({
"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 = database.sqlite("app.db")
db.execute("SELECT id, username, email FROM users")
users = db.fetchall()
return jsonify({"users": users})
@app.route('/logout')
def logout():
session.clear()
return jsonify({"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.6.0.tar.gz.
File metadata
- Download URL: ol_utills-0.6.0.tar.gz
- Upload date:
- Size: 9.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8a089ec7ad90b48a4409d99c49209d6077b889ce58cb037122fea064e9bc8d3f
|
|
| MD5 |
117ea9602b437729869c9bd2445aa364
|
|
| BLAKE2b-256 |
2618a8b627ecfc49556598f15e52eab2c8cecbf7ab1e8a22cc98dc680abedaf1
|
Provenance
The following attestation bundles were made for ol_utills-0.6.0.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.6.0.tar.gz -
Subject digest:
8a089ec7ad90b48a4409d99c49209d6077b889ce58cb037122fea064e9bc8d3f - Sigstore transparency entry: 1176417632
- Sigstore integration time:
-
Permalink:
OverLimit-OL/Ol_Utills@3088547371da92c0b5e6009f48aa8e46372f98d8 -
Branch / Tag:
refs/tags/0.505v - Owner: https://github.com/OverLimit-OL
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@3088547371da92c0b5e6009f48aa8e46372f98d8 -
Trigger Event:
release
-
Statement type:
File details
Details for the file ol_utills-0.6.0-py3-none-any.whl.
File metadata
- Download URL: ol_utills-0.6.0-py3-none-any.whl
- Upload date:
- Size: 9.8 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 |
3af8f285161015dd5f438f7d67969f8cf8afae9fe78c2d58d7138e34827ebd57
|
|
| MD5 |
3db3667a701abf23aa512fad624280fe
|
|
| BLAKE2b-256 |
96e07051f321ffc16f728fc9005f7bc6865dac04e627d8d47c1fcc7fc5cd115e
|
Provenance
The following attestation bundles were made for ol_utills-0.6.0-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.6.0-py3-none-any.whl -
Subject digest:
3af8f285161015dd5f438f7d67969f8cf8afae9fe78c2d58d7138e34827ebd57 - Sigstore transparency entry: 1176417716
- Sigstore integration time:
-
Permalink:
OverLimit-OL/Ol_Utills@3088547371da92c0b5e6009f48aa8e46372f98d8 -
Branch / Tag:
refs/tags/0.505v - Owner: https://github.com/OverLimit-OL
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@3088547371da92c0b5e6009f48aa8e46372f98d8 -
Trigger Event:
release
-
Statement type: