Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion src/usepy/validator/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
from .is_async_function import is_async_function
from .is_url import is_url
from .is_empty import is_empty
from .validators import is_email, is_json, is_number

__all__ = ["is_async_function", "is_url"]
__all__ = [
"is_async_function",
"is_url",
"is_empty",
"is_email",
"is_json",
"is_number",
]
42 changes: 42 additions & 0 deletions src/usepy/validator/is_empty.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from typing import Any


def is_empty(value: Any) -> bool:
"""
Checks if a value is empty.

Empty values include: None, empty string, empty list, empty dict, empty set, 0, False.

Args:
value (Any): The value to check.

Returns:
bool: True if the value is considered empty, False otherwise.

Examples:
>>> is_empty(None)
True
>>> is_empty('')
True
>>> is_empty([])
True
>>> is_empty({})
True
>>> is_empty('hello')
False
>>> is_empty([1])
False
"""
if value is None:
return True
if isinstance(value, (str, bytes, bytearray)):
# Strip whitespace before checking length
if isinstance(value, str):
value = value.strip()
return len(value) == 0
if isinstance(value, (list, tuple, set, dict)):
return len(value) == 0
# Check for numeric 0 and False
if value == 0 or value is False:
return True
return False
83 changes: 83 additions & 0 deletions src/usepy/validator/validators.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import re
from typing import Any


def is_email(email: str) -> bool:
"""
Checks if a string is a valid email address.

Args:
email (str): The email string to validate.

Returns:
bool: True if valid email format, False otherwise.

Examples:
>>> is_email('user@example.com')
True
>>> is_email('invalid.email')
False
>>> is_email('')
False
"""
if not email:
return False
# Simple email regex for basic validation
pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
return bool(re.match(pattern, email))


def is_json(json_string: str) -> bool:
"""
Checks if a string is valid JSON.

Args:
json_string (str): The JSON string to validate.

Returns:
bool: True if valid JSON format, False otherwise.

Examples:
>>> is_json('{"key": "value"}')
True
>>> is_json('invalid json')
False
"""
import json
try:
json.loads(json_string)
return True
except (json.JSONDecodeError, TypeError):
return False


def is_number(value: Any) -> bool:
"""
Checks if a value is a number (int, float, or numeric string).

Args:
value (Any): The value to check.

Returns:
bool: True if the value is a number, False otherwise.

Examples:
>>> is_number(123)
True
>>> is_number('123.45')
True
>>> is_number('not a number')
False
>>> is_number(None)
False
"""
if isinstance(value, (int, float)):
return True
if isinstance(value, str) and value.strip():
# Check if string can be converted to float
try:
float(value)
return True
except ValueError:
return False
return False
116 changes: 116 additions & 0 deletions tests/test_validator_new.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import pytest
from usepy.validator import is_empty, is_email, is_json, is_number


class TestIsEmpty:
"""Tests for is_empty() function"""

def test_is_empty_none(self):
assert is_empty(None) is True

def test_is_empty_string(self):
assert is_empty('') is True
assert is_empty(' ') is True

def test_is_empty_list(self):
assert is_empty([]) is True

def test_is_empty_tuple(self):
assert is_empty(()) is True

def test_is_empty_dict(self):
assert is_empty({}) is True

def test_is_empty_set(self):
assert is_empty(set()) is True

def test_is_empty_zero(self):
assert is_empty(0) is True
assert is_empty(0.0) is True
assert is_empty(False) is True

def test_is_not_empty_string(self):
assert is_empty('hello') is False

def test_is_not_empty_list(self):
assert is_empty([1]) is False

def test_is_not_empty_dict(self):
assert is_empty({'a': 1}) is False


class TestIsEmail:
"""Tests for is_email() function"""

def test_valid_email(self):
assert is_email('user@example.com') is True
assert is_email('user.name@domain.co.uk') is True
assert is_email('test+tag@gmail.com') is True

def test_invalid_email(self):
assert is_email('invalid.email') is False
assert is_email('user@') is False
assert is_email('@example.com') is False
assert is_email('user@domain') is False

def test_empty_email(self):
assert is_email('') is False
assert is_email(None) is False


class TestIsJson:
"""Tests for is_json() function"""

def test_valid_json(self):
assert is_json('{"key": "value"}') is True
assert is_json('{"nested": {"key": [1, 2, 3]}}') is True
assert is_json('[1, 2, 3]') is True
assert is_json('null') is True
assert is_json('true') is True
assert is_json('"string"') is True
assert is_json('123') is True
assert is_json('null') is True

def test_invalid_json(self):
assert is_json('{"invalid": value}') is False
assert is_json('not json') is False
assert is_json('{') is False
assert is_json('') is False # Empty string is NOT valid JSON

def test_none_is_json(self):
assert is_json(None) is False


class TestIsNumber:
"""Tests for is_number() function"""

def test_int_is_number(self):
assert is_number(123) is True
assert is_number(-456) is True

def test_float_is_number(self):
assert is_number(123.45) is True
assert is_number(-78.9) is True

def test_numeric_string_is_number(self):
assert is_number('123') is True
assert is_number('123.45') is True
assert is_number('-123') is True

def test_non_numeric_string_not_number(self):
assert is_number('abc') is False
assert is_number('12a34') is False
assert is_number('hello') is False

def test_zero_is_number(self):
assert is_number(0) is True
assert is_number(0.0) is True

def test_none_not_number(self):
assert is_number(None) is False

def test_empty_string_not_number(self):
assert is_number('') is False

def test_whitespace_not_number(self):
assert is_number(' ') is False
Loading