diff --git a/dist/type_enforced-1.4.0-py3-none-any.whl b/dist/type_enforced-1.4.0-py3-none-any.whl
new file mode 100644
index 0000000..d254dd7
Binary files /dev/null and b/dist/type_enforced-1.4.0-py3-none-any.whl differ
diff --git a/dist/type_enforced-1.4.0.tar.gz b/dist/type_enforced-1.4.0.tar.gz
new file mode 100644
index 0000000..82849a3
Binary files /dev/null and b/dist/type_enforced-1.4.0.tar.gz differ
diff --git a/docs/search.js b/docs/search.js
index a1a4f41..ad674e9 100644
--- a/docs/search.js
+++ b/docs/search.js
@@ -1,6 +1,6 @@
window.pdocSearch = (function(){
/** elasticlunr - http://weixsong.github.io * Copyright (C) 2017 Oliver Nightingale * Copyright (C) 2017 Wei Song * MIT Licensed */!function(){function e(e){if(null===e||"object"!=typeof e)return e;var t=e.constructor();for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);return t}var t=function(e){var n=new t.Index;return n.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),e&&e.call(n,n),n};t.version="0.9.5",lunr=t,t.utils={},t.utils.warn=function(e){return function(t){e.console&&console.warn&&console.warn(t)}}(this),t.utils.toString=function(e){return void 0===e||null===e?"":e.toString()},t.EventEmitter=function(){this.events={}},t.EventEmitter.prototype.addListener=function(){var e=Array.prototype.slice.call(arguments),t=e.pop(),n=e;if("function"!=typeof t)throw new TypeError("last argument must be a function");n.forEach(function(e){this.hasHandler(e)||(this.events[e]=[]),this.events[e].push(t)},this)},t.EventEmitter.prototype.removeListener=function(e,t){if(this.hasHandler(e)){var n=this.events[e].indexOf(t);-1!==n&&(this.events[e].splice(n,1),0==this.events[e].length&&delete this.events[e])}},t.EventEmitter.prototype.emit=function(e){if(this.hasHandler(e)){var t=Array.prototype.slice.call(arguments,1);this.events[e].forEach(function(e){e.apply(void 0,t)},this)}},t.EventEmitter.prototype.hasHandler=function(e){return e in this.events},t.tokenizer=function(e){if(!arguments.length||null===e||void 0===e)return[];if(Array.isArray(e)){var n=e.filter(function(e){return null===e||void 0===e?!1:!0});n=n.map(function(e){return t.utils.toString(e).toLowerCase()});var i=[];return n.forEach(function(e){var n=e.split(t.tokenizer.seperator);i=i.concat(n)},this),i}return e.toString().trim().toLowerCase().split(t.tokenizer.seperator)},t.tokenizer.defaultSeperator=/[\s\-]+/,t.tokenizer.seperator=t.tokenizer.defaultSeperator,t.tokenizer.setSeperator=function(e){null!==e&&void 0!==e&&"object"==typeof e&&(t.tokenizer.seperator=e)},t.tokenizer.resetSeperator=function(){t.tokenizer.seperator=t.tokenizer.defaultSeperator},t.tokenizer.getSeperator=function(){return t.tokenizer.seperator},t.Pipeline=function(){this._queue=[]},t.Pipeline.registeredFunctions={},t.Pipeline.registerFunction=function(e,n){n in t.Pipeline.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+n),e.label=n,t.Pipeline.registeredFunctions[n]=e},t.Pipeline.getRegisteredFunction=function(e){return e in t.Pipeline.registeredFunctions!=!0?null:t.Pipeline.registeredFunctions[e]},t.Pipeline.warnIfFunctionNotRegistered=function(e){var n=e.label&&e.label in this.registeredFunctions;n||t.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",e)},t.Pipeline.load=function(e){var n=new t.Pipeline;return e.forEach(function(e){var i=t.Pipeline.getRegisteredFunction(e);if(!i)throw new Error("Cannot load un-registered function: "+e);n.add(i)}),n},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(e){t.Pipeline.warnIfFunctionNotRegistered(e),this._queue.push(e)},this)},t.Pipeline.prototype.after=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._queue.indexOf(e);if(-1===i)throw new Error("Cannot find existingFn");this._queue.splice(i+1,0,n)},t.Pipeline.prototype.before=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._queue.indexOf(e);if(-1===i)throw new Error("Cannot find existingFn");this._queue.splice(i,0,n)},t.Pipeline.prototype.remove=function(e){var t=this._queue.indexOf(e);-1!==t&&this._queue.splice(t,1)},t.Pipeline.prototype.run=function(e){for(var t=[],n=e.length,i=this._queue.length,o=0;n>o;o++){for(var r=e[o],s=0;i>s&&(r=this._queue[s](r,o,e),void 0!==r&&null!==r);s++);void 0!==r&&null!==r&&t.push(r)}return t},t.Pipeline.prototype.reset=function(){this._queue=[]},t.Pipeline.prototype.get=function(){return this._queue},t.Pipeline.prototype.toJSON=function(){return this._queue.map(function(e){return t.Pipeline.warnIfFunctionNotRegistered(e),e.label})},t.Index=function(){this._fields=[],this._ref="id",this.pipeline=new t.Pipeline,this.documentStore=new t.DocumentStore,this.index={},this.eventEmitter=new t.EventEmitter,this._idfCache={},this.on("add","remove","update",function(){this._idfCache={}}.bind(this))},t.Index.prototype.on=function(){var e=Array.prototype.slice.call(arguments);return this.eventEmitter.addListener.apply(this.eventEmitter,e)},t.Index.prototype.off=function(e,t){return this.eventEmitter.removeListener(e,t)},t.Index.load=function(e){e.version!==t.version&&t.utils.warn("version mismatch: current "+t.version+" importing "+e.version);var n=new this;n._fields=e.fields,n._ref=e.ref,n.documentStore=t.DocumentStore.load(e.documentStore),n.pipeline=t.Pipeline.load(e.pipeline),n.index={};for(var i in e.index)n.index[i]=t.InvertedIndex.load(e.index[i]);return n},t.Index.prototype.addField=function(e){return this._fields.push(e),this.index[e]=new t.InvertedIndex,this},t.Index.prototype.setRef=function(e){return this._ref=e,this},t.Index.prototype.saveDocument=function(e){return this.documentStore=new t.DocumentStore(e),this},t.Index.prototype.addDoc=function(e,n){if(e){var n=void 0===n?!0:n,i=e[this._ref];this.documentStore.addDoc(i,e),this._fields.forEach(function(n){var o=this.pipeline.run(t.tokenizer(e[n]));this.documentStore.addFieldLength(i,n,o.length);var r={};o.forEach(function(e){e in r?r[e]+=1:r[e]=1},this);for(var s in r){var u=r[s];u=Math.sqrt(u),this.index[n].addToken(s,{ref:i,tf:u})}},this),n&&this.eventEmitter.emit("add",e,this)}},t.Index.prototype.removeDocByRef=function(e){if(e&&this.documentStore.isDocStored()!==!1&&this.documentStore.hasDoc(e)){var t=this.documentStore.getDoc(e);this.removeDoc(t,!1)}},t.Index.prototype.removeDoc=function(e,n){if(e){var n=void 0===n?!0:n,i=e[this._ref];this.documentStore.hasDoc(i)&&(this.documentStore.removeDoc(i),this._fields.forEach(function(n){var o=this.pipeline.run(t.tokenizer(e[n]));o.forEach(function(e){this.index[n].removeToken(e,i)},this)},this),n&&this.eventEmitter.emit("remove",e,this))}},t.Index.prototype.updateDoc=function(e,t){var t=void 0===t?!0:t;this.removeDocByRef(e[this._ref],!1),this.addDoc(e,!1),t&&this.eventEmitter.emit("update",e,this)},t.Index.prototype.idf=function(e,t){var n="@"+t+"/"+e;if(Object.prototype.hasOwnProperty.call(this._idfCache,n))return this._idfCache[n];var i=this.index[t].getDocFreq(e),o=1+Math.log(this.documentStore.length/(i+1));return this._idfCache[n]=o,o},t.Index.prototype.getFields=function(){return this._fields.slice()},t.Index.prototype.search=function(e,n){if(!e)return[];e="string"==typeof e?{any:e}:JSON.parse(JSON.stringify(e));var i=null;null!=n&&(i=JSON.stringify(n));for(var o=new t.Configuration(i,this.getFields()).get(),r={},s=Object.keys(e),u=0;u
Initialize a FunctionMethodEnforce class object as a wrapper for a passed function __fn__
.
Requires:
\n\n- `__fn__`:\n - What: The function to enforce\n - Type: function | method | class\n
\n", "signature": "(__fn__)"}, "type_enforced.enforcer.Enforcer": {"fullname": "type_enforced.enforcer.Enforcer", "modulename": "type_enforced.enforcer", "qualname": "Enforcer", "kind": "function", "doc": "A wrapper to enforce types within a function or method given argument annotations.
\n\nEach wrapped item is converted into a special FunctionMethodEnforcer
class object that validates the passed parameters for the function or method when it is called. If a function or method that is passed does not have any annotations, it is not converted into a FunctionMethodEnforcer
class as no validation is possible.
If wrapping a class, all methods in the class that meet any of the following criteria will be wrapped individually:
\n\n__call__
staticmethod
(if python >= 3.10)classmethod
(if python >= 3.10)Requires:
\n\nclsFnMethod
:\nExample Use:
\n\n>>> import type_enforced\n>>> @type_enforced.Enforcer\n... def my_fn(a: int , b: [int, str] =2, c: int =3) -> None:\n... pass\n...\n>>> my_fn(a=1, b=2, c=3)\n>>> my_fn(a=1, b='2', c=3)\n>>> my_fn(a='a', b=2, c=3)\nTraceback (most recent call last):\n File \"<stdin>\", line 1, in <module>\n File \"/home/conmak/development/personal/type_enforced/type_enforced/enforcer.py\", line 85, in __call__\n self.__check_type__(assigned_vars.get(key), value, key)\n File \"/home/conmak/development/personal/type_enforced/type_enforced/enforcer.py\", line 107, in __check_type__\n self.__exception__(\n File \"/home/conmak/development/personal/type_enforced/type_enforced/enforcer.py\", line 34, in __exception__\n raise Exception(f\"({self.__fn__.__qualname__}): {message}\")\nException: (my_fn): Type mismatch for typed variable `a`. Expected one of the following `[<class 'int'>]` but got `<class 'str'>` instead.\n
\n", "signature": "(clsFnMethod):", "funcdef": "def"}, "type_enforced.utils": {"fullname": "type_enforced.utils", "modulename": "type_enforced.utils", "kind": "module", "doc": "\n"}, "type_enforced.utils.WithSubclasses": {"fullname": "type_enforced.utils.WithSubclasses", "modulename": "type_enforced.utils", "qualname": "WithSubclasses", "kind": "function", "doc": "A special helper function to allow a class type to be passed and also allow all subclasses of that type.
\n\nRequires:
\n\nobj
:\nReturns:
\n\nout
:\nNotes:
\n\nInitialize a FunctionMethodEnforce class object as a wrapper for a passed function __fn__
.
Requires:
\n\n- `__fn__`:\n - What: The function to enforce\n - Type: function | method | class\n
\n", "signature": "(__fn__)"}, "type_enforced.enforcer.Enforcer": {"fullname": "type_enforced.enforcer.Enforcer", "modulename": "type_enforced.enforcer", "qualname": "Enforcer", "kind": "variable", "doc": "A wrapper to enforce types within a function or method given argument annotations.
\n\nEach wrapped item is converted into a special FunctionMethodEnforcer
class object that validates the passed parameters for the function or method when it is called. If a function or method that is passed does not have any annotations, it is not converted into a FunctionMethodEnforcer
class as no validation is possible.
If wrapping a class, all methods in the class that meet any of the following criteria will be wrapped individually:
\n\n__call__
staticmethod
(if python >= 3.10)classmethod
(if python >= 3.10)Requires:
\n\nclsFnMethod
:\nExample Use:
\n\n>>> import type_enforced\n>>> @type_enforced.Enforcer\n... def my_fn(a: int , b: [int, str] =2, c: int =3) -> None:\n... pass\n...\n>>> my_fn(a=1, b=2, c=3)\n>>> my_fn(a=1, b='2', c=3)\n>>> my_fn(a='a', b=2, c=3)\nTraceback (most recent call last):\n File \"<stdin>\", line 1, in <module>\n File \"/home/conmak/development/personal/type_enforced/type_enforced/enforcer.py\", line 85, in __call__\n self.__check_type__(assigned_vars.get(key), value, key)\n File \"/home/conmak/development/personal/type_enforced/type_enforced/enforcer.py\", line 107, in __check_type__\n self.__exception__(\n File \"/home/conmak/development/personal/type_enforced/type_enforced/enforcer.py\", line 34, in __exception__\n raise Exception(f\"({self.__fn__.__qualname__}): {message}\")\nException: (my_fn): Type mismatch for typed variable `a`. Expected one of the following `[<class 'int'>]` but got `<class 'str'>` instead.\n
\n", "default_value": "<Partial type_enforced.enforcer.Enforcer object>"}, "type_enforced.utils": {"fullname": "type_enforced.utils", "modulename": "type_enforced.utils", "kind": "module", "doc": "\n"}, "type_enforced.utils.WithSubclasses": {"fullname": "type_enforced.utils.WithSubclasses", "modulename": "type_enforced.utils", "qualname": "WithSubclasses", "kind": "function", "doc": "A special helper function to allow a class type to be passed and also allow all subclasses of that type.
\n\nRequires:
\n\nobj
:\nReturns:
\n\nout
:\nNotes:
\n\nA special class wrapper to allow for easy partial function wrappings and calls.
\n"}, "type_enforced.utils.Partial.__init__": {"fullname": "type_enforced.utils.Partial.__init__", "modulename": "type_enforced.utils", "qualname": "Partial.__init__", "kind": "function", "doc": "\n", "signature": "(__fn__, *__args__, **__kwargs__)"}}, "docInfo": {"type_enforced": {"qualname": 0, "fullname": 2, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "type_enforced.enforcer": {"qualname": 0, "fullname": 3, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "type_enforced.enforcer.FunctionMethodEnforcer": {"qualname": 1, "fullname": 4, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "type_enforced.enforcer.FunctionMethodEnforcer.__init__": {"qualname": 3, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 11, "bases": 0, "doc": 43}, "type_enforced.enforcer.Enforcer": {"qualname": 1, "fullname": 4, "annotation": 0, "default_value": 10, "signature": 0, "bases": 0, "doc": 339}, "type_enforced.utils": {"qualname": 0, "fullname": 3, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "type_enforced.utils.WithSubclasses": {"qualname": 1, "fullname": 4, "annotation": 0, "default_value": 0, "signature": 11, "bases": 0, "doc": 123}, "type_enforced.utils.Partial": {"qualname": 1, "fullname": 4, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 16}, "type_enforced.utils.Partial.__init__": {"qualname": 3, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 29, "bases": 0, "doc": 3}}, "length": 9, "save": true}, "index": {"qualname": {"root": {"docs": {"type_enforced.enforcer.FunctionMethodEnforcer.__init__": {"tf": 1}, "type_enforced.utils.Partial.__init__": {"tf": 1}}, "df": 2, "f": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"type_enforced.enforcer.FunctionMethodEnforcer": {"tf": 1}, "type_enforced.enforcer.FunctionMethodEnforcer.__init__": {"tf": 1}}, "df": 2}}}}}}}}}}}}}}}}}}}}}}, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {"type_enforced.enforcer.FunctionMethodEnforcer.__init__": {"tf": 1}, "type_enforced.utils.Partial.__init__": {"tf": 1}}, "df": 2}}}}, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}}}}}}}, "w": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"type_enforced.utils.WithSubclasses": {"tf": 1}}, "df": 1}}}}}}}}}}}}}}, "p": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {"type_enforced.utils.Partial": {"tf": 1}, "type_enforced.utils.Partial.__init__": {"tf": 1}}, "df": 2}}}}}}}}}, "fullname": {"root": {"docs": {"type_enforced.enforcer.FunctionMethodEnforcer.__init__": {"tf": 1}, "type_enforced.utils.Partial.__init__": {"tf": 1}}, "df": 2, "t": {"docs": {}, "df": 0, "y": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {"type_enforced": {"tf": 1}, "type_enforced.enforcer": {"tf": 1}, "type_enforced.enforcer.FunctionMethodEnforcer": {"tf": 1}, "type_enforced.enforcer.FunctionMethodEnforcer.__init__": {"tf": 1}, "type_enforced.enforcer.Enforcer": {"tf": 1}, "type_enforced.utils": {"tf": 1}, "type_enforced.utils.WithSubclasses": {"tf": 1}, "type_enforced.utils.Partial": {"tf": 1}, "type_enforced.utils.Partial.__init__": {"tf": 1}}, "df": 9}}}}, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"type_enforced": {"tf": 1}, "type_enforced.enforcer": {"tf": 1}, "type_enforced.enforcer.FunctionMethodEnforcer": {"tf": 1}, "type_enforced.enforcer.FunctionMethodEnforcer.__init__": {"tf": 1}, "type_enforced.enforcer.Enforcer": {"tf": 1}, "type_enforced.utils": {"tf": 1}, "type_enforced.utils.WithSubclasses": {"tf": 1}, "type_enforced.utils.Partial": {"tf": 1}, "type_enforced.utils.Partial.__init__": {"tf": 1}}, "df": 9}, "r": {"docs": {"type_enforced.enforcer": {"tf": 1}, "type_enforced.enforcer.FunctionMethodEnforcer": {"tf": 1}, "type_enforced.enforcer.FunctionMethodEnforcer.__init__": {"tf": 1}, "type_enforced.enforcer.Enforcer": {"tf": 1.4142135623730951}}, "df": 4}}}}}}}}, "f": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"type_enforced.enforcer.FunctionMethodEnforcer": {"tf": 1}, "type_enforced.enforcer.FunctionMethodEnforcer.__init__": {"tf": 1}}, "df": 2}}}}}}}}}}}}}}}}}}}}}}, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {"type_enforced.enforcer.FunctionMethodEnforcer.__init__": {"tf": 1}, "type_enforced.utils.Partial.__init__": {"tf": 1}}, "df": 2}}}}, "u": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "s": {"docs": {"type_enforced.utils": {"tf": 1}, "type_enforced.utils.WithSubclasses": {"tf": 1}, "type_enforced.utils.Partial": {"tf": 1}, "type_enforced.utils.Partial.__init__": {"tf": 1}}, "df": 4}}}}}, "w": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"type_enforced.utils.WithSubclasses": {"tf": 1}}, "df": 1}}}}}}}}}}}}}}, "p": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {"type_enforced.utils.Partial": {"tf": 1}, "type_enforced.utils.Partial.__init__": {"tf": 1}}, "df": 2}}}}}}}}}, "annotation": {"root": {"docs": {}, "df": 0}}, "default_value": {"root": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1.4142135623730951}}, "df": 1, "l": {"docs": {}, "df": 0, "t": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}, "p": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}}}}}}, "t": {"docs": {}, "df": 0, "y": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}}}, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}, "r": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1.4142135623730951}}, "df": 1}}}}}}}}, "o": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "j": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}}}}}, "g": {"docs": {}, "df": 0, "t": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}}}, "signature": {"root": {"docs": {"type_enforced.enforcer.FunctionMethodEnforcer.__init__": {"tf": 3.1622776601683795}, "type_enforced.utils.WithSubclasses": {"tf": 3.1622776601683795}, "type_enforced.utils.Partial.__init__": {"tf": 5.0990195135927845}}, "df": 3, "f": {"docs": {}, "df": 0, "n": {"docs": {"type_enforced.enforcer.FunctionMethodEnforcer.__init__": {"tf": 1}, "type_enforced.utils.Partial.__init__": {"tf": 1}}, "df": 2}}, "o": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "j": {"docs": {"type_enforced.utils.WithSubclasses": {"tf": 1}}, "df": 1}}}, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "s": {"docs": {"type_enforced.utils.Partial.__init__": {"tf": 1}}, "df": 1}}}}, "k": {"docs": {}, "df": 0, "w": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "s": {"docs": {"type_enforced.utils.Partial.__init__": {"tf": 1}}, "df": 1}}}}}}}}, "bases": {"root": {"docs": {}, "df": 0}}, "doc": {"root": {"1": {"0": {"7": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}, "docs": {"type_enforced.enforcer.Enforcer": {"tf": 1.4142135623730951}}, "df": 1}, "docs": {"type_enforced.enforcer.Enforcer": {"tf": 1.7320508075688772}}, "df": 1}, "2": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 2}}, "df": 1}, "3": {"4": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}, "docs": {"type_enforced.enforcer.Enforcer": {"tf": 2.449489742783178}}, "df": 1}, "8": {"5": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}, "docs": {}, "df": 0}, "docs": {"type_enforced": {"tf": 1.7320508075688772}, "type_enforced.enforcer": {"tf": 1.7320508075688772}, "type_enforced.enforcer.FunctionMethodEnforcer": {"tf": 1.7320508075688772}, "type_enforced.enforcer.FunctionMethodEnforcer.__init__": {"tf": 4.358898943540674}, "type_enforced.enforcer.Enforcer": {"tf": 8.246211251235321}, "type_enforced.utils": {"tf": 1.7320508075688772}, "type_enforced.utils.WithSubclasses": {"tf": 7.0710678118654755}, "type_enforced.utils.Partial": {"tf": 1.7320508075688772}, "type_enforced.utils.Partial.__init__": {"tf": 1.7320508075688772}}, "df": 9, "i": {"docs": {}, "df": 0, "n": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 2.23606797749979}}, "df": 1, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "z": {"docs": {}, "df": 0, "e": {"docs": {"type_enforced.enforcer.FunctionMethodEnforcer.__init__": {"tf": 1}}, "df": 1}}}}}}}}, "t": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 2}}, "df": 1, "o": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1.4142135623730951}}, "df": 1}}, "d": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "y": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}}}}}}}}}, "p": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "t": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}}, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "d": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}}}}}, "t": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1.4142135623730951}}, "df": 1, "e": {"docs": {}, "df": 0, "m": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}}, "s": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 2.23606797749979}, "type_enforced.utils.WithSubclasses": {"tf": 1}}, "df": 2}, "f": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 2}, "type_enforced.utils.WithSubclasses": {"tf": 1}}, "df": 2}, "m": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "t": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}}}}}, "a": {"docs": {"type_enforced.enforcer.FunctionMethodEnforcer.__init__": {"tf": 1.7320508075688772}, "type_enforced.enforcer.Enforcer": {"tf": 3.4641016151377544}, "type_enforced.utils.WithSubclasses": {"tf": 2.23606797749979}, "type_enforced.utils.Partial": {"tf": 1}}, "df": 4, "s": {"docs": {"type_enforced.enforcer.FunctionMethodEnforcer.__init__": {"tf": 1}, "type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 2, "s": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}}}}}}, "r": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}}}}}}, "n": {"docs": {"type_enforced.utils.WithSubclasses": {"tf": 1.4142135623730951}}, "df": 1, "n": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "s": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1.4142135623730951}}, "df": 1}}}}}}}}}, "y": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1.4142135623730951}, "type_enforced.utils.WithSubclasses": {"tf": 1}}, "df": 2}, "d": {"docs": {"type_enforced.utils.WithSubclasses": {"tf": 1}, "type_enforced.utils.Partial": {"tf": 1}}, "df": 2}}, "l": {"docs": {}, "df": 0, "l": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}, "type_enforced.utils.WithSubclasses": {"tf": 1.4142135623730951}}, "df": 2, "o": {"docs": {}, "df": 0, "w": {"docs": {"type_enforced.utils.WithSubclasses": {"tf": 1.4142135623730951}, "type_enforced.utils.Partial": {"tf": 1}}, "df": 2}}}, "s": {"docs": {}, "df": 0, "o": {"docs": {"type_enforced.utils.WithSubclasses": {"tf": 1.4142135623730951}}, "df": 1}}}}, "f": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1, "u": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"type_enforced.enforcer.FunctionMethodEnforcer.__init__": {"tf": 1.7320508075688772}, "type_enforced.enforcer.Enforcer": {"tf": 2.23606797749979}, "type_enforced.utils.WithSubclasses": {"tf": 1}, "type_enforced.utils.Partial": {"tf": 1}}, "df": 4, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {"type_enforced.enforcer.FunctionMethodEnforcer.__init__": {"tf": 1}}, "df": 1, "r": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1.4142135623730951}}, "df": 1}}}}}}}}}}}}}}, "a": {"docs": {}, "df": 0, "l": {"docs": {"type_enforced.utils.WithSubclasses": {"tf": 1}}, "df": 1}}}}}}}}}, "o": {"docs": {}, "df": 0, "r": {"docs": {"type_enforced.enforcer.FunctionMethodEnforcer.__init__": {"tf": 1}, "type_enforced.enforcer.Enforcer": {"tf": 1.4142135623730951}, "type_enforced.utils.WithSubclasses": {"tf": 1}, "type_enforced.utils.Partial": {"tf": 1}}, "df": 4}, "l": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "w": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1.4142135623730951}}, "df": 1}}}}}}}}, "n": {"docs": {"type_enforced.enforcer.FunctionMethodEnforcer.__init__": {"tf": 1.4142135623730951}, "type_enforced.enforcer.Enforcer": {"tf": 2.449489742783178}}, "df": 2}, "i": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 2}}, "df": 1}}}, "r": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "m": {"docs": {"type_enforced.utils.WithSubclasses": {"tf": 1}}, "df": 1}}}}, "c": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 2}}, "df": 1, "l": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "s": {"docs": {"type_enforced.enforcer.FunctionMethodEnforcer.__init__": {"tf": 1.4142135623730951}, "type_enforced.enforcer.Enforcer": {"tf": 2.8284271247461903}, "type_enforced.utils.WithSubclasses": {"tf": 2}, "type_enforced.utils.Partial": {"tf": 1}}, "df": 4, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "d": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}}}}}}}}, "s": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "d": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}}}}}}}}}, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1.4142135623730951}}, "df": 1}}}}}}, "s": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"type_enforced.utils.WithSubclasses": {"tf": 1}}, "df": 1}}}}}}}}, "r": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {"type_enforced.utils.WithSubclasses": {"tf": 1}}, "df": 1}}}}}}, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "l": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1.7320508075688772}}, "df": 1, "e": {"docs": {}, "df": 0, "d": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}, "s": {"docs": {"type_enforced.utils.Partial": {"tf": 1}}, "df": 1}}}}, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "a": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}}}}}}, "h": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "k": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1.4142135623730951}}, "df": 1}}}}}, "o": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "j": {"docs": {"type_enforced.utils.WithSubclasses": {"tf": 1}}, "df": 1, "e": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {"type_enforced.enforcer.FunctionMethodEnforcer.__init__": {"tf": 1}, "type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 2}}}}}, "r": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 2}}, "df": 1}, "f": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1.4142135623730951}, "type_enforced.utils.WithSubclasses": {"tf": 2}}, "df": 2}, "n": {"docs": {}, "df": 0, "e": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}, "u": {"docs": {}, "df": 0, "t": {"docs": {"type_enforced.utils.WithSubclasses": {"tf": 1}}, "df": 1}}}, "w": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"type_enforced.enforcer.FunctionMethodEnforcer.__init__": {"tf": 1}, "type_enforced.enforcer.Enforcer": {"tf": 1}, "type_enforced.utils.Partial": {"tf": 1}}, "df": 3}, "d": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 2}}, "df": 1}}, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1, "s": {"docs": {"type_enforced.utils.Partial": {"tf": 1}}, "df": 1}}}}}}}}, "h": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {"type_enforced.enforcer.FunctionMethodEnforcer.__init__": {"tf": 1}, "type_enforced.enforcer.Enforcer": {"tf": 1}, "type_enforced.utils.WithSubclasses": {"tf": 1.4142135623730951}}, "df": 3}}, "e": {"docs": {}, "df": 0, "n": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}}, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1.7320508075688772}}, "df": 1, "i": {"docs": {}, "df": 0, "n": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}}}, "l": {"docs": {}, "df": 0, "l": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}}}, "p": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "s": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1, "e": {"docs": {}, "df": 0, "d": {"docs": {"type_enforced.enforcer.FunctionMethodEnforcer.__init__": {"tf": 1}, "type_enforced.enforcer.Enforcer": {"tf": 1.4142135623730951}, "type_enforced.utils.WithSubclasses": {"tf": 1.4142135623730951}}, "df": 3}}}}, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "s": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}}}}}}, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"type_enforced.utils.WithSubclasses": {"tf": 1}}, "df": 1}}}, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {"type_enforced.utils.Partial": {"tf": 1}}, "df": 1}}}}}}, "o": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}}}}}}, "y": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1.7320508075688772}}, "df": 1, "t": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1.4142135623730951}}, "df": 1}}}}}, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {"type_enforced.utils.WithSubclasses": {"tf": 1}}, "df": 1}}}}}}}}}}}, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "q": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"type_enforced.enforcer.FunctionMethodEnforcer.__init__": {"tf": 1}, "type_enforced.enforcer.Enforcer": {"tf": 1}, "type_enforced.utils.WithSubclasses": {"tf": 1}}, "df": 3}}}}}}, "c": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}}, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "y": {"docs": {"type_enforced.utils.WithSubclasses": {"tf": 1.4142135623730951}}, "df": 1}}}}}}}}}, "t": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "s": {"docs": {"type_enforced.utils.WithSubclasses": {"tf": 1}}, "df": 1}}}}}}, "a": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}}}}, "t": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "e": {"docs": {"type_enforced.enforcer.FunctionMethodEnforcer.__init__": {"tf": 1}, "type_enforced.enforcer.Enforcer": {"tf": 2.449489742783178}, "type_enforced.utils.WithSubclasses": {"tf": 1.4142135623730951}}, "df": 3}, "a": {"docs": {}, "df": 0, "t": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 2}, "type_enforced.utils.WithSubclasses": {"tf": 1.4142135623730951}}, "df": 2}}, "i": {"docs": {}, "df": 0, "s": {"docs": {"type_enforced.utils.WithSubclasses": {"tf": 1}}, "df": 1}}}, "o": {"docs": {"type_enforced.enforcer.FunctionMethodEnforcer.__init__": {"tf": 1}, "type_enforced.enforcer.Enforcer": {"tf": 1}, "type_enforced.utils.WithSubclasses": {"tf": 1.4142135623730951}, "type_enforced.utils.Partial": {"tf": 1}}, "df": 4}, "y": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {"type_enforced.enforcer.FunctionMethodEnforcer.__init__": {"tf": 1}, "type_enforced.enforcer.Enforcer": {"tf": 2.449489742783178}, "type_enforced.utils.WithSubclasses": {"tf": 2.449489742783178}}, "df": 3, "s": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1.4142135623730951}}, "df": 1}, "d": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}}}, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "k": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}}}}}}}}, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {"type_enforced.enforcer.FunctionMethodEnforcer.__init__": {"tf": 1}, "type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 2, "d": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1.7320508075688772}}, "df": 1, "/": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "y": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1.7320508075688772}}, "df": 1}}}}, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1.7320508075688772}}, "df": 1}}}}}}}}}}, "r": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}}}}}}, "a": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "h": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}, "s": {"docs": {}, "df": 0, "y": {"docs": {"type_enforced.utils.Partial": {"tf": 1}}, "df": 1}}}, "x": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}}}}, "c": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 2}}, "df": 1}}}}}}}, "p": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}}}}}}}, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "d": {"docs": {"type_enforced.enforcer.FunctionMethodEnforcer.__init__": {"tf": 1}, "type_enforced.enforcer.Enforcer": {"tf": 2.23606797749979}}, "df": 2, "s": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 2}}, "df": 1}}}}}, "e": {"docs": {}, "df": 0, "t": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}, "s": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "e": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}}}}}, "y": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 2.23606797749979}}, "df": 1}, "o": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}, "d": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}}}}, "i": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "h": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}}}}}}}, "g": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}}}, "t": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 4.69041575982343}}, "df": 1}, "e": {"docs": {}, "df": 0, "t": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1, "s": {"docs": {"type_enforced.utils.WithSubclasses": {"tf": 1}}, "df": 1}}}, "o": {"docs": {}, "df": 0, "t": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}}, "s": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}, "type_enforced.utils.WithSubclasses": {"tf": 1}, "type_enforced.utils.Partial": {"tf": 1}}, "df": 3}}}}}}, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "d": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}}}}}}}}}, "r": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1.4142135623730951}}, "df": 1, "s": {"docs": {"type_enforced.utils.WithSubclasses": {"tf": 1}}, "df": 1}}, "d": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}}}, "h": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "d": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}, "type_enforced.utils.WithSubclasses": {"tf": 1}}, "df": 2}}}}}, "e": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "f": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1.7320508075688772}}, "df": 1}}}, "u": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "s": {"docs": {"type_enforced.utils.WithSubclasses": {"tf": 1}}, "df": 1, "e": {"docs": {}, "df": 0, "s": {"docs": {"type_enforced.utils.WithSubclasses": {"tf": 1.7320508075688772}}, "df": 1}}}}}}}}}}, "v": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}}}}}}, "u": {"docs": {}, "df": 0, "e": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}}, "r": {"docs": {}, "df": 0, "s": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}, "i": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}}}}}}}, "d": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}}, "e": {"docs": {}, "df": 0, "f": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}}, "n": {"docs": {}, "df": 0, "o": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1, "t": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1.4142135623730951}}, "df": 1, "e": {"docs": {}, "df": 0, "s": {"docs": {"type_enforced.utils.WithSubclasses": {"tf": 1}}, "df": 1}}}, "n": {"docs": {}, "df": 0, "e": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}}}, "h": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1.4142135623730951}}, "df": 1}}}, "o": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "/": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "k": {"docs": {}, "df": 0, "/": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "/": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "/": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "y": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1.7320508075688772}}, "df": 1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, "e": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"type_enforced.utils.WithSubclasses": {"tf": 1}}, "df": 1}}}}}}, "b": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 2}}, "df": 1, "e": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}, "type_enforced.utils.WithSubclasses": {"tf": 1.4142135623730951}}, "df": 2}, "u": {"docs": {}, "df": 0, "t": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}}, "u": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}, "n": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "z": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"type_enforced.utils.WithSubclasses": {"tf": 1.4142135623730951}}, "df": 1}}}, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"type_enforced.utils.WithSubclasses": {"tf": 1}}, "df": 1}}}}}}}}}}}}}, "l": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}}, "t": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 2}}, "df": 1}, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 2}}, "df": 1}}, "s": {"docs": {}, "df": 0, "t": {"docs": {"type_enforced.utils.WithSubclasses": {"tf": 1.4142135623730951}}, "df": 1}}}}, "k": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "y": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1.4142135623730951}}, "df": 1}}}, "q": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {"type_enforced.enforcer.Enforcer": {"tf": 1}}, "df": 1}}}}}}}}}}}, "pipeline": ["trimmer"], "_isPrebuiltIndex": true}; // mirrored in build-search-index.js (part 1) // Also split on html tags. this is a cheap heuristic, but good enough. diff --git a/docs/type_enforced.html b/docs/type_enforced.html index 77a73b3..4a74738 100644 --- a/docs/type_enforced.html +++ b/docs/type_enforced.html @@ -3,7 +3,7 @@ - +1from types import FunctionType, MethodType, GenericAlias - 2from typing import Type, Union, Sized, Literal - 3from functools import update_wrapper, wraps - 4 - 5# Python 3.10+ has a UnionType object that is used to represent Union types - 6try: - 7 from types import UnionType - 8except ImportError: - 9 # Python < 3.10 does not have UnionType - 10 # Since UnionType is validated after NoneType, we can use NoneType - 11 # as a stand in for UnionType to ignore it in older versions of python - 12 UnionType = type(None) - 13 - 14 - 15class FunctionMethodEnforcer: - 16 def __init__(self, __fn__): - 17 """ - 18 Initialize a FunctionMethodEnforce class object as a wrapper for a passed function `__fn__`. - 19 - 20 Requires: +@@ -359,213 +389,224 @@1from types import ( + 2 FunctionType, + 3 MethodType, + 4 GenericAlias, + 5 GeneratorType, + 6 BuiltinFunctionType, + 7 BuiltinMethodType, + 8) + 9from typing import Type, Union, Sized, Literal, Callable + 10from functools import update_wrapper, wraps + 11from type_enforced.utils import Partial + 12 + 13# Python 3.10+ has a UnionType object that is used to represent Union types + 14try: + 15 from types import UnionType + 16except ImportError: + 17 # Python < 3.10 does not have UnionType + 18 # Since UnionType is validated after NoneType, we can use NoneType + 19 # as a stand in for UnionType to ignore it in older versions of python + 20 UnionType = type(None) 21 - 22 - `__fn__`: - 23 - What: The function to enforce - 24 - Type: function | method | class - 25 """ - 26 update_wrapper(self, __fn__) - 27 self.__fn__ = __fn__ - 28 self.__outer_self__ = None - 29 # Validate that the passed function or method is a method or function - 30 self.__check_method_function__() - 31 # Get input defaults for the function or method - 32 self.__get_defaults__() - 33 # Get a dictionary of all annotations as checkable types - 34 self.__checkable_types__ = { - 35 key: self.__get_checkable_type__(value) - 36 for key, value in self.__annotations__.items() - 37 } - 38 self.__return_type__ = self.__checkable_types__.pop("return", None) - 39 - 40 def __get_defaults__(self): - 41 """ - 42 Get the default values of the passed function or method and store them in `self.__fn_defaults__`. - 43 """ - 44 # Determine assigned variables as they were passed in - 45 # See https://stackoverflow.com/a/71884467/12014156 - 46 if self.__fn__.__kwdefaults__ is not None: - 47 # __defaults__ are not used if *args are present necessitating this line - 48 self.__fn_defaults__ = self.__fn__.__kwdefaults__ - 49 elif self.__fn__.__defaults__ is not None: - 50 # Get the list of variable names (omittiting **kwargs var if present) - 51 varnames = list(self.__fn__.__code__.co_varnames)[ - 52 : self.__fn__.__code__.co_argcount - 53 ] - 54 # Create a dictionary of default values - 55 self.__fn_defaults__ = dict( - 56 zip( - 57 varnames[-len(self.__fn__.__defaults__) :], - 58 self.__fn__.__defaults__, - 59 ) - 60 ) - 61 else: - 62 self.__fn_defaults__ = {} - 63 - 64 def __get_checkable_type__(self, item_annotation): - 65 """ - 66 Gets the checkable type as a nested dict for a passed annotation. - 67 """ - 68 valid_types = {} - 69 if not isinstance(item_annotation, (list, tuple)): - 70 item_annotation = [item_annotation] - 71 for valid_type in item_annotation: - 72 # Special code to replace None with NoneType - 73 if valid_type is None: - 74 valid_types[type(None)] = None - 75 continue - 76 elif hasattr(valid_type, "__origin__"): - 77 # Special code for iterable types (e.g. list, tuple, dict, set) including typing iterables - 78 if valid_type.__origin__ in [list, tuple, dict, set]: - 79 valid_types[ - 80 valid_type.__origin__ - 81 ] = self.__get_checkable_type__(valid_type.__args__) - 82 # Handle any generic aliases - 83 elif isinstance(valid_type, GenericAlias): - 84 valid_types[valid_type.__origin__] = None - 85 # Handle Union Types (e.g. Union, Optional, ...) - 86 elif valid_type.__origin__ == Union: - 87 valid_types.update( + 22 + 23class FunctionMethodEnforcer: + 24 def __init__(self, __fn__): + 25 """ + 26 Initialize a FunctionMethodEnforce class object as a wrapper for a passed function `__fn__`. + 27 + 28 Requires: + 29 + 30 - `__fn__`: + 31 - What: The function to enforce + 32 - Type: function | method | class + 33 """ + 34 update_wrapper(self, __fn__) + 35 self.__fn__ = __fn__ + 36 self.__outer_self__ = None + 37 # Validate that the passed function or method is a method or function + 38 self.__check_method_function__() + 39 # Get input defaults for the function or method + 40 self.__get_defaults__() + 41 # Get a dictionary of all annotations as checkable types + 42 self.__checkable_types__ = { + 43 key: self.__get_checkable_type__(value) + 44 for key, value in self.__annotations__.items() + 45 } + 46 self.__return_type__ = self.__checkable_types__.pop("return", None) + 47 + 48 def __get_defaults__(self): + 49 """ + 50 Get the default values of the passed function or method and store them in `self.__fn_defaults__`. + 51 """ + 52 # Determine assigned variables as they were passed in + 53 # See https://stackoverflow.com/a/71884467/12014156 + 54 if self.__fn__.__kwdefaults__ is not None: + 55 # __defaults__ are not used if *args are present necessitating this line + 56 self.__fn_defaults__ = self.__fn__.__kwdefaults__ + 57 elif self.__fn__.__defaults__ is not None: + 58 # Get the list of variable names (omittiting **kwargs var if present) + 59 varnames = list(self.__fn__.__code__.co_varnames)[ + 60 : self.__fn__.__code__.co_argcount + 61 ] + 62 # Create a dictionary of default values + 63 self.__fn_defaults__ = dict( + 64 zip( + 65 varnames[-len(self.__fn__.__defaults__) :], + 66 self.__fn__.__defaults__, + 67 ) + 68 ) + 69 else: + 70 self.__fn_defaults__ = {} + 71 + 72 def __get_checkable_type__(self, item_annotation): + 73 """ + 74 Gets the checkable type as a nested dict for a passed annotation. + 75 """ + 76 valid_types = {} + 77 if not isinstance(item_annotation, (list, tuple)): + 78 item_annotation = [item_annotation] + 79 for valid_type in item_annotation: + 80 # Special code to replace None with NoneType + 81 if valid_type is None: + 82 valid_types[type(None)] = None + 83 continue + 84 elif hasattr(valid_type, "__origin__"): + 85 # Special code for iterable types (e.g. list, tuple, dict, set) including typing iterables + 86 if valid_type.__origin__ in [list, tuple, dict, set]: + 87 valid_types[valid_type.__origin__] = ( 88 self.__get_checkable_type__(valid_type.__args__) 89 ) - 90 # Handle Literals - 91 # Note: These will be handled separately in the self.__check_type__ - 92 # as the object is validated and not its type. - 93 elif valid_type.__origin__ == Literal: - 94 valid_types = { - 95 Literal: {i: None for i in valid_type.__args__} - 96 } - 97 - 98 # Handle Sized objects - 99 elif valid_type == Sized: -100 valid_types = { -101 list: None, -102 tuple: None, -103 dict: None, -104 set: None, -105 str: None, -106 bytes: None, -107 bytearray: None, -108 memoryview: None, -109 range: None, -110 # Allow nested types to be passed as well -111 **valid_types, -112 } -113 # Handle uninitialized class type objects (e.g. MyCustomClass) -114 else: -115 valid_types[valid_type] = None -116 # Handle special '|' syntax for Union Types -117 elif isinstance(valid_type, UnionType): -118 valid_types.update( -119 self.__get_checkable_type__(valid_type.__args__) -120 ) -121 else: -122 valid_types[valid_type] = None -123 return valid_types -124 -125 def __exception__(self, message): -126 """ -127 Usage: -128 -129 - Creates a class based exception message -130 -131 Requires: -132 -133 - `message`: -134 - Type: str -135 - What: The message to warn users with -136 """ -137 raise TypeError(f"({self.__fn__.__qualname__}): {message}") -138 -139 def __get__(self, obj, objtype): -140 """ -141 Overwrite standard __get__ method to return __call__ instead for wrapped class methods. -142 -143 Also stores the calling (__get__) `obj` to be passed as an initial argument for `__call__` such that methods can pass `self` correctly. -144 """ -145 -146 @wraps(self.__fn__) -147 def __get_fn__(*args, **kwargs): -148 return self.__call__(*args, **kwargs) + 90 # Handle any generic aliases + 91 elif isinstance(valid_type, GenericAlias): + 92 valid_types[valid_type.__origin__] = None + 93 # Handle Union Types (e.g. Union, Optional, ...) + 94 elif valid_type.__origin__ == Union: + 95 valid_types.update( + 96 self.__get_checkable_type__(valid_type.__args__) + 97 ) + 98 # Handle Literals + 99 # Note: These will be handled separately in the self.__check_type__ +100 # as the object is validated and not its type. +101 elif valid_type.__origin__ == Literal: +102 valid_types = { +103 Literal: {i: None for i in valid_type.__args__} +104 } +105 +106 # Handle Sized objects +107 elif valid_type == Sized: +108 valid_types = { +109 list: None, +110 tuple: None, +111 dict: None, +112 set: None, +113 str: None, +114 bytes: None, +115 bytearray: None, +116 memoryview: None, +117 range: None, +118 # Allow nested types to be passed as well +119 **valid_types, +120 } +121 # Handle uninitialized class type objects (e.g. MyCustomClass) +122 elif valid_type == Callable: +123 valid_types = { +124 staticmethod: None, +125 classmethod: None, +126 FunctionType: None, +127 BuiltinFunctionType: None, +128 MethodType: None, +129 BuiltinMethodType: None, +130 GeneratorType: None, +131 **valid_types, +132 } +133 else: +134 valid_types[valid_type] = None +135 # Handle special '|' syntax for Union Types +136 elif isinstance(valid_type, UnionType): +137 valid_types.update( +138 self.__get_checkable_type__(valid_type.__args__) +139 ) +140 else: +141 valid_types[valid_type] = None +142 return valid_types +143 +144 def __exception__(self, message): +145 """ +146 Usage: +147 +148 - Creates a class based exception message 149 -150 self.__outer_self__ = obj -151 return __get_fn__ -152 -153 def __check_method_function__(self): -154 """ -155 Validate that `self.__fn__` is a method or function -156 """ -157 if not isinstance(self.__fn__, (MethodType, FunctionType)): -158 raise Exception( -159 f"A non function/method was passed to Enforcer. See the stack trace above for more information." -160 ) +150 Requires: +151 +152 - `message`: +153 - Type: str +154 - What: The message to warn users with +155 """ +156 raise TypeError(f"({self.__fn__.__qualname__}): {message}") +157 +158 def __get__(self, obj, objtype): +159 """ +160 Overwrite standard __get__ method to return __call__ instead for wrapped class methods. 161 -162 def __call__(self, *args, **kwargs): -163 """ -164 This method is used to validate the passed inputs and return the output of the wrapped function or method. -165 """ -166 # Special code to pass self as an initial argument -167 # for validation purposes in methods -168 # See: self.__get__ -169 if self.__outer_self__ is not None: -170 args = (self.__outer_self__, *args) -171 # Create a compreshensive dictionary of assigned variables (order matters) -172 assigned_vars = { -173 **self.__fn_defaults__, -174 **dict(zip(self.__fn__.__code__.co_varnames[: len(args)], args)), -175 **kwargs, -176 } -177 # Validate all listed annotations vs the assigned_vars dictionary -178 for key, value in self.__checkable_types__.items(): -179 self.__check_type__(assigned_vars.get(key), value, key) -180 # Execute the function callable -181 return_value = self.__fn__(*args, **kwargs) -182 # If a return type was passed, validate the returned object -183 if self.__return_type__ is not None: -184 self.__check_type__(return_value, self.__return_type__, "return") -185 return return_value -186 -187 def __check_type__(self, obj, acceptable_types, key): -188 """ -189 Raises an exception the type of a passed `obj` (parameter) is not in the list of supplied `acceptable_types` for the argument. -190 """ -191 if isinstance(obj, type): -192 passed_type = Type[obj] -193 else: -194 passed_type = type(obj) -195 if passed_type not in acceptable_types: -196 # Add special string to store any string to add before acceptable types -197 # in any exception message -198 pre_acceptable_types_str = "" -199 # Special check for Literals -200 if Literal in acceptable_types: -201 if obj in acceptable_types[Literal]: -202 return -203 else: -204 pre_acceptable_types_str = "Literal" -205 acceptable_types = acceptable_types[Literal] -206 passed_type = obj -207 # Raise the exception -208 self.__exception__( -209 f"Type mismatch for typed variable `{key}`. Expected one of the following `{pre_acceptable_types_str}{str(list(acceptable_types.keys()))}` but got `{passed_type}` instead." -210 ) -211 sub_type = acceptable_types.get(passed_type) -212 if sub_type is not None: -213 if passed_type == dict: -214 for sub_key, value in obj.items(): -215 self.__check_type__(value, sub_type, f"{key}[{sub_key}]") -216 else: -217 for sub_key, value in enumerate(obj): -218 self.__check_type__(value, sub_type, f"{key}[{sub_key}]") -219 -220 def __repr__(self): -221 return f"<type_enforced {self.__fn__.__module__}.{self.__fn__.__qualname__} object at {hex(id(self))}>" -222 -223 -224def Enforcer(clsFnMethod): -225 """ -226 A wrapper to enforce types within a function or method given argument annotations. -227 -228 Each wrapped item is converted into a special `FunctionMethodEnforcer` class object that validates the passed parameters for the function or method when it is called. If a function or method that is passed does not have any annotations, it is not converted into a `FunctionMethodEnforcer` class as no validation is possible. -229 -230 If wrapping a class, all methods in the class that meet any of the following criteria will be wrapped individually: -231 -232 - Methods with `__call__` -233 - Methods wrapped with `staticmethod` (if python >= 3.10) -234 - Methods wrapped with `classmethod` (if python >= 3.10) -235 -236 Requires: -237 -238 - `clsFnMethod`: -239 - What: The class, function or method that should have input types enforced -240 - Type: function | method | class +162 Also stores the calling (__get__) `obj` to be passed as an initial argument for `__call__` such that methods can pass `self` correctly. +163 """ +164 +165 @wraps(self.__fn__) +166 def __get_fn__(*args, **kwargs): +167 return self.__call__(*args, **kwargs) +168 +169 self.__outer_self__ = obj +170 return __get_fn__ +171 +172 def __check_method_function__(self): +173 """ +174 Validate that `self.__fn__` is a method or function +175 """ +176 if not isinstance(self.__fn__, (MethodType, FunctionType)): +177 raise Exception( +178 f"A non function/method was passed to Enforcer. See the stack trace above for more information." +179 ) +180 +181 def __call__(self, *args, **kwargs): +182 """ +183 This method is used to validate the passed inputs and return the output of the wrapped function or method. +184 """ +185 # Special code to pass self as an initial argument +186 # for validation purposes in methods +187 # See: self.__get__ +188 if self.__outer_self__ is not None: +189 args = (self.__outer_self__, *args) +190 # Create a compreshensive dictionary of assigned variables (order matters) +191 assigned_vars = { +192 **self.__fn_defaults__, +193 **dict(zip(self.__fn__.__code__.co_varnames[: len(args)], args)), +194 **kwargs, +195 } +196 # Validate all listed annotations vs the assigned_vars dictionary +197 for key, value in self.__checkable_types__.items(): +198 self.__check_type__(assigned_vars.get(key), value, key) +199 # Execute the function callable +200 return_value = self.__fn__(*args, **kwargs) +201 # If a return type was passed, validate the returned object +202 if self.__return_type__ is not None: +203 self.__check_type__(return_value, self.__return_type__, "return") +204 return return_value +205 +206 def __check_type__(self, obj, acceptable_types, key): +207 """ +208 Raises an exception the type of a passed `obj` (parameter) is not in the list of supplied `acceptable_types` for the argument. +209 """ +210 if isinstance(obj, type): +211 passed_type = Type[obj] +212 else: +213 passed_type = type(obj) +214 if passed_type not in acceptable_types: +215 # Add special string to store any string to add before acceptable types +216 # in any exception message +217 pre_acceptable_types_str = "" +218 # Special check for Literals +219 if Literal in acceptable_types: +220 if obj in acceptable_types[Literal]: +221 return +222 else: +223 pre_acceptable_types_str = "Literal" +224 acceptable_types = acceptable_types[Literal] +225 passed_type = obj +226 # Raise the exception +227 self.__exception__( +228 f"Type mismatch for typed variable `{key}`. Expected one of the following `{pre_acceptable_types_str}{str(list(acceptable_types.keys()))}` but got `{passed_type}` instead." +229 ) +230 sub_type = acceptable_types.get(passed_type) +231 if sub_type is not None: +232 if passed_type == dict: +233 for sub_key, value in obj.items(): +234 self.__check_type__(value, sub_type, f"{key}[{sub_key}]") +235 else: +236 for sub_key, value in enumerate(obj): +237 self.__check_type__(value, sub_type, f"{key}[{sub_key}]") +238 +239 def __repr__(self): +240 return f"<type_enforced {self.__fn__.__module__}.{self.__fn__.__qualname__} object at {hex(id(self))}>" 241 -242 Example Use: -243 ``` -244 >>> import type_enforced -245 >>> @type_enforced.Enforcer -246 ... def my_fn(a: int , b: [int, str] =2, c: int =3) -> None: -247 ... pass -248 ... -249 >>> my_fn(a=1, b=2, c=3) -250 >>> my_fn(a=1, b='2', c=3) -251 >>> my_fn(a='a', b=2, c=3) -252 Traceback (most recent call last): -253 File "<stdin>", line 1, in <module> -254 File "/home/conmak/development/personal/type_enforced/type_enforced/enforcer.py", line 85, in __call__ -255 self.__check_type__(assigned_vars.get(key), value, key) -256 File "/home/conmak/development/personal/type_enforced/type_enforced/enforcer.py", line 107, in __check_type__ -257 self.__exception__( -258 File "/home/conmak/development/personal/type_enforced/type_enforced/enforcer.py", line 34, in __exception__ -259 raise Exception(f"({self.__fn__.__qualname__}): {message}") -260 Exception: (my_fn): Type mismatch for typed variable `a`. Expected one of the following `[<class 'int'>]` but got `<class 'str'>` instead. -261 ``` -262 """ -263 if isinstance( -264 clsFnMethod, (staticmethod, classmethod, FunctionType, MethodType) -265 ): -266 # Only apply the enforcer if annotations are specified -267 if getattr(clsFnMethod, "__annotations__", {}) == {}: -268 return clsFnMethod -269 elif isinstance(clsFnMethod, staticmethod): -270 return staticmethod(FunctionMethodEnforcer(clsFnMethod.__func__)) -271 elif isinstance(clsFnMethod, classmethod): -272 return classmethod(FunctionMethodEnforcer(clsFnMethod.__func__)) -273 elif isinstance(clsFnMethod, (FunctionType, MethodType)): -274 return FunctionMethodEnforcer(clsFnMethod) -275 else: -276 for key, value in clsFnMethod.__dict__.items(): -277 if hasattr(value, "__call__") or isinstance( -278 value, (classmethod, staticmethod) -279 ): -280 setattr(clsFnMethod, key, Enforcer(value)) -281 return clsFnMethod +242 +243def Enforcer(clsFnMethod, enabled): +244 """ +245 A wrapper to enforce types within a function or method given argument annotations. +246 +247 Each wrapped item is converted into a special `FunctionMethodEnforcer` class object that validates the passed parameters for the function or method when it is called. If a function or method that is passed does not have any annotations, it is not converted into a `FunctionMethodEnforcer` class as no validation is possible. +248 +249 If wrapping a class, all methods in the class that meet any of the following criteria will be wrapped individually: +250 +251 - Methods with `__call__` +252 - Methods wrapped with `staticmethod` (if python >= 3.10) +253 - Methods wrapped with `classmethod` (if python >= 3.10) +254 +255 Requires: +256 +257 - `clsFnMethod`: +258 - What: The class, function or method that should have input types enforced +259 - Type: function | method | class +260 +261 Example Use: +262 ``` +263 >>> import type_enforced +264 >>> @type_enforced.Enforcer +265 ... def my_fn(a: int , b: [int, str] =2, c: int =3) -> None: +266 ... pass +267 ... +268 >>> my_fn(a=1, b=2, c=3) +269 >>> my_fn(a=1, b='2', c=3) +270 >>> my_fn(a='a', b=2, c=3) +271 Traceback (most recent call last): +272 File "<stdin>", line 1, in <module> +273 File "/home/conmak/development/personal/type_enforced/type_enforced/enforcer.py", line 85, in __call__ +274 self.__check_type__(assigned_vars.get(key), value, key) +275 File "/home/conmak/development/personal/type_enforced/type_enforced/enforcer.py", line 107, in __check_type__ +276 self.__exception__( +277 File "/home/conmak/development/personal/type_enforced/type_enforced/enforcer.py", line 34, in __exception__ +278 raise Exception(f"({self.__fn__.__qualname__}): {message}") +279 Exception: (my_fn): Type mismatch for typed variable `a`. Expected one of the following `[<class 'int'>]` but got `<class 'str'>` instead. +280 ``` +281 """ +282 if not hasattr(clsFnMethod, "__enforcer_enabled__"): +283 clsFnMethod.__enforcer_enabled__ = enabled +284 if clsFnMethod.__enforcer_enabled__ == False: +285 return clsFnMethod +286 if isinstance( +287 clsFnMethod, (staticmethod, classmethod, FunctionType, MethodType) +288 ): +289 # Only apply the enforcer if annotations are specified +290 if getattr(clsFnMethod, "__annotations__", {}) == {}: +291 return clsFnMethod +292 elif isinstance(clsFnMethod, staticmethod): +293 return staticmethod(FunctionMethodEnforcer(clsFnMethod.__func__)) +294 elif isinstance(clsFnMethod, classmethod): +295 return classmethod(FunctionMethodEnforcer(clsFnMethod.__func__)) +296 elif isinstance(clsFnMethod, (FunctionType, MethodType)): +297 return FunctionMethodEnforcer(clsFnMethod) +298 elif hasattr(clsFnMethod, "__dict__"): +299 for key, value in clsFnMethod.__dict__.items(): +300 if hasattr(value, "__call__") or isinstance( +301 value, (classmethod, staticmethod) +302 ): +303 setattr(clsFnMethod, key, Enforcer(value, enabled=enabled)) +304 return clsFnMethod +305 else: +306 raise Exception( +307 "Enforcer can only be used on class methods, functions, or classes." +308 ) +309 +310 +311Enforcer = Partial(Enforcer, enabled=True)
16class FunctionMethodEnforcer: - 17 def __init__(self, __fn__): - 18 """ - 19 Initialize a FunctionMethodEnforce class object as a wrapper for a passed function `__fn__`. - 20 - 21 Requires: - 22 - 23 - `__fn__`: - 24 - What: The function to enforce - 25 - Type: function | method | class - 26 """ - 27 update_wrapper(self, __fn__) - 28 self.__fn__ = __fn__ - 29 self.__outer_self__ = None - 30 # Validate that the passed function or method is a method or function - 31 self.__check_method_function__() - 32 # Get input defaults for the function or method - 33 self.__get_defaults__() - 34 # Get a dictionary of all annotations as checkable types - 35 self.__checkable_types__ = { - 36 key: self.__get_checkable_type__(value) - 37 for key, value in self.__annotations__.items() - 38 } - 39 self.__return_type__ = self.__checkable_types__.pop("return", None) - 40 - 41 def __get_defaults__(self): - 42 """ - 43 Get the default values of the passed function or method and store them in `self.__fn_defaults__`. - 44 """ - 45 # Determine assigned variables as they were passed in - 46 # See https://stackoverflow.com/a/71884467/12014156 - 47 if self.__fn__.__kwdefaults__ is not None: - 48 # __defaults__ are not used if *args are present necessitating this line - 49 self.__fn_defaults__ = self.__fn__.__kwdefaults__ - 50 elif self.__fn__.__defaults__ is not None: - 51 # Get the list of variable names (omittiting **kwargs var if present) - 52 varnames = list(self.__fn__.__code__.co_varnames)[ - 53 : self.__fn__.__code__.co_argcount - 54 ] - 55 # Create a dictionary of default values - 56 self.__fn_defaults__ = dict( - 57 zip( - 58 varnames[-len(self.__fn__.__defaults__) :], - 59 self.__fn__.__defaults__, - 60 ) - 61 ) - 62 else: - 63 self.__fn_defaults__ = {} - 64 - 65 def __get_checkable_type__(self, item_annotation): - 66 """ - 67 Gets the checkable type as a nested dict for a passed annotation. - 68 """ - 69 valid_types = {} - 70 if not isinstance(item_annotation, (list, tuple)): - 71 item_annotation = [item_annotation] - 72 for valid_type in item_annotation: - 73 # Special code to replace None with NoneType - 74 if valid_type is None: - 75 valid_types[type(None)] = None - 76 continue - 77 elif hasattr(valid_type, "__origin__"): - 78 # Special code for iterable types (e.g. list, tuple, dict, set) including typing iterables - 79 if valid_type.__origin__ in [list, tuple, dict, set]: - 80 valid_types[ - 81 valid_type.__origin__ - 82 ] = self.__get_checkable_type__(valid_type.__args__) - 83 # Handle any generic aliases - 84 elif isinstance(valid_type, GenericAlias): - 85 valid_types[valid_type.__origin__] = None - 86 # Handle Union Types (e.g. Union, Optional, ...) - 87 elif valid_type.__origin__ == Union: - 88 valid_types.update( +@@ -581,29 +622,29 @@24class FunctionMethodEnforcer: + 25 def __init__(self, __fn__): + 26 """ + 27 Initialize a FunctionMethodEnforce class object as a wrapper for a passed function `__fn__`. + 28 + 29 Requires: + 30 + 31 - `__fn__`: + 32 - What: The function to enforce + 33 - Type: function | method | class + 34 """ + 35 update_wrapper(self, __fn__) + 36 self.__fn__ = __fn__ + 37 self.__outer_self__ = None + 38 # Validate that the passed function or method is a method or function + 39 self.__check_method_function__() + 40 # Get input defaults for the function or method + 41 self.__get_defaults__() + 42 # Get a dictionary of all annotations as checkable types + 43 self.__checkable_types__ = { + 44 key: self.__get_checkable_type__(value) + 45 for key, value in self.__annotations__.items() + 46 } + 47 self.__return_type__ = self.__checkable_types__.pop("return", None) + 48 + 49 def __get_defaults__(self): + 50 """ + 51 Get the default values of the passed function or method and store them in `self.__fn_defaults__`. + 52 """ + 53 # Determine assigned variables as they were passed in + 54 # See https://stackoverflow.com/a/71884467/12014156 + 55 if self.__fn__.__kwdefaults__ is not None: + 56 # __defaults__ are not used if *args are present necessitating this line + 57 self.__fn_defaults__ = self.__fn__.__kwdefaults__ + 58 elif self.__fn__.__defaults__ is not None: + 59 # Get the list of variable names (omittiting **kwargs var if present) + 60 varnames = list(self.__fn__.__code__.co_varnames)[ + 61 : self.__fn__.__code__.co_argcount + 62 ] + 63 # Create a dictionary of default values + 64 self.__fn_defaults__ = dict( + 65 zip( + 66 varnames[-len(self.__fn__.__defaults__) :], + 67 self.__fn__.__defaults__, + 68 ) + 69 ) + 70 else: + 71 self.__fn_defaults__ = {} + 72 + 73 def __get_checkable_type__(self, item_annotation): + 74 """ + 75 Gets the checkable type as a nested dict for a passed annotation. + 76 """ + 77 valid_types = {} + 78 if not isinstance(item_annotation, (list, tuple)): + 79 item_annotation = [item_annotation] + 80 for valid_type in item_annotation: + 81 # Special code to replace None with NoneType + 82 if valid_type is None: + 83 valid_types[type(None)] = None + 84 continue + 85 elif hasattr(valid_type, "__origin__"): + 86 # Special code for iterable types (e.g. list, tuple, dict, set) including typing iterables + 87 if valid_type.__origin__ in [list, tuple, dict, set]: + 88 valid_types[valid_type.__origin__] = ( 89 self.__get_checkable_type__(valid_type.__args__) 90 ) - 91 # Handle Literals - 92 # Note: These will be handled separately in the self.__check_type__ - 93 # as the object is validated and not its type. - 94 elif valid_type.__origin__ == Literal: - 95 valid_types = { - 96 Literal: {i: None for i in valid_type.__args__} - 97 } - 98 - 99 # Handle Sized objects -100 elif valid_type == Sized: -101 valid_types = { -102 list: None, -103 tuple: None, -104 dict: None, -105 set: None, -106 str: None, -107 bytes: None, -108 bytearray: None, -109 memoryview: None, -110 range: None, -111 # Allow nested types to be passed as well -112 **valid_types, -113 } -114 # Handle uninitialized class type objects (e.g. MyCustomClass) -115 else: -116 valid_types[valid_type] = None -117 # Handle special '|' syntax for Union Types -118 elif isinstance(valid_type, UnionType): -119 valid_types.update( -120 self.__get_checkable_type__(valid_type.__args__) -121 ) -122 else: -123 valid_types[valid_type] = None -124 return valid_types -125 -126 def __exception__(self, message): -127 """ -128 Usage: -129 -130 - Creates a class based exception message -131 -132 Requires: -133 -134 - `message`: -135 - Type: str -136 - What: The message to warn users with -137 """ -138 raise TypeError(f"({self.__fn__.__qualname__}): {message}") -139 -140 def __get__(self, obj, objtype): -141 """ -142 Overwrite standard __get__ method to return __call__ instead for wrapped class methods. -143 -144 Also stores the calling (__get__) `obj` to be passed as an initial argument for `__call__` such that methods can pass `self` correctly. -145 """ -146 -147 @wraps(self.__fn__) -148 def __get_fn__(*args, **kwargs): -149 return self.__call__(*args, **kwargs) + 91 # Handle any generic aliases + 92 elif isinstance(valid_type, GenericAlias): + 93 valid_types[valid_type.__origin__] = None + 94 # Handle Union Types (e.g. Union, Optional, ...) + 95 elif valid_type.__origin__ == Union: + 96 valid_types.update( + 97 self.__get_checkable_type__(valid_type.__args__) + 98 ) + 99 # Handle Literals +100 # Note: These will be handled separately in the self.__check_type__ +101 # as the object is validated and not its type. +102 elif valid_type.__origin__ == Literal: +103 valid_types = { +104 Literal: {i: None for i in valid_type.__args__} +105 } +106 +107 # Handle Sized objects +108 elif valid_type == Sized: +109 valid_types = { +110 list: None, +111 tuple: None, +112 dict: None, +113 set: None, +114 str: None, +115 bytes: None, +116 bytearray: None, +117 memoryview: None, +118 range: None, +119 # Allow nested types to be passed as well +120 **valid_types, +121 } +122 # Handle uninitialized class type objects (e.g. MyCustomClass) +123 elif valid_type == Callable: +124 valid_types = { +125 staticmethod: None, +126 classmethod: None, +127 FunctionType: None, +128 BuiltinFunctionType: None, +129 MethodType: None, +130 BuiltinMethodType: None, +131 GeneratorType: None, +132 **valid_types, +133 } +134 else: +135 valid_types[valid_type] = None +136 # Handle special '|' syntax for Union Types +137 elif isinstance(valid_type, UnionType): +138 valid_types.update( +139 self.__get_checkable_type__(valid_type.__args__) +140 ) +141 else: +142 valid_types[valid_type] = None +143 return valid_types +144 +145 def __exception__(self, message): +146 """ +147 Usage: +148 +149 - Creates a class based exception message 150 -151 self.__outer_self__ = obj -152 return __get_fn__ -153 -154 def __check_method_function__(self): -155 """ -156 Validate that `self.__fn__` is a method or function -157 """ -158 if not isinstance(self.__fn__, (MethodType, FunctionType)): -159 raise Exception( -160 f"A non function/method was passed to Enforcer. See the stack trace above for more information." -161 ) +151 Requires: +152 +153 - `message`: +154 - Type: str +155 - What: The message to warn users with +156 """ +157 raise TypeError(f"({self.__fn__.__qualname__}): {message}") +158 +159 def __get__(self, obj, objtype): +160 """ +161 Overwrite standard __get__ method to return __call__ instead for wrapped class methods. 162 -163 def __call__(self, *args, **kwargs): -164 """ -165 This method is used to validate the passed inputs and return the output of the wrapped function or method. -166 """ -167 # Special code to pass self as an initial argument -168 # for validation purposes in methods -169 # See: self.__get__ -170 if self.__outer_self__ is not None: -171 args = (self.__outer_self__, *args) -172 # Create a compreshensive dictionary of assigned variables (order matters) -173 assigned_vars = { -174 **self.__fn_defaults__, -175 **dict(zip(self.__fn__.__code__.co_varnames[: len(args)], args)), -176 **kwargs, -177 } -178 # Validate all listed annotations vs the assigned_vars dictionary -179 for key, value in self.__checkable_types__.items(): -180 self.__check_type__(assigned_vars.get(key), value, key) -181 # Execute the function callable -182 return_value = self.__fn__(*args, **kwargs) -183 # If a return type was passed, validate the returned object -184 if self.__return_type__ is not None: -185 self.__check_type__(return_value, self.__return_type__, "return") -186 return return_value -187 -188 def __check_type__(self, obj, acceptable_types, key): -189 """ -190 Raises an exception the type of a passed `obj` (parameter) is not in the list of supplied `acceptable_types` for the argument. -191 """ -192 if isinstance(obj, type): -193 passed_type = Type[obj] -194 else: -195 passed_type = type(obj) -196 if passed_type not in acceptable_types: -197 # Add special string to store any string to add before acceptable types -198 # in any exception message -199 pre_acceptable_types_str = "" -200 # Special check for Literals -201 if Literal in acceptable_types: -202 if obj in acceptable_types[Literal]: -203 return -204 else: -205 pre_acceptable_types_str = "Literal" -206 acceptable_types = acceptable_types[Literal] -207 passed_type = obj -208 # Raise the exception -209 self.__exception__( -210 f"Type mismatch for typed variable `{key}`. Expected one of the following `{pre_acceptable_types_str}{str(list(acceptable_types.keys()))}` but got `{passed_type}` instead." -211 ) -212 sub_type = acceptable_types.get(passed_type) -213 if sub_type is not None: -214 if passed_type == dict: -215 for sub_key, value in obj.items(): -216 self.__check_type__(value, sub_type, f"{key}[{sub_key}]") -217 else: -218 for sub_key, value in enumerate(obj): -219 self.__check_type__(value, sub_type, f"{key}[{sub_key}]") -220 -221 def __repr__(self): -222 return f"<type_enforced {self.__fn__.__module__}.{self.__fn__.__qualname__} object at {hex(id(self))}>" +163 Also stores the calling (__get__) `obj` to be passed as an initial argument for `__call__` such that methods can pass `self` correctly. +164 """ +165 +166 @wraps(self.__fn__) +167 def __get_fn__(*args, **kwargs): +168 return self.__call__(*args, **kwargs) +169 +170 self.__outer_self__ = obj +171 return __get_fn__ +172 +173 def __check_method_function__(self): +174 """ +175 Validate that `self.__fn__` is a method or function +176 """ +177 if not isinstance(self.__fn__, (MethodType, FunctionType)): +178 raise Exception( +179 f"A non function/method was passed to Enforcer. See the stack trace above for more information." +180 ) +181 +182 def __call__(self, *args, **kwargs): +183 """ +184 This method is used to validate the passed inputs and return the output of the wrapped function or method. +185 """ +186 # Special code to pass self as an initial argument +187 # for validation purposes in methods +188 # See: self.__get__ +189 if self.__outer_self__ is not None: +190 args = (self.__outer_self__, *args) +191 # Create a compreshensive dictionary of assigned variables (order matters) +192 assigned_vars = { +193 **self.__fn_defaults__, +194 **dict(zip(self.__fn__.__code__.co_varnames[: len(args)], args)), +195 **kwargs, +196 } +197 # Validate all listed annotations vs the assigned_vars dictionary +198 for key, value in self.__checkable_types__.items(): +199 self.__check_type__(assigned_vars.get(key), value, key) +200 # Execute the function callable +201 return_value = self.__fn__(*args, **kwargs) +202 # If a return type was passed, validate the returned object +203 if self.__return_type__ is not None: +204 self.__check_type__(return_value, self.__return_type__, "return") +205 return return_value +206 +207 def __check_type__(self, obj, acceptable_types, key): +208 """ +209 Raises an exception the type of a passed `obj` (parameter) is not in the list of supplied `acceptable_types` for the argument. +210 """ +211 if isinstance(obj, type): +212 passed_type = Type[obj] +213 else: +214 passed_type = type(obj) +215 if passed_type not in acceptable_types: +216 # Add special string to store any string to add before acceptable types +217 # in any exception message +218 pre_acceptable_types_str = "" +219 # Special check for Literals +220 if Literal in acceptable_types: +221 if obj in acceptable_types[Literal]: +222 return +223 else: +224 pre_acceptable_types_str = "Literal" +225 acceptable_types = acceptable_types[Literal] +226 passed_type = obj +227 # Raise the exception +228 self.__exception__( +229 f"Type mismatch for typed variable `{key}`. Expected one of the following `{pre_acceptable_types_str}{str(list(acceptable_types.keys()))}` but got `{passed_type}` instead." +230 ) +231 sub_type = acceptable_types.get(passed_type) +232 if sub_type is not None: +233 if passed_type == dict: +234 for sub_key, value in obj.items(): +235 self.__check_type__(value, sub_type, f"{key}[{sub_key}]") +236 else: +237 for sub_key, value in enumerate(obj): +238 self.__check_type__(value, sub_type, f"{key}[{sub_key}]") +239 +240 def __repr__(self): +241 return f"<type_enforced {self.__fn__.__module__}.{self.__fn__.__qualname__} object at {hex(id(self))}>"
17 def __init__(self, __fn__): -18 """ -19 Initialize a FunctionMethodEnforce class object as a wrapper for a passed function `__fn__`. -20 -21 Requires: -22 -23 - `__fn__`: -24 - What: The function to enforce -25 - Type: function | method | class -26 """ -27 update_wrapper(self, __fn__) -28 self.__fn__ = __fn__ -29 self.__outer_self__ = None -30 # Validate that the passed function or method is a method or function -31 self.__check_method_function__() -32 # Get input defaults for the function or method -33 self.__get_defaults__() -34 # Get a dictionary of all annotations as checkable types -35 self.__checkable_types__ = { -36 key: self.__get_checkable_type__(value) -37 for key, value in self.__annotations__.items() -38 } -39 self.__return_type__ = self.__checkable_types__.pop("return", None) +@@ -621,77 +662,14 @@25 def __init__(self, __fn__): +26 """ +27 Initialize a FunctionMethodEnforce class object as a wrapper for a passed function `__fn__`. +28 +29 Requires: +30 +31 - `__fn__`: +32 - What: The function to enforce +33 - Type: function | method | class +34 """ +35 update_wrapper(self, __fn__) +36 self.__fn__ = __fn__ +37 self.__outer_self__ = None +38 # Validate that the passed function or method is a method or function +39 self.__check_method_function__() +40 # Get input defaults for the function or method +41 self.__get_defaults__() +42 # Get a dictionary of all annotations as checkable types +43 self.__checkable_types__ = { +44 key: self.__get_checkable_type__(value) +45 for key, value in self.__annotations__.items() +46 } +47 self.__return_type__ = self.__checkable_types__.pop("return", None)
225def Enforcer(clsFnMethod): -226 """ -227 A wrapper to enforce types within a function or method given argument annotations. -228 -229 Each wrapped item is converted into a special `FunctionMethodEnforcer` class object that validates the passed parameters for the function or method when it is called. If a function or method that is passed does not have any annotations, it is not converted into a `FunctionMethodEnforcer` class as no validation is possible. -230 -231 If wrapping a class, all methods in the class that meet any of the following criteria will be wrapped individually: -232 -233 - Methods with `__call__` -234 - Methods wrapped with `staticmethod` (if python >= 3.10) -235 - Methods wrapped with `classmethod` (if python >= 3.10) -236 -237 Requires: -238 -239 - `clsFnMethod`: -240 - What: The class, function or method that should have input types enforced -241 - Type: function | method | class -242 -243 Example Use: -244 ``` -245 >>> import type_enforced -246 >>> @type_enforced.Enforcer -247 ... def my_fn(a: int , b: [int, str] =2, c: int =3) -> None: -248 ... pass -249 ... -250 >>> my_fn(a=1, b=2, c=3) -251 >>> my_fn(a=1, b='2', c=3) -252 >>> my_fn(a='a', b=2, c=3) -253 Traceback (most recent call last): -254 File "<stdin>", line 1, in <module> -255 File "/home/conmak/development/personal/type_enforced/type_enforced/enforcer.py", line 85, in __call__ -256 self.__check_type__(assigned_vars.get(key), value, key) -257 File "/home/conmak/development/personal/type_enforced/type_enforced/enforcer.py", line 107, in __check_type__ -258 self.__exception__( -259 File "/home/conmak/development/personal/type_enforced/type_enforced/enforcer.py", line 34, in __exception__ -260 raise Exception(f"({self.__fn__.__qualname__}): {message}") -261 Exception: (my_fn): Type mismatch for typed variable `a`. Expected one of the following `[<class 'int'>]` but got `<class 'str'>` instead. -262 ``` -263 """ -264 if isinstance( -265 clsFnMethod, (staticmethod, classmethod, FunctionType, MethodType) -266 ): -267 # Only apply the enforcer if annotations are specified -268 if getattr(clsFnMethod, "__annotations__", {}) == {}: -269 return clsFnMethod -270 elif isinstance(clsFnMethod, staticmethod): -271 return staticmethod(FunctionMethodEnforcer(clsFnMethod.__func__)) -272 elif isinstance(clsFnMethod, classmethod): -273 return classmethod(FunctionMethodEnforcer(clsFnMethod.__func__)) -274 elif isinstance(clsFnMethod, (FunctionType, MethodType)): -275 return FunctionMethodEnforcer(clsFnMethod) -276 else: -277 for key, value in clsFnMethod.__dict__.items(): -278 if hasattr(value, "__call__") or isinstance( -279 value, (classmethod, staticmethod) -280 ): -281 setattr(clsFnMethod, key, Enforcer(value)) -282 return clsFnMethod -
A wrapper to enforce types within a function or method given argument annotations.
Each wrapped item is converted into a special FunctionMethodEnforcer
class object that validates the passed parameters for the function or method when it is called. If a function or method that is passed does not have any annotations, it is not converted into a FunctionMethodEnforcer
class as no validation is possible.
1def WithSubclasses(obj): - 2 """ - 3 A special helper function to allow a class type to be passed and also allow all subclasses of that type. +@@ -94,31 +163,31 @@1import types + 2from functools import update_wrapper + 3 4 - 5 Requires: - 6 - 7 - `obj`: - 8 - What: An uninitialized class that should also be considered type correct if a subclass is passed. - 9 - Type: Any Uninitialized class + 5def WithSubclasses(obj): + 6 """ + 7 A special helper function to allow a class type to be passed and also allow all subclasses of that type. + 8 + 9 Requires: 10 -11 Returns: -12 -13 - `out`: -14 - What: A list of all of the subclasses (recursively parsed) -15 - Type: list of strs +11 - `obj`: +12 - What: An uninitialized class that should also be considered type correct if a subclass is passed. +13 - Type: Any Uninitialized class +14 +15 Returns: 16 -17 -18 Notes: -19 -20 - From a functional perspective, this recursively get the subclasses for an uninitialised class (type). -21 """ -22 out = [obj] -23 for i in obj.__subclasses__(): -24 out += WithSubclasses(i) -25 return out +17 - `out`: +18 - What: A list of all of the subclasses (recursively parsed) +19 - Type: list of strs +20 +21 +22 Notes: +23 +24 - From a functional perspective, this recursively gets the subclasses for an uninitialised class (type). +25 """ +26 out = [obj] +27 for i in obj.__subclasses__(): +28 out += WithSubclasses(i) +29 return out +30 +31 +32class Partial: +33 """ +34 A special class wrapper to allow for easy partial function wrappings and calls. +35 """ +36 +37 def __init__( +38 self, +39 __fn__, +40 *__args__, +41 **__kwargs__, +42 ): +43 update_wrapper(self, __fn__) +44 self.__fn__ = __fn__ +45 self.__args__ = __args__ +46 self.__kwargs__ = __kwargs__ +47 self.__fnArity__ = self.__getFnArity__() +48 self.__arity__ = self.__getArity__(__args__, __kwargs__) +49 +50 def __exception__(self, message): +51 pre_message = ( +52 f"({self.__fn__.__module__}.{self.__fn__.__qualname__}_partial): " +53 ) +54 raise Exception(pre_message + message) +55 +56 def __call__(self, *args, **kwargs): +57 new_args = self.__args__ + args +58 new_kwargs = {**self.__kwargs__, **kwargs} +59 self.__arity__ = self.__getArity__(new_args, new_kwargs) +60 if self.__arity__ < 0: +61 self.__exception__("Too many arguments were supplied") +62 if self.__arity__ == 0: +63 results = self.__fn__(*new_args, **new_kwargs) +64 return results +65 return Partial( +66 self.__fn__, +67 *new_args, +68 **new_kwargs, +69 ) +70 +71 def __repr__(self): +72 return f"<Partial {self.__fn__.__module__}.{self.__fn__.__qualname__} object at {hex(id(self))}>" +73 +74 def __getArity__(self, args, kwargs): +75 return self.__fnArity__ - (len(args) + len(kwargs)) +76 +77 def __getFnArity__(self): +78 if not isinstance(self.__fn__, (types.MethodType, types.FunctionType)): +79 self.__exception__( +80 "A non function was passed as a function and does not have any arity. See the stack trace above for more information." +81 ) +82 extra_method_input_count = ( +83 1 if isinstance(self.__fn__, (types.MethodType)) else 0 +84 ) +85 return self.__fn__.__code__.co_argcount - extra_method_input_count
2def WithSubclasses(obj): - 3 """ - 4 A special helper function to allow a class type to be passed and also allow all subclasses of that type. - 5 - 6 Requires: - 7 - 8 - `obj`: - 9 - What: An uninitialized class that should also be considered type correct if a subclass is passed. -10 - Type: Any Uninitialized class +@@ -140,19 +209,120 @@6def WithSubclasses(obj): + 7 """ + 8 A special helper function to allow a class type to be passed and also allow all subclasses of that type. + 9 +10 Requires: 11 -12 Returns: -13 -14 - `out`: -15 - What: A list of all of the subclasses (recursively parsed) -16 - Type: list of strs +12 - `obj`: +13 - What: An uninitialized class that should also be considered type correct if a subclass is passed. +14 - Type: Any Uninitialized class +15 +16 Returns: 17 -18 -19 Notes: -20 -21 - From a functional perspective, this recursively get the subclasses for an uninitialised class (type). -22 """ -23 out = [obj] -24 for i in obj.__subclasses__(): -25 out += WithSubclasses(i) -26 return out +18 - `out`: +19 - What: A list of all of the subclasses (recursively parsed) +20 - Type: list of strs +21 +22 +23 Notes: +24 +25 - From a functional perspective, this recursively gets the subclasses for an uninitialised class (type). +26 """ +27 out = [obj] +28 for i in obj.__subclasses__(): +29 out += WithSubclasses(i) +30 return out
out
:
- What: A list of all of the subclasses (recursively parsed)
-- Type: list of strs
+- Type: list of strs
Notes:
-
- From a functional perspective, this recursively get the subclasses for an uninitialised class (type).
+- From a functional perspective, this recursively gets the subclasses for an uninitialised class (type).
33class Partial: +34 """ +35 A special class wrapper to allow for easy partial function wrappings and calls. +36 """ +37 +38 def __init__( +39 self, +40 __fn__, +41 *__args__, +42 **__kwargs__, +43 ): +44 update_wrapper(self, __fn__) +45 self.__fn__ = __fn__ +46 self.__args__ = __args__ +47 self.__kwargs__ = __kwargs__ +48 self.__fnArity__ = self.__getFnArity__() +49 self.__arity__ = self.__getArity__(__args__, __kwargs__) +50 +51 def __exception__(self, message): +52 pre_message = ( +53 f"({self.__fn__.__module__}.{self.__fn__.__qualname__}_partial): " +54 ) +55 raise Exception(pre_message + message) +56 +57 def __call__(self, *args, **kwargs): +58 new_args = self.__args__ + args +59 new_kwargs = {**self.__kwargs__, **kwargs} +60 self.__arity__ = self.__getArity__(new_args, new_kwargs) +61 if self.__arity__ < 0: +62 self.__exception__("Too many arguments were supplied") +63 if self.__arity__ == 0: +64 results = self.__fn__(*new_args, **new_kwargs) +65 return results +66 return Partial( +67 self.__fn__, +68 *new_args, +69 **new_kwargs, +70 ) +71 +72 def __repr__(self): +73 return f"<Partial {self.__fn__.__module__}.{self.__fn__.__qualname__} object at {hex(id(self))}>" +74 +75 def __getArity__(self, args, kwargs): +76 return self.__fnArity__ - (len(args) + len(kwargs)) +77 +78 def __getFnArity__(self): +79 if not isinstance(self.__fn__, (types.MethodType, types.FunctionType)): +80 self.__exception__( +81 "A non function was passed as a function and does not have any arity. See the stack trace above for more information." +82 ) +83 extra_method_input_count = ( +84 1 if isinstance(self.__fn__, (types.MethodType)) else 0 +85 ) +86 return self.__fn__.__code__.co_argcount - extra_method_input_count +
A special class wrapper to allow for easy partial function wrappings and calls.
+38 def __init__( +39 self, +40 __fn__, +41 *__args__, +42 **__kwargs__, +43 ): +44 update_wrapper(self, __fn__) +45 self.__fn__ = __fn__ +46 self.__args__ = __args__ +47 self.__kwargs__ = __kwargs__ +48 self.__fnArity__ = self.__getFnArity__() +49 self.__arity__ = self.__getArity__(__args__, __kwargs__) +