Latest commit

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

nested-validator-python

A tiny, fast, list-aware, nested rules validator for Python — with smart type coercion. By Autobit

nested-validator-python lets you declare validation as compact strings (e.g. required|int|gte:0) and recursively validate complex payloads (lists of dicts, lists within lists, etc.) using a clean __field convention for per-item rules. It also coerces common types (ints, floats, booleans, timestamps) so your validated result is ready for persistence.

Ideal for service layers, ORMs, and lightweight APIs where you want strict inputs without heavy dependencies.

Features

✅ String rules like required|min:3|max:100|email

🔁 Arbitrary nesting via __ per-item rules for lists

🧠 Type coercion for int, numeric, boolean, timestamp

🔗 Cross-field rules: same, different, before, after, confirmed

🧾 Clear, indexed errors for deep list paths (items[2].props[0].key)

🧰 Zero heavy deps; Python 3.9+ (tested up to 3.12)

Install

Using GitHub (until PyPI release):

pip install "git+https://github.com/AutobitDevs/nested-validator-python.git"

Or copy the core file into your project (e.g., utils/validator.py) and import from there.

Quick Start

If installed as a package:

from nested_validator import Validator

Or if you dropped it into your codebase:

from utils.validator import Validator

payload = { "name": "Equities", "properties": [ {"key": "margin", "value": "5", "default": "yes"}, {"key": "lot", "value": "50"} ] }

rules = { "name": "required|string|min:3|max:100", "properties": "required|list", "__properties": { # per-item rules for 'properties' "key": "required|string|min:1|max:100", "value": "int|gte:0", # "5" -> 5 (coerced) "default": "boolean" # "yes" -> True (coerced) } }

v = Validator(rules) validated = v.validate(payload)

if v.fails(): print(v.messages()) # full error map else: print(validated) # { # "name": "Equities", # "properties": [ # {"key": "margin", "value": 5, "default": True}, # {"key": "lot", "value": 50} # ] # }

Deeply Nested Example payload = { "orders": [ { "id": "1001", "lines": [ {"sku": "X", "qty": "2"}, {"sku": "Y", "qty": 1} ] } ] }

rules = { "orders": "required|list", "__orders": { "id": "required|string", "lines": "required|list", "__lines": { "sku": "required|string|min:1", "qty": "required|int|gte:1" } } }

Errors are indexed, e.g. orders[0].lines[1].qty.

Rules Reference

Basic

required, string, int, numeric, boolean, timestamp

min:, max:, size:

in:a,b,c

email, regex:

date or date:%Y-%m-%d (default %Y-%m-%d)

gt:, lt:, gte:, lte:

Cross-field

same:<other_field>, different:<other_field>

confirmed (requires _confirmation)

after:<other_date_field>, before:<other_date_field> (YYYY-MM-DD)

Lists & Nesting

Mark list fields with "list".

Provide item rules at the same level via __.

You can nest this pattern as deeply as needed.

Type Coercion (Summary) Rule Accepts Produces int "42", 42.0 42 numeric "3.14", 2 3.14, 2 boolean true/false/yes/no/on/off/1/0 True/False timestamp UNIX seconds as str or int int

Coerced values are written back into the input dict before building validated.

Minimal Service Example class Instrument(Service): async def createCategory(self): data = self.req["payload"] v = Validator({ "name": "required|string|min:3|max:100", "properties": "required|list", "__properties": { "key": "required|string|min:1|max:100", "value": "int|gte:0", "default": "max:100" } }) validated = v.validate(data) if v.fails(): return await self.response("failed", v.message())

 # Optional uniqueness check (ONQL)
q = self.ORM.build("fintrabit.instrument_categories[name=$1]", validated["name"])
if await self.ORM.onql(q):
return await self.response("failed", "Category name already exists")
res = await self.ORM.insert("instrument_category", validated)
return await self.response("success", "Category created", res)

API

Validator(rules: dict) – create a validator

validate(data: dict) -> dict – validates and returns normalized data (coerced)

fails() -> bool – any errors?

messages() -> dict – full error map (deep, indexed)

message() -> str|None – first error string (UI-friendly)

Custom rules: add a method validate(self, field, value, param, data) that raises ValidationError on failure.

Roadmap

Pluggable unique:<model.field> adapters

i18n error messages

Strict mode (reject unknown fields)

PyPI package

Contributing

PRs welcome! Please:

Keep it dependency-light

Add tests for new behavior

Explain changes clearly

Run tests (example):

pytest -q

License

MIT

Credits

By Autobit © Autobit Software Services Pvt Ltd

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Latest commit

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

nested-validator-python

A tiny, fast, list-aware, nested rules validator for Python — with smart type coercion. By Autobit

nested-validator-python lets you declare validation as compact strings (e.g. required|int|gte:0) and recursively validate complex payloads (lists of dicts, lists within lists, etc.) using a clean __field convention for per-item rules. It also coerces common types (ints, floats, booleans, timestamps) so your validated result is ready for persistence.

Ideal for service layers, ORMs, and lightweight APIs where you want strict inputs without heavy dependencies.

Features

✅ String rules like required|min:3|max:100|email

🔁 Arbitrary nesting via __ per-item rules for lists

🧠 Type coercion for int, numeric, boolean, timestamp

🔗 Cross-field rules: same, different, before, after, confirmed

🧾 Clear, indexed errors for deep list paths (items[2].props[0].key)

🧰 Zero heavy deps; Python 3.9+ (tested up to 3.12)

Install

Using GitHub (until PyPI release):

pip install "git+https://github.com/AutobitDevs/nested-validator-python.git"

Or copy the core file into your project (e.g., utils/validator.py) and import from there.

Quick Start

If installed as a package:

from nested_validator import Validator

Or if you dropped it into your codebase:

from utils.validator import Validator

payload = { "name": "Equities", "properties": [ {"key": "margin", "value": "5", "default": "yes"}, {"key": "lot", "value": "50"} ] }

rules = { "name": "required|string|min:3|max:100", "properties": "required|list", "__properties": { # per-item rules for 'properties' "key": "required|string|min:1|max:100", "value": "int|gte:0", # "5" -> 5 (coerced) "default": "boolean" # "yes" -> True (coerced) } }

v = Validator(rules) validated = v.validate(payload)

if v.fails(): print(v.messages()) # full error map else: print(validated) # { # "name": "Equities", # "properties": [ # {"key": "margin", "value": 5, "default": True}, # {"key": "lot", "value": 50} # ] # }

Deeply Nested Example payload = { "orders": [ { "id": "1001", "lines": [ {"sku": "X", "qty": "2"}, {"sku": "Y", "qty": 1} ] } ] }

rules = { "orders": "required|list", "__orders": { "id": "required|string", "lines": "required|list", "__lines": { "sku": "required|string|min:1", "qty": "required|int|gte:1" } } }

Errors are indexed, e.g. orders[0].lines[1].qty.

Rules Reference

Basic

required, string, int, numeric, boolean, timestamp

min:, max:, size:

in:a,b,c

email, regex:

date or date:%Y-%m-%d (default %Y-%m-%d)

gt:, lt:, gte:, lte:

Cross-field

same:<other_field>, different:<other_field>

confirmed (requires _confirmation)

after:<other_date_field>, before:<other_date_field> (YYYY-MM-DD)

Lists & Nesting

Mark list fields with "list".

Provide item rules at the same level via __.

You can nest this pattern as deeply as needed.

Type Coercion (Summary) Rule Accepts Produces int "42", 42.0 42 numeric "3.14", 2 3.14, 2 boolean true/false/yes/no/on/off/1/0 True/False timestamp UNIX seconds as str or int int

Coerced values are written back into the input dict before building validated.

Minimal Service Example class Instrument(Service): async def createCategory(self): data = self.req["payload"] v = Validator({ "name": "required|string|min:3|max:100", "properties": "required|list", "__properties": { "key": "required|string|min:1|max:100", "value": "int|gte:0", "default": "max:100" } }) validated = v.validate(data) if v.fails(): return await self.response("failed", v.message())

 # Optional uniqueness check (ONQL)
q = self.ORM.build("fintrabit.instrument_categories[name=$1]", validated["name"])
if await self.ORM.onql(q):
return await self.response("failed", "Category name already exists")
res = await self.ORM.insert("instrument_category", validated)
return await self.response("success", "Category created", res)

API

Validator(rules: dict) – create a validator

validate(data: dict) -> dict – validates and returns normalized data (coerced)

fails() -> bool – any errors?

messages() -> dict – full error map (deep, indexed)

message() -> str|None – first error string (UI-friendly)

Custom rules: add a method validate(self, field, value, param, data) that raises ValidationError on failure.

Roadmap

Pluggable unique:<model.field> adapters

i18n error messages

Strict mode (reject unknown fields)

PyPI package

Contributing

PRs welcome! Please:

Keep it dependency-light

Add tests for new behavior

Explain changes clearly

Run tests (example):

pytest -q

License

MIT

Credits

By Autobit © Autobit Software Services Pvt Ltd

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

nested-validator-python

A tiny, fast, list-aware, nested rules validator for Python — with smart type coercion. By Autobit

nested-validator-python lets you declare validation as compact strings (e.g. required|int|gte:0) and recursively validate complex payloads (lists of dicts, lists within lists, etc.) using a clean __field convention for per-item rules. It also coerces common types (ints, floats, booleans, timestamps) so your validated result is ready for persistence.

Ideal for service layers, ORMs, and lightweight APIs where you want strict inputs without heavy dependencies.

Features

✅ String rules like required|min:3|max:100|email

🔁 Arbitrary nesting via __ per-item rules for lists

🧠 Type coercion for int, numeric, boolean, timestamp

🔗 Cross-field rules: same, different, before, after, confirmed

🧾 Clear, indexed errors for deep list paths (items[2].props[0].key)

🧰 Zero heavy deps; Python 3.9+ (tested up to 3.12)

Install

Using GitHub (until PyPI release):

pip install "git+https://github.com/AutobitDevs/nested-validator-python.git"

Or copy the core file into your project (e.g., utils/validator.py) and import from there.

Quick Start

If installed as a package:

from nested_validator import Validator

Or if you dropped it into your codebase:

from utils.validator import Validator

payload = { "name": "Equities", "properties": [ {"key": "margin", "value": "5", "default": "yes"}, {"key": "lot", "value": "50"} ] }

rules = { "name": "required|string|min:3|max:100", "properties": "required|list", "__properties": { # per-item rules for 'properties' "key": "required|string|min:1|max:100", "value": "int|gte:0", # "5" -> 5 (coerced) "default": "boolean" # "yes" -> True (coerced) } }

v = Validator(rules) validated = v.validate(payload)

if v.fails(): print(v.messages()) # full error map else: print(validated) # { # "name": "Equities", # "properties": [ # {"key": "margin", "value": 5, "default": True}, # {"key": "lot", "value": 50} # ] # }

Deeply Nested Example payload = { "orders": [ { "id": "1001", "lines": [ {"sku": "X", "qty": "2"}, {"sku": "Y", "qty": 1} ] } ] }

rules = { "orders": "required|list", "__orders": { "id": "required|string", "lines": "required|list", "__lines": { "sku": "required|string|min:1", "qty": "required|int|gte:1" } } }

Errors are indexed, e.g. orders[0].lines[1].qty.

Rules Reference

Basic

required, string, int, numeric, boolean, timestamp

min:, max:, size:

in:a,b,c

email, regex:

date or date:%Y-%m-%d (default %Y-%m-%d)

gt:, lt:, gte:, lte:

Cross-field

same:<other_field>, different:<other_field>

confirmed (requires _confirmation)

after:<other_date_field>, before:<other_date_field> (YYYY-MM-DD)

Lists & Nesting

Mark list fields with "list".

Provide item rules at the same level via __.

You can nest this pattern as deeply as needed.

Type Coercion (Summary) Rule Accepts Produces int "42", 42.0 42 numeric "3.14", 2 3.14, 2 boolean true/false/yes/no/on/off/1/0 True/False timestamp UNIX seconds as str or int int

Coerced values are written back into the input dict before building validated.

Minimal Service Example class Instrument(Service): async def createCategory(self): data = self.req["payload"] v = Validator({ "name": "required|string|min:3|max:100", "properties": "required|list", "__properties": { "key": "required|string|min:1|max:100", "value": "int|gte:0", "default": "max:100" } }) validated = v.validate(data) if v.fails(): return await self.response("failed", v.message())

 # Optional uniqueness check (ONQL)
q = self.ORM.build("fintrabit.instrument_categories[name=$1]", validated["name"])
if await self.ORM.onql(q):
return await self.response("failed", "Category name already exists")
res = await self.ORM.insert("instrument_category", validated)
return await self.response("success", "Category created", res)

API

Validator(rules: dict) – create a validator

validate(data: dict) -> dict – validates and returns normalized data (coerced)

fails() -> bool – any errors?

messages() -> dict – full error map (deep, indexed)

message() -> str|None – first error string (UI-friendly)

Custom rules: add a method validate(self, field, value, param, data) that raises ValidationError on failure.

Roadmap

Pluggable unique:<model.field> adapters

i18n error messages

Strict mode (reject unknown fields)

PyPI package

Contributing

PRs welcome! Please:

Keep it dependency-light

Add tests for new behavior

Explain changes clearly

Run tests (example):

pytest -q

License

MIT

Credits

By Autobit © Autobit Software Services Pvt Ltd

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

nested-validator-python

A tiny, fast, list-aware, nested rules validator for Python — with smart type coercion. By Autobit

nested-validator-python lets you declare validation as compact strings (e.g. required|int|gte:0) and recursively validate complex payloads (lists of dicts, lists within lists, etc.) using a clean __field convention for per-item rules. It also coerces common types (ints, floats, booleans, timestamps) so your validated result is ready for persistence.

Ideal for service layers, ORMs, and lightweight APIs where you want strict inputs without heavy dependencies.

Features

✅ String rules like required|min:3|max:100|email

🔁 Arbitrary nesting via __ per-item rules for lists

🧠 Type coercion for int, numeric, boolean, timestamp

🔗 Cross-field rules: same, different, before, after, confirmed

🧾 Clear, indexed errors for deep list paths (items[2].props[0].key)

🧰 Zero heavy deps; Python 3.9+ (tested up to 3.12)

Install

Using GitHub (until PyPI release):

pip install "git+https://github.com/AutobitDevs/nested-validator-python.git"

Or copy the core file into your project (e.g., utils/validator.py) and import from there.

Quick Start

If installed as a package:

from nested_validator import Validator

Or if you dropped it into your codebase:

from utils.validator import Validator

payload = { "name": "Equities", "properties": [ {"key": "margin", "value": "5", "default": "yes"}, {"key": "lot", "value": "50"} ] }

rules = { "name": "required|string|min:3|max:100", "properties": "required|list", "__properties": { # per-item rules for 'properties' "key": "required|string|min:1|max:100", "value": "int|gte:0", # "5" -> 5 (coerced) "default": "boolean" # "yes" -> True (coerced) } }

v = Validator(rules) validated = v.validate(payload)

if v.fails(): print(v.messages()) # full error map else: print(validated) # { # "name": "Equities", # "properties": [ # {"key": "margin", "value": 5, "default": True}, # {"key": "lot", "value": 50} # ] # }

Deeply Nested Example payload = { "orders": [ { "id": "1001", "lines": [ {"sku": "X", "qty": "2"}, {"sku": "Y", "qty": 1} ] } ] }

rules = { "orders": "required|list", "__orders": { "id": "required|string", "lines": "required|list", "__lines": { "sku": "required|string|min:1", "qty": "required|int|gte:1" } } }

Errors are indexed, e.g. orders[0].lines[1].qty.

Rules Reference

Basic

required, string, int, numeric, boolean, timestamp

min:, max:, size:

in:a,b,c

email, regex:

date or date:%Y-%m-%d (default %Y-%m-%d)

gt:, lt:, gte:, lte:

Cross-field

same:<other_field>, different:<other_field>

confirmed (requires _confirmation)

after:<other_date_field>, before:<other_date_field> (YYYY-MM-DD)

Lists & Nesting

Mark list fields with "list".

Provide item rules at the same level via __.

You can nest this pattern as deeply as needed.

Type Coercion (Summary) Rule Accepts Produces int "42", 42.0 42 numeric "3.14", 2 3.14, 2 boolean true/false/yes/no/on/off/1/0 True/False timestamp UNIX seconds as str or int int

Coerced values are written back into the input dict before building validated.

Minimal Service Example class Instrument(Service): async def createCategory(self): data = self.req["payload"] v = Validator({ "name": "required|string|min:3|max:100", "properties": "required|list", "__properties": { "key": "required|string|min:1|max:100", "value": "int|gte:0", "default": "max:100" } }) validated = v.validate(data) if v.fails(): return await self.response("failed", v.message())

 # Optional uniqueness check (ONQL)
q = self.ORM.build("fintrabit.instrument_categories[name=$1]", validated["name"])
if await self.ORM.onql(q):
return await self.response("failed", "Category name already exists")
res = await self.ORM.insert("instrument_category", validated)
return await self.response("success", "Category created", res)

API

Validator(rules: dict) – create a validator

validate(data: dict) -> dict – validates and returns normalized data (coerced)

fails() -> bool – any errors?

messages() -> dict – full error map (deep, indexed)

message() -> str|None – first error string (UI-friendly)

Custom rules: add a method validate(self, field, value, param, data) that raises ValidationError on failure.

Roadmap

Pluggable unique:<model.field> adapters

i18n error messages

Strict mode (reject unknown fields)

PyPI package

Contributing

PRs welcome! Please:

Keep it dependency-light

Add tests for new behavior

Explain changes clearly

Run tests (example):

pytest -q

License

MIT

Credits

By Autobit © Autobit Software Services Pvt Ltd

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Latest commit

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

nested-validator-python

A tiny, fast, list-aware, nested rules validator for Python — with smart type coercion. By Autobit

nested-validator-python lets you declare validation as compact strings (e.g. required|int|gte:0) and recursively validate complex payloads (lists of dicts, lists within lists, etc.) using a clean __field convention for per-item rules. It also coerces common types (ints, floats, booleans, timestamps) so your validated result is ready for persistence.

Ideal for service layers, ORMs, and lightweight APIs where you want strict inputs without heavy dependencies.

Features

✅ String rules like required|min:3|max:100|email

🔁 Arbitrary nesting via __ per-item rules for lists

🧠 Type coercion for int, numeric, boolean, timestamp

🔗 Cross-field rules: same, different, before, after, confirmed

🧾 Clear, indexed errors for deep list paths (items[2].props[0].key)

🧰 Zero heavy deps; Python 3.9+ (tested up to 3.12)

Install

Using GitHub (until PyPI release):

pip install "git+https://github.com/AutobitDevs/nested-validator-python.git"

Or copy the core file into your project (e.g., utils/validator.py) and import from there.

Quick Start

If installed as a package:

from nested_validator import Validator

Or if you dropped it into your codebase:

from utils.validator import Validator

payload = { "name": "Equities", "properties": [ {"key": "margin", "value": "5", "default": "yes"}, {"key": "lot", "value": "50"} ] }

rules = { "name": "required|string|min:3|max:100", "properties": "required|list", "__properties": { # per-item rules for 'properties' "key": "required|string|min:1|max:100", "value": "int|gte:0", # "5" -> 5 (coerced) "default": "boolean" # "yes" -> True (coerced) } }

v = Validator(rules) validated = v.validate(payload)

if v.fails(): print(v.messages()) # full error map else: print(validated) # { # "name": "Equities", # "properties": [ # {"key": "margin", "value": 5, "default": True}, # {"key": "lot", "value": 50} # ] # }

Deeply Nested Example payload = { "orders": [ { "id": "1001", "lines": [ {"sku": "X", "qty": "2"}, {"sku": "Y", "qty": 1} ] } ] }

rules = { "orders": "required|list", "__orders": { "id": "required|string", "lines": "required|list", "__lines": { "sku": "required|string|min:1", "qty": "required|int|gte:1" } } }

Errors are indexed, e.g. orders[0].lines[1].qty.

Rules Reference

Basic

required, string, int, numeric, boolean, timestamp

min:, max:, size:

in:a,b,c

email, regex:

date or date:%Y-%m-%d (default %Y-%m-%d)

gt:, lt:, gte:, lte:

Cross-field

same:<other_field>, different:<other_field>

confirmed (requires _confirmation)

after:<other_date_field>, before:<other_date_field> (YYYY-MM-DD)

Lists & Nesting

Mark list fields with "list".

Provide item rules at the same level via __.

You can nest this pattern as deeply as needed.

Type Coercion (Summary) Rule Accepts Produces int "42", 42.0 42 numeric "3.14", 2 3.14, 2 boolean true/false/yes/no/on/off/1/0 True/False timestamp UNIX seconds as str or int int

Coerced values are written back into the input dict before building validated.

Minimal Service Example class Instrument(Service): async def createCategory(self): data = self.req["payload"] v = Validator({ "name": "required|string|min:3|max:100", "properties": "required|list", "__properties": { "key": "required|string|min:1|max:100", "value": "int|gte:0", "default": "max:100" } }) validated = v.validate(data) if v.fails(): return await self.response("failed", v.message())

 # Optional uniqueness check (ONQL)
q = self.ORM.build("fintrabit.instrument_categories[name=$1]", validated["name"])
if await self.ORM.onql(q):
return await self.response("failed", "Category name already exists")
res = await self.ORM.insert("instrument_category", validated)
return await self.response("success", "Category created", res)

API

Validator(rules: dict) – create a validator

validate(data: dict) -> dict – validates and returns normalized data (coerced)

fails() -> bool – any errors?

messages() -> dict – full error map (deep, indexed)

message() -> str|None – first error string (UI-friendly)

Custom rules: add a method validate(self, field, value, param, data) that raises ValidationError on failure.

Roadmap

Pluggable unique:<model.field> adapters

i18n error messages

Strict mode (reject unknown fields)

PyPI package

Contributing

PRs welcome! Please:

Keep it dependency-light

Add tests for new behavior

Explain changes clearly

Run tests (example):

pytest -q

License

MIT

Credits

By Autobit © Autobit Software Services Pvt Ltd

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

nested-validator-python

A tiny, fast, list-aware, nested rules validator for Python — with smart type coercion. By Autobit

nested-validator-python lets you declare validation as compact strings (e.g. required|int|gte:0) and recursively validate complex payloads (lists of dicts, lists within lists, etc.) using a clean __field convention for per-item rules. It also coerces common types (ints, floats, booleans, timestamps) so your validated result is ready for persistence.

Ideal for service layers, ORMs, and lightweight APIs where you want strict inputs without heavy dependencies.

Features

✅ String rules like required|min:3|max:100|email

🔁 Arbitrary nesting via __ per-item rules for lists

🧠 Type coercion for int, numeric, boolean, timestamp

🔗 Cross-field rules: same, different, before, after, confirmed

🧾 Clear, indexed errors for deep list paths (items[2].props[0].key)

🧰 Zero heavy deps; Python 3.9+ (tested up to 3.12)

Install

Using GitHub (until PyPI release):

pip install "git+https://github.com/AutobitDevs/nested-validator-python.git"

Or copy the core file into your project (e.g., utils/validator.py) and import from there.

Quick Start

If installed as a package:

from nested_validator import Validator

Or if you dropped it into your codebase:

from utils.validator import Validator

payload = { "name": "Equities", "properties": [ {"key": "margin", "value": "5", "default": "yes"}, {"key": "lot", "value": "50"} ] }

rules = { "name": "required|string|min:3|max:100", "properties": "required|list", "__properties": { # per-item rules for 'properties' "key": "required|string|min:1|max:100", "value": "int|gte:0", # "5" -> 5 (coerced) "default": "boolean" # "yes" -> True (coerced) } }

v = Validator(rules) validated = v.validate(payload)

if v.fails(): print(v.messages()) # full error map else: print(validated) # { # "name": "Equities", # "properties": [ # {"key": "margin", "value": 5, "default": True}, # {"key": "lot", "value": 50} # ] # }

Deeply Nested Example payload = { "orders": [ { "id": "1001", "lines": [ {"sku": "X", "qty": "2"}, {"sku": "Y", "qty": 1} ] } ] }

rules = { "orders": "required|list", "__orders": { "id": "required|string", "lines": "required|list", "__lines": { "sku": "required|string|min:1", "qty": "required|int|gte:1" } } }

Errors are indexed, e.g. orders[0].lines[1].qty.

Rules Reference

Basic

required, string, int, numeric, boolean, timestamp

min:, max:, size:

in:a,b,c

email, regex:

date or date:%Y-%m-%d (default %Y-%m-%d)

gt:, lt:, gte:, lte:

Cross-field

same:<other_field>, different:<other_field>

confirmed (requires _confirmation)

after:<other_date_field>, before:<other_date_field> (YYYY-MM-DD)

Lists & Nesting

Mark list fields with "list".

Provide item rules at the same level via __.

You can nest this pattern as deeply as needed.

Type Coercion (Summary) Rule Accepts Produces int "42", 42.0 42 numeric "3.14", 2 3.14, 2 boolean true/false/yes/no/on/off/1/0 True/False timestamp UNIX seconds as str or int int

Coerced values are written back into the input dict before building validated.

Minimal Service Example class Instrument(Service): async def createCategory(self): data = self.req["payload"] v = Validator({ "name": "required|string|min:3|max:100", "properties": "required|list", "__properties": { "key": "required|string|min:1|max:100", "value": "int|gte:0", "default": "max:100" } }) validated = v.validate(data) if v.fails(): return await self.response("failed", v.message())

 # Optional uniqueness check (ONQL)
q = self.ORM.build("fintrabit.instrument_categories[name=$1]", validated["name"])
if await self.ORM.onql(q):
return await self.response("failed", "Category name already exists")
res = await self.ORM.insert("instrument_category", validated)
return await self.response("success", "Category created", res)

API

Validator(rules: dict) – create a validator

validate(data: dict) -> dict – validates and returns normalized data (coerced)

fails() -> bool – any errors?

messages() -> dict – full error map (deep, indexed)

message() -> str|None – first error string (UI-friendly)

Custom rules: add a method validate(self, field, value, param, data) that raises ValidationError on failure.

Roadmap

Pluggable unique:<model.field> adapters

i18n error messages

Strict mode (reject unknown fields)

PyPI package

Contributing

PRs welcome! Please:

Keep it dependency-light

Add tests for new behavior

Explain changes clearly

Run tests (example):

pytest -q

License

MIT

Credits

By Autobit © Autobit Software Services Pvt Ltd

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

nested-validator-python

A tiny, fast, list-aware, nested rules validator for Python — with smart type coercion. By Autobit

nested-validator-python lets you declare validation as compact strings (e.g. required|int|gte:0) and recursively validate complex payloads (lists of dicts, lists within lists, etc.) using a clean __field convention for per-item rules. It also coerces common types (ints, floats, booleans, timestamps) so your validated result is ready for persistence.

Ideal for service layers, ORMs, and lightweight APIs where you want strict inputs without heavy dependencies.

Features

✅ String rules like required|min:3|max:100|email

🔁 Arbitrary nesting via __ per-item rules for lists

🧠 Type coercion for int, numeric, boolean, timestamp

🔗 Cross-field rules: same, different, before, after, confirmed

🧾 Clear, indexed errors for deep list paths (items[2].props[0].key)

🧰 Zero heavy deps; Python 3.9+ (tested up to 3.12)

Install

Using GitHub (until PyPI release):

pip install "git+https://github.com/AutobitDevs/nested-validator-python.git"

Or copy the core file into your project (e.g., utils/validator.py) and import from there.

Quick Start

If installed as a package:

from nested_validator import Validator

Or if you dropped it into your codebase:

from utils.validator import Validator

payload = { "name": "Equities", "properties": [ {"key": "margin", "value": "5", "default": "yes"}, {"key": "lot", "value": "50"} ] }

rules = { "name": "required|string|min:3|max:100", "properties": "required|list", "__properties": { # per-item rules for 'properties' "key": "required|string|min:1|max:100", "value": "int|gte:0", # "5" -> 5 (coerced) "default": "boolean" # "yes" -> True (coerced) } }

v = Validator(rules) validated = v.validate(payload)

if v.fails(): print(v.messages()) # full error map else: print(validated) # { # "name": "Equities", # "properties": [ # {"key": "margin", "value": 5, "default": True}, # {"key": "lot", "value": 50} # ] # }

Deeply Nested Example payload = { "orders": [ { "id": "1001", "lines": [ {"sku": "X", "qty": "2"}, {"sku": "Y", "qty": 1} ] } ] }

rules = { "orders": "required|list", "__orders": { "id": "required|string", "lines": "required|list", "__lines": { "sku": "required|string|min:1", "qty": "required|int|gte:1" } } }

Errors are indexed, e.g. orders[0].lines[1].qty.

Rules Reference

Basic

required, string, int, numeric, boolean, timestamp

min:, max:, size:

in:a,b,c

email, regex:

date or date:%Y-%m-%d (default %Y-%m-%d)

gt:, lt:, gte:, lte:

Cross-field

same:<other_field>, different:<other_field>

confirmed (requires _confirmation)

after:<other_date_field>, before:<other_date_field> (YYYY-MM-DD)

Lists & Nesting

Mark list fields with "list".

Provide item rules at the same level via __.

You can nest this pattern as deeply as needed.

Type Coercion (Summary) Rule Accepts Produces int "42", 42.0 42 numeric "3.14", 2 3.14, 2 boolean true/false/yes/no/on/off/1/0 True/False timestamp UNIX seconds as str or int int

Coerced values are written back into the input dict before building validated.

Minimal Service Example class Instrument(Service): async def createCategory(self): data = self.req["payload"] v = Validator({ "name": "required|string|min:3|max:100", "properties": "required|list", "__properties": { "key": "required|string|min:1|max:100", "value": "int|gte:0", "default": "max:100" } }) validated = v.validate(data) if v.fails(): return await self.response("failed", v.message())

 # Optional uniqueness check (ONQL)
q = self.ORM.build("fintrabit.instrument_categories[name=$1]", validated["name"])
if await self.ORM.onql(q):
return await self.response("failed", "Category name already exists")
res = await self.ORM.insert("instrument_category", validated)
return await self.response("success", "Category created", res)

API

Validator(rules: dict) – create a validator

validate(data: dict) -> dict – validates and returns normalized data (coerced)

fails() -> bool – any errors?

messages() -> dict – full error map (deep, indexed)

message() -> str|None – first error string (UI-friendly)

Custom rules: add a method validate(self, field, value, param, data) that raises ValidationError on failure.

Roadmap

Pluggable unique:<model.field> adapters

i18n error messages

Strict mode (reject unknown fields)

PyPI package

Contributing

PRs welcome! Please:

Keep it dependency-light

Add tests for new behavior

Explain changes clearly

Run tests (example):

pytest -q

License

MIT

Credits

By Autobit © Autobit Software Services Pvt Ltd

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Latest commit

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

nested-validator-python

A tiny, fast, list-aware, nested rules validator for Python — with smart type coercion. By Autobit

nested-validator-python lets you declare validation as compact strings (e.g. required|int|gte:0) and recursively validate complex payloads (lists of dicts, lists within lists, etc.) using a clean __field convention for per-item rules. It also coerces common types (ints, floats, booleans, timestamps) so your validated result is ready for persistence.

Ideal for service layers, ORMs, and lightweight APIs where you want strict inputs without heavy dependencies.

Features

✅ String rules like required|min:3|max:100|email

🔁 Arbitrary nesting via __ per-item rules for lists

🧠 Type coercion for int, numeric, boolean, timestamp

🔗 Cross-field rules: same, different, before, after, confirmed

🧾 Clear, indexed errors for deep list paths (items[2].props[0].key)

🧰 Zero heavy deps; Python 3.9+ (tested up to 3.12)

Install

Using GitHub (until PyPI release):

pip install "git+https://github.com/AutobitDevs/nested-validator-python.git"

Or copy the core file into your project (e.g., utils/validator.py) and import from there.

Quick Start

If installed as a package:

from nested_validator import Validator

Or if you dropped it into your codebase:

from utils.validator import Validator

payload = { "name": "Equities", "properties": [ {"key": "margin", "value": "5", "default": "yes"}, {"key": "lot", "value": "50"} ] }

rules = { "name": "required|string|min:3|max:100", "properties": "required|list", "__properties": { # per-item rules for 'properties' "key": "required|string|min:1|max:100", "value": "int|gte:0", # "5" -> 5 (coerced) "default": "boolean" # "yes" -> True (coerced) } }

v = Validator(rules) validated = v.validate(payload)

if v.fails(): print(v.messages()) # full error map else: print(validated) # { # "name": "Equities", # "properties": [ # {"key": "margin", "value": 5, "default": True}, # {"key": "lot", "value": 50} # ] # }

Deeply Nested Example payload = { "orders": [ { "id": "1001", "lines": [ {"sku": "X", "qty": "2"}, {"sku": "Y", "qty": 1} ] } ] }

rules = { "orders": "required|list", "__orders": { "id": "required|string", "lines": "required|list", "__lines": { "sku": "required|string|min:1", "qty": "required|int|gte:1" } } }

Errors are indexed, e.g. orders[0].lines[1].qty.

Rules Reference

Basic

required, string, int, numeric, boolean, timestamp

min:, max:, size:

in:a,b,c

email, regex:

date or date:%Y-%m-%d (default %Y-%m-%d)

gt:, lt:, gte:, lte:

Cross-field

same:<other_field>, different:<other_field>

confirmed (requires _confirmation)

after:<other_date_field>, before:<other_date_field> (YYYY-MM-DD)

Lists & Nesting

Mark list fields with "list".

Provide item rules at the same level via __.

You can nest this pattern as deeply as needed.

Type Coercion (Summary) Rule Accepts Produces int "42", 42.0 42 numeric "3.14", 2 3.14, 2 boolean true/false/yes/no/on/off/1/0 True/False timestamp UNIX seconds as str or int int

Coerced values are written back into the input dict before building validated.

Minimal Service Example class Instrument(Service): async def createCategory(self): data = self.req["payload"] v = Validator({ "name": "required|string|min:3|max:100", "properties": "required|list", "__properties": { "key": "required|string|min:1|max:100", "value": "int|gte:0", "default": "max:100" } }) validated = v.validate(data) if v.fails(): return await self.response("failed", v.message())

 # Optional uniqueness check (ONQL)
q = self.ORM.build("fintrabit.instrument_categories[name=$1]", validated["name"])
if await self.ORM.onql(q):
return await self.response("failed", "Category name already exists")
res = await self.ORM.insert("instrument_category", validated)
return await self.response("success", "Category created", res)

API

Validator(rules: dict) – create a validator

validate(data: dict) -> dict – validates and returns normalized data (coerced)

fails() -> bool – any errors?

messages() -> dict – full error map (deep, indexed)

message() -> str|None – first error string (UI-friendly)

Custom rules: add a method validate(self, field, value, param, data) that raises ValidationError on failure.

Roadmap

Pluggable unique:<model.field> adapters

i18n error messages

Strict mode (reject unknown fields)

PyPI package

Contributing

PRs welcome! Please:

Keep it dependency-light

Add tests for new behavior

Explain changes clearly

Run tests (example):

pytest -q

License

MIT

Credits

By Autobit © Autobit Software Services Pvt Ltd

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages