PlainTools’ Docs§
Welcome to PlainTools’ documentation!
PlainTools is a Python 3 library designed to streamline simple operations, loops and contexts with easy to handle classes and functions.
This documentation site can be accessed from the Python interpreter|environment itself with:
import PlainTools as pt
pt.site(pt) # This will open the PLainToolsDocs.html file!
[Table of Contents]
Numeric Constructor
- The base solution for numberic-related problems.
Statement & Extension Functions
- Powerful, close to native syntax and easy to use.
Debugger & Utility Functions
- Easy debugging management with console operations.
Operator & Instantiated Classes
- Ready-to-use instances of functional objects.
Constructor Classes & Custom Objects
- Custom object constructors.
[Introduction]
The following needs to be considered when reading these docs:
- It is encouraged that you use the suggested convention:
import PlainTools as pt
- It is assumed that you know the basics of Python’s data types.
- Type annotations were made in a more verbose way, with:
X: Integer
- Instead of:
X: int
Unfamiliar types like ‘Real’ can be associated with what meaning they first convey:
- Having a variable declared as:
Y: Real
- Is the same as:
Y: int | float | decimal.Decimal | fractions.Fraction
And is itself similar or very closely related to ‘numbers.Real’.
Any documentation found here can be similarly provided in the Python
context or environment running this module by the use of the
pt.doc()
function as:
- pt.doc(*objs)
Where objs is the desired function(s) or class(es) to obtain documentation from.
This will print the target’s documentation, if any, to the current console
or stdout
in general. Note that pt.doc()
also works with any builtin
object as well as third-party ones, given they have any type of docstring themselves.
[Resources & Credits]
- Disclaimer: LLM (AI) Use:
ChatGPT, Codeium and Gemini (The later not credited as it did not “contribute” directly to the codebase) were used in this project development.
If you, your university or your company (in general, if the target for this library’s use) does have any restrictions, implicit or explicit, against the use of LLMs in production | academic coding, please avert from using this library.
Any code “contributed” by or taken from any LLM (AI) use, prompted directly or indirectly, was heavily debugged and tested (to the best of my personal capacity).
If any code comes across as sluggish, unnoptimized or just bad, please let me know by raising an issue or DMing me at GitHub (@gabrielmsilva00), or email me at @gabrielmaia.silva00@gmail.com.
- For a more clear understanding of the above, you will probably find 40~80% LLM-made code wherever attributes from the following libraries were used:
re
ast
itertools
functools
multiprocessing
- References & Auxiliary Material:
AutoPEP8, code formatting;
Sphinx, documentation;
Sphinx-Design, styling;
StackOverflow, definitions, concepts;
W3Schools, theories, fundamentals, methods;
OpenAI’s ChatGPT, definitions, debugging;
Claude AI, additional debugging;
Codeium AI, autocompletion, code refactoring & cleaning;
SingleFile, HTML factoring of this Sphinx-generated documentation;
JetBrains Mono, this awesome font!
- Credits & Thanks:
A big thanks to my professor Vitor Tocci, who lectured Introduction to Data Proccessing and introduced me into Python programming when I had little background experience in the matter.
Thanks to my beloved girlfriend Ana Caroline, who tirelessly heard me babble about Python through hours in these past few months where I was still learning and improving much of my understanding of the language. I love you!
Thanks to all of my friends and family who helped me debug the documentation itself (this HTML file) when I had zero Sphinx knowledge. I hope I did well enough and hope to do much more in the future!
Numeric Constructor§
(Goto Table of Contents)
Before anything else, it is important to lay down the documentation for the
base of any numeric-related definition or class. And such is the
pt.pnumber()
function.
- pt.pnumber(*objs) Number | List[Number]: §
Plain Numeric Constructor.
For each input, this function constructs a generic Numeric class instance which dynamically inherits the input’s parent class. This means that all numeric types such as ‘int’, ‘float’, ‘complex’, ‘Decimal’ and ‘Fraction’ given to this function will generate a subclass instance with inheritance from the object’s own numeric class.
Failure to convert the object to a numeric type (contained into the numbers.Number definition) will result in an instance of float(‘nan’) class being returned.
- Examples:
Considering
x = pt.pnumber(1/3)
; - print(x)
0.333...
The
pt.pnumber()
constructor detects repeating decimals.
- x.value
0.3333333333333333
This is used for proper arithmetic operations.
- x.period
3
This is the detected repeating decimal.
- x.fraction
(1, 3)
The fraction part can be used for reconstruction of the numeric object.
- x.type
<class 'float'>
The
x
object dynamically inherited from thefloat
class.
- x.id
2667619486224
# This is an exampleThe direct assigned
id()
of the objectfloat(1/3)
given to the numeric constructor.Please note that this is different than both
id(x)
andid(x.value)
- Args:
- obj: Any | Iterable[Any]
Object(s) to
pt.SEVAL(obj)
into a numeric type.Failure to safely convert to a numeric type will return
float('nan')
.
- Returns:
- R: Number | List[Number]
Numeric-type instance(s) (of
isinstance(obj, numbers.Number)
).The numeric class created dynamically inherits from the
obj
own class.
- Notes:
It is computationally expensive; Not ideal for long sequences.
Due to the above, you may want to use ‘pt.pround()’ instead.
Formatter Functions§
(Goto Table of Contents)
Formatter functions are intended to take a variety of types as input and output data in a formatted, previsible way.
- pt.plist(*vals) List[Any]: §
Plain List.
Transforms iterable sets into a flat list; Recursive unpacking.
- Pseudocode:
- If one (List) contains other (Lists) inside:
(Unpack) the (Lists) inside, keeping only the (Values).
This repeats until all (Lists) only contains plain (Values).
Return a final (List) containing only the (Values) of everything given.
- Examples:
- plist((1, 2), [3, 4], {5, 6})
[1, 2, 3, 4, 5, 6]
- plist({0: 10, 1: 20, 2: 40})
[10, 20, 40]
- plist({‘A’:10, ‘B’:15, ‘C’:20, ‘D’:{“X”: 100, “Y”: 200, “Z”: 300}})
[10, 15, 20, 100, 200, 300]
- Args:
- *vals: Any | Iterable[Any]
Data entries to be flattened.
- Returns:
- R: List[Any]
Flat list containing the data entries.
- pt.punit(*its) Any | Tuple[Any]: §
Plain Units.
Unpacks single units inside iterable sets;
Returns a single value if there is only one value in the iterable.
- Pseudocode:
- If any given (List) contains a (Single) (Value):
(Unpack) the (List), so it becomes it’s plain (Value).
- If (Final List) contains (Multiple) (Values):
Return (Final List).
- Else, if (Final List) contains a (Single) (Value):
Return (Value).
- Examples:
- punit([5], [3, 2], [[9]])
(5, [3, 2], 9)
- punit([1, 2], 3, (4,))
([1, 2], 3, 4)
- punit([[7, 8]], {9})
([7, 8], 9)
- Args:
- *its: Iterable[Any]
Iterable sets.
- Returns:
- R: Any | Tuple[Any]
A single item or a tuple of items.
- pt.pround(*vals, tol='auto', dcm='auto', prd=4) Number | Iterable[Number] | None: §
Plain Round.
Numeric formatter; Evaluates numeric expressions; Less precise than
pt.pnumber()
, but much faster. Removes floating point imprecision errors with great accuracy; Works well expressing repeating decimals.The ‘tol’ argument is used roughly for the precision of the output. It is designed to work 99.9% of the time, figuratively speaking, with a standard precision of up to 1e-12 when set to ‘auto’, as default.
The ‘dcm’ argument works similarly to the ‘ndigits’ argument found in the ‘round()’ built-in function, and in fact, is used into it along the works. The default setting of ‘auto’ will round the number if any repeating decimals are found, up to 4 repetitions.
- Examples:
- pnumber([8.0, ‘0.1 * 3’, ‘355/113’, ‘math.e’])
[8, 0.3, 3.1415929203539825, 2.718281828459045]
- pnumber(1/3, 10/33, 100/333, 1000/3333)
[0.333, 0.30303, 0.3003003003, 0.3000300030003]
- pnumber(0.1 ** 1e-12)
0.9999999999977
- pnumber(0.1 ** 32) # Fails with ‘auto’ precision tolerance.
0 # float(0.1 ** 32) is 1.0000000000000018e-32
- pnumber(0.1 ** 32, tol=32)
1e-32
- Args:
- *vals: Real | Iterable[Real | String]
Numbers to be formatted.
- Kwargs:
- tol: String | Integer = ‘auto’
Precision of the output;
It is recommended to follow the lowest decimal place.
i.e. tol=64 for a precision of up to 1e-64.
- dcm: String | Integer = ‘auto’
Decimal places of the output;
It is involved in the rounding phase of the function.
‘auto’ rounds repeating decimals up to 4 repetitions;
i.e. pnumber(1/3, dcm=’auto’) == 0.3333
(dcm=16 | dcm=None) end up with the same result.
- Returns:
- R: Real | Iterable[Real] | None
Formatted numbers, None if NaN.
- pt.pdecimals(*nums) Integer: §
Plain Decimals.
Identifies the highest number of decimal places in a set.
If the number has a repeating period (detected by pt.pnumber()), the return value will be float(‘inf’), even if the Python representation of the float(num) is limited to 16 decimal places.
- Pseudocode:
Start (Decimals) as 0.
- (For Each) (Value):
- If (String) of (Number) in (Value) have (‘.’) character:
- (Count) how many (Digits) there is after (‘.’) character.
- If (Digits) is greater than (Decimals):
(Decimals) become number of (Digits).
Return final (Decimals) value.
- Examples:
- pdecimals(1.23, 4.5678, 3.1, 5.67890)
4
- pdecimals(1/3)
inf
- pdecimals(math.pi)
15
- Args:
- [*]nums: Number | Iterable[Number | String]
Numbers to be formatted.
- Returns:
- R: Integer
Highest quantity of decimal places found.
- pt.pstring(*objs, sep=', ') String: §
Plain String.
More comprehensible ‘str()’ operator; Concatenates elements of iterables.
- Pseudocode:
- Check (Type) of (Value):
- If (Type) is (Dictionary):
(Include) the (Keys) and (Values) of (Dictionary) in the (String).
- Else, if (Type) is a (List), (Tuple) or (Set):
(Include) all (Values) in the (String).
- Else, if (Type) is (Something Else):
(Include) the String of (Type) in the (String).
Return final version of (String).
- Examples:
- pstring({0: ‘a’, 1: ‘b’, 2: ‘c’})
‘0: a, 1: b, 2: c’
- pstring([1, 2, 3], (4, 5), {6, 7})
‘1, 2, 3, 4, 5, 6, 7’
- pstring(‘Hello’, [‘world’, ‘!’], sep = ‘ ‘)
‘Hello world !’
- Args:
- *objs: Any | Iterable[Any]
Objects to be converted to string.
- Kwargs:
- sep: String = ‘, ‘
Separator between elements in the final string.
- Returns:
- R: String
Single string containing the concatenated elements.
- pt.pistype(obj, *types) Bool | Tuple[Bool]: §
Plain Type Check.
Checks if the object is an instance of the provided types.
- Pseudocode:
- Check (Type) of (Value) and (Type) of (Asked Types):
- (For Each) (Asked Type):
- If (Type) of (Value) is the same as this (Asked Type):
(Include) (True) in the final (Result)
- Else, if (Type) of (Value) is not the same as this (Asked Type):
(Include) (False) in the final (Result)
Return the final (Result).
- Examples:
- pistype(‘Hello’, String, Iterable, Set)
(True, True, False)
- pistype([1, 2, 3], List, Tuple, Iterable)
(True, False, True)
- pistype(42.0, Number, Integer, Float)
(True, False, True)
- Args:
- obj: Any
Object to be checked against.
- *types: Type
Types to compare using isinstance(obj, type).
- Returns:
- R: Bool | Tuple[Bool]
Sequence of Booleans according to the checks.
- pt.prange(*args, type='list') Iterable[Number]: §
Plain Range.
Simulates the ‘range()’ function from Python 2.x.
Instead of a range object, returns a plain Iterable of specified type.
Stop argument is the de-facto stop, being the last value of list.
Args functionality is the same as standard ‘range()’ built-in function.
- Pseudocode:
- Check for the given (Parameters):
- If there is (One) (Parameter):
Return a (List) (Starting) at (0) and (Stopping) at (Parameter) with an (Step) of (1).
- Else, if there are (Two) (Parameters):
Return a (List) (Starting) at (1st Parameter) and (Stopping) at (2nd Parameter) with a (Step) of (1).
- Else, if there are (Three) (Parameters):
Return a (List) (Starting) at (1st Parameter), (Stopping) at (2nd Parameter) with a (Step) of (3rd Parameter).
- Else, if there are (Four) (Parameters):
Return an (Iterable) of (Type) (4th Parameter), (Starting) at (1st Parameter), (Stopping) at (2nd Parameter) and with a (Step) of (3rd Parameter).
Return the final (Iterable).
- Examples:
- prange(5)
[0, 1, 2, 3, 4]
- prange(5, 2.5, 0.5, ‘tuple’)
(5, 4.5, 4, 3.5, 3, 2.5)
- prange(0, 15, 4, ‘dict’)
{0: 0, 1: 4, 2: 8, 3: 12}
- Args:
- *args: Number
- Functionality varies according to arguments:
A single parameter determines the stop; with start of 1.
Two parameters determines start and stop; with step of 1.
Three parameters determines start, stop and step; returning a list.
Four parameters determines start, stop, step and type
- Kwargs:
- start: Number = None
Start value of the iterable.
- stop: Number = None
Stop value of the iterable.
- step: Number = None
Step value of the iterable.
- type: String = None
Type of the returned iterable (‘list’, ‘tuple’, ‘set’, ‘dict’, ‘cont’).
- Returns:
R: Iterable[Number] = Iterable (defined in ‘get’) containing the range.
- pt.pinterval(*args, type='list') Iterable[Number]: §
Plain Interval.
Generates a list of numeric elements equidistant between them, from start to stop.
- Pseudocode:
- Check for the given (Parameters):
- If there is (One) (Parameter):
Return a (List) (Starting) at (0) and (Stopping) at (100) with (Parameter) (Values).
- Else, if there are (Two) (Parameters):
Return a (List) (Starting) at (0) and (Stopping) at (2nd Parameter) with (1st Parameter) number of (Values).
- Else, if there are (Three) (Parameters):
Return a (List) (Starting) at (2nd Parameter), (Stopping) at (3rd Parameter) with (1st Parameter) number of (Values).
- Else, if there are (Four) (Parameters):
Return an (Iterable) of (Type) (4th Parameter), (Starting) at (2nd Parameter), (Stopping) at (3rd Parameter) and with (1st Parameter) number of (Values).
Return the final (Iterable).
- Examples:
- pinterval(5)
[0, 25, 50, 75, 100]
- pinterval(3, 5)
[0, 2.5, 5]
- pinterval(5, 10, 0, ‘dict’)
{0: 10, 1: 7.5, 2: 5, 3: 2.5, 4: 0}
- Args:
- *args: Number
- Can contain up to four positional arguments:
- One argument: divs;
List of [0, 0±n1, 0±n2, (…), 100] with ‘divs’ elements.
- Two arguments: divs and stop;
List of [0, 0±n1, 0±n2, (…), stop] with ‘divs’ elements.
- Three arguments: divs, start and stop;
List of [start, start±n1, (…), stop] with ‘divs’ elems.
- Four arguments: divs, start, stop and type.
Iterable of type(start, (…), stop) with ‘divs’ elements.
- Kwargs:
- divs: Number = None
Number of elements in the returned Iterable.
- start: Number = None
Start value of the interval (default is 0).
- stop: Number = None
Stop value of the interval.
- type: String = None
Type of the returned collection (‘list’, ‘tuple’, ‘set’, ‘dict’).
- Returns:
- R: Iterable[Number]
List of numeric values with equidistant intervals.
- pt.psequence(*nums, abs_lim=None, rel_lim=10e3) Chain[Real]: §
Plain Sequence.
Generates a numerical sequence based on the provided numbers or patterns.
It supports the use of ellipsis (…) to denote the continuation of the sequence with a defined step or to an optional limit.
- Args:
- *nums: Real | Iterable[Real]
The numbers or patterns used to generate the sequence.
Ellipsis (…) can be used to sign continuation of sequence.
- Kwargs:
- abs_lim: Real = None
The absolute limit for the sequence, if provided.
- rel_lim: Real = 10e3
The relative limit, as a multiplier to the last expressed num.
- Returns:
- R: Chain[Real]
A chain of numbers representing the generated sequence.
- Example:
- psequence(1, 2, 3, …, 10)
Generates the sequence equivalent to (1, 2, …, 9, 10).
- psequence(1, 3, 5, …, abs_lim=150)
Generates the sequence equivalent to (1, 3, …, 147, 149).
- psequence(0.1)
Generates the sequence equiv. to (0.1, 0.2, …, 999.9, 1000).
- Notes:
If an ellipsis (…) is used, the function will infer the step from the preceding numbers in the sequence.
If abs_lim is provided, the sequence will stop when it reaches or exceeds this limit.
If rel_lim is provided, it will be used to calculate the maximum limit based on the last number in the sequence before the ellipsis.
The sequence continues either until the absolute or relative limit is met.
- pt.pindex(target, *its) Integer | None | Tuple[Integer | None]: §
Plain Index.
Returns the index of the first occurrence of ‘target’ in ‘its’.
- Pseudocode:
- Look for (Target) in all (Iterables) provided:
- (For Each) (Iterable):
- If (Target) is found in this (Iterable):
(Include) (Target)’s (Index) in the final (Result).
- Else, if (Target) is not found in this (Iterable):
(Include) (None) in the final (Result).
Return the final (Result).
- Examples:
- pindex(True, (False, False, True))
2
- pindex(5, range(10))
5
- pindex(1, (False, False, True), [‘a’, ‘b’, ‘c’], range(10))
(2, None, 1)
- Args:
- target: Any
Value to search for in the provided iterables.
- *its: Iterable[Any]
One or more iterables to be checked for ‘target’.
- Returns:
- R: Integer | None | Tuple[Integer | None]
Index of the first ‘target’ occurrence into provided iterables.
- pt.pminmax(*vals) Container[String: Number]: §
Plain Min & Max.
Returns the minimum and maximum values from a set of numbers.
- Pseudocode:
- Given any (Values) or (Iterables[Values]):
Return both (Minimum) and (Maximum) from all given (Values).
- Examples:
- pminmax([5, 2, -8, ‘15*2’])
{‘min’: -8, ‘max’: 30}
- pminmax([5, 2, -8, ‘15*2’]).min
-8
- pminmax(1, -2, [‘1.5 * 2’], math.pi)[1][1]
3.141592653589793
- Args:
- *vals: Number | Iterable[Number]
Objects to be compared for their value.
- Returns:
- R: Container[String: Number]
A Container, derived from dict, containing min & max values.
- pt.plen(*iters) Container[String: Integer]: §
Plain Length.
Returns the minimum and maximum sizes of given iterables.
- Pseudocode:
- Given any (Iterables):
Return both (Minimum) and (Maximum) (Size) from all given (Iterables).
- Examples:
- pcount([1, 2, 3], (4, 5), {6})
{‘min’: 1, ‘max’: 3}
- pcount([1, 2, 3, [4, 5], 6], (“ABCDEFGHIJ”, “XYZ”), {}).min
0
- pcount({0: 1, 1: -2, 2: 4, 3: -8, 4: 16, 5: 32}).max
5
- Args:
- *iters: Any | Iterable[Any]
Objects to be counted for their sizes.
- Returns:
- R: Container[String: Integer]
A Container , derived from dict, containing min & max lengths.
- pt.pabs(*nums) Container[String: Number] §
Plain Absolutes.
Identifies the lowest or highest absolute number of a set. Returns a Container with the min, max, original min, original max values.
- Pseudocode:
(Flatten) the input (Values). - Calculate the (Absolute) (Maximum) (Value). - Calculate the (Absolute) (Minimum) (Value). - Identify the (Original) (Maximum) and (Minimum) (Values).
Return a (Container) with (Absolute) and (Original) (Minimum) and (Maximum) (Values).
- Examples:
- x = pabs([5, 8, -2, ‘15*2’])
x == {‘min’:2, ‘max’:30, ‘ogmin’:-2, ‘ogmax’: 30}
x.min == 2
x.ogmin == -2
x.max == x.ogmax == 30
- y = pabs(-1, -2, [‘1.5 * 2’], math.pi)
y[‘min’] == 1
y[‘ogmin’] == -2
y[‘max’] == 3.141592653589793
- zmin, zmax, ztruemin, ztruemax = pabs(prange(-10, 0, 1))
zmin == 0
zmax == 10
ztruemin == -10
ztruemax == 0
- Args:
- *nums: Number | Iterable[Number | String]
Objects to be counted.
- Returns:
- R: Container[String: Number]
A Container, with min, max, original min and original max.
- pt.psum(*nums) Real: §
Plain Sum.
Returns the sum of possible numbers from given sets.
- Examples:
- psum([5, 2, -8, ‘15*2’])
29
- psum(prange(-10, 0))
-55
- psum(Container(John=2.55, Maria=3.14, Paul=1.75))
7.44
- Args:
- *nums: Real | Iterable[Real | String]
Objects to be counted.
- Returns:
- R: Real
Sum of numbers.
- pt.pimport(libs, funs=None) Module | Object | Tuple[Module | Object]: §
Plain Import.
Helper function for local scope importation.
- Pseudocode:
(Split) (Libs) into individual (Module Names).
- (For Each) (Module Name):
- Attempt to (Import) the (Module).
If (Funs) are given, attempt to (Import) only the specified (Objects) from the (Module).
Return the (Imported) (Modules) or (Objects) as (Objects).
- Examples:
- calc = pimport(‘math’)
Allocates ‘calc’ as an alias to the ‘math’ module.
ie: calc.e == math.e
- pi, log = pimport(‘math’,’pi, log’)
Allocates to variables the imported objects (math.pi & math.log).
ie: pi == math.pi
- Args:
- libs: String
Modules to import; separated by comma in the 1st string.
(‘a, b, c’).
- funs: String = None
Objects to import; separated by comma in the 2nd string.
(‘a, b, c’).
- Returns:
- R: Module | Object | Tuple[Module | Object]
Imported modules or objects.
- pt.pframe(depth, outer=False) Frame: §
Plain Frame.
Helper function for getting the frame information in the specified depth.
- Pseudocode:
(Inspect) all the current (Frames).
Return the (Depth)º (Frame), counting from the current (Frame) outwards.
- Examples:
(@file PlainTools.py)
- x = pframe()
x.f_code.co_filename == ‘..\path\to\file\PlainTools.py’
x.f_lineno == (Line number of pframe() call)
x.f_code.co_names == (Tuple of strings of names used in the program)
x.f_locals == Current frame’s locals() dictionary.
x.f_globals == Current frame’s globals() dictionary.
- Args:
- depth: Integer = 1
(Default: 1) How many frames to go in;
Note that this is in reverse order, so a depth=2
inspects the currentframe up until currentframe()[-2]
- Kwargs:
- outer: Bool = False
Determines if the Frame is get from inspect.getouterframes()
- Returns:
- R: Frame
Frame object.
Statement & Extension Functions§
(Goto Table of Contents)
Statement Functions bring new, easy-to-use functions that improve the native, standard syntax and built-in functions.
- pt.let(**kwargs) Container[Any: Any]: §
Let ‘Statement’.
Note: The ‘let()’ function is unusable inside function definition scopes; It is neither a bug nor fixable, but a limitation of the Python language.
Assigns and evaluates multiple variables in a single function call.
Keep in mind that real assignment happens after the function call ends; Doing ‘let(x=5, y=10, z=x+y)’ raises ‘NameError: name ‘x’ is not defined’; But doing ‘let(x=5, y=10), let(z=x+y)’ works just fine.
- Examples:
- let(x=5, y=10, z=math.pi)
(5, 10, 3.141592653589793)
x = 5
y = 10
z = 3.141592653589793
- let(w=Seval(‘15 ** 5 / 2’))
w = 379687.5
- Kwrgs:
- **kwargs: Any
Direct assignments to given kwarg variables.
- Returns:
- R: Container[Any: Any]
A Container with the relationed objects assigned.
- pt.const(**kwargs) Container[Constant: Any]: §
Constant ‘Statement’.
Note: The ‘const()’ function is unusable in function definition scopes; It is neither a bug nor fixable, but a limitation of the Python language.
Assigns and evaluates multiple constant variables in a function call. Returns Constant objects, being immutable by nature.
Keep in mind that real assignmenet happens after the function call ends; Doing ‘const(x=5, z=x+5)’ raises ‘NameError: name ‘x’ is not defined’; But doing ‘const(x=5), const(z=x+5)’ works just fine.
- Examples:
- const(x=2.5, y=3.5)
(2.5, 3.5)
x == Constant(2.5)
y == Constant(3.5)
- const(z=[0, 1, 1, 2, 3, 5, 8, 13])
z == Constant([0, 1, 1, 2, 3, 5, 8, 13])
- Kwargs:
- **kwargs: dict
Additional constants to assign in the current context.
- Returns:
- R: Container[Constant: Any]
A Container with the relationed objects assigned as Constants.
- pt.printnl(*args, **kwargs) None: §
New Line Print.
- Rationale:
Prints the input with a new line after each prompt.
- pt.printc(*args, fill=' ', **kwargs) None: §
Centered Print.
- Rationale:
Prints the input centered on the window; Fills with (fill) character.
- pt.showcall(func) Function: §
Show Call Information.
This decorator outputs detailed information about the function call, including the line number, function name, arguments, return value or error, and execution time. It is useful for debugging and monitoring function execution.
- Example:
@showcall
def my_function(x, y):
return x + y
- my_function(3, 4)
[!-CALL-!]
Ln 10 # Example!
Fn my_function
A* (3, 4)
K* {}
R* 7
Tm 0.0001s
@showcall
def vec_func(i, j, k, op=’div’):
⠀⠀⠀⠀(…)
⠀⠀⠀⠀if op == ‘div’:
⠀⠀⠀⠀⠀⠀⠀⠀return (i * j) / k
- vec_func(2, 3, 0) # Division by zero!
[!-CALL-!]
Ln 14 # Example too!
Fn vec_func
A* (2, 3, 0)
K* {‘op’: ‘div’}
R* [!-ERROR-!]
Er ZeroDivisionError
As division by zero
Tm 0.017s
- pt.moduleview(module) Container: §
Module View.
Returns a Container of a module’s attributes and values.
- Note that, as the return type is a
Container
, you can do such as: - calc = moduleview(‘math’)calc.pi # the exact same as math.pi
- Example:
- moduleview(‘math’)
Returns a Container(k:v) for every ‘k:v’ pair inside ‘math’ module.
i.e. {‘pi’: 3.141592653589793}
i.e. {‘sqrt’: <built-in function sqrt>}
- Args:
- module: Module | String
- Module to be viewed. If String, its imported as a module object.
- Return:
- R: Container
- View of the module as k:v pairs.
- Note that, as the return type is a
- pt.doc(*objs) List[String] | Null: §
Docstring Printer.
- Rationale:
Prints into the console any docstring associated with the given object(s) or its parent class(es), headed by its origin module.
Prints the current frame’s module docstring if no object is given.
- pt.site(module) None: §
Documentation HTML Viewer.
- Rationale:
This function will search for any .html files in the module’s directory that are named after the module itself, and attempt to open it in the default browser of the user.
- pt.skip(n=1, *args, **kwargs) None: §
Line Skip.
- Rationale:
Prints into de console ‘n’ times; Defaults to a 1 line skip.
- pt.evinput(*args, **kwargs) None: §
Evaluated Input.
- Rationale:
Performs a Safe Eval (see: Seval@:ref:Instantiable Classes) into the input, converting to adequate types.
- pt.timeout(secs, func, *args, **kwargs) Any | Error: §
Timeout.
Runs a function in a separate proccess with a time limit; Raises an exception if it exceeds given limit in seconds.
- Examples:
- timeout(5, long_running_function, arg1, arg2)
Executes long_running_function(arg1, arg2) with a 5-second limit.
- Args:
- secs: Number
Time limit in seconds.
- func: Callable
Function to execute.
- *args: Any
Positional arguments to pass to the function.
- **kwargs: Any
Keyword arguments to pass to the function.
- Returns:
- R: Any | Err
The result of the function, or an exception if timed out.
- pt.loop(times=0, escape=KeyboardInterrupt, loopif=True, show=False, nl=False) Decorator: §
Loop Decorator.
A decorator that repeatedly executes the function based on specified conditions.
It allows for control over the number of iterations, conditional execution, and exception handling within the loop.
Exceptions raised by the function do not inherently stop the loop unless their type is specified in the escape parameter. However, the KeyboardInterrupt exception is guaranteed to always be caught and interrupt the loop execution.
- Examples:
@loop(times=3)
def my_function(x):
⠀⠀⠀⠀print(f”Value: {x}”)
This will print the value of x three times at ‘my_function()’.
@loop(loopif=lambda: some_condition())
def my_function(x):
⠀⠀⠀⠀print(f”Value: {x}”)
This will execute my_function as long as some_condition() returns True.
@loop(escape=KeyboardInterrupt)
def my_function(x):
⠀⠀⠀⠀print(f”Processing {x}”)
This will execute my_function in a loop until a KeyboardInterrupt exception is raised.
@loop(times=5, show=True)
def example_function(x):
⠀⠀⠀⠀print(x)
This will run ‘example_function()’ 5 times, printing the iteration details each time.
- Args:
- times: Integer = 0
The number of times to execute the decorated function.
If set to 0, the loop will run indefinitely unless broken out.
Default is 0.
- escape: Exception | Tuple[Exception, …] = KeyboardInterrupt
Exception(s) that, if raised, will stop the loop.
Default is KeyboardInterrupt (guaranteed even if changed).
- loopif: Function | Bool = True
A condition that, if evaluated to False, will break the loop.
It can be a Lambda type with out-scope parameters or conditions.
Default is True.
- show: Bool = False
If True, prints the function name, arguments, and iteration.
Default is False.
- nl: Bool = False
If True, inserts a newline after each iteration.
Default is False.
- Returns:
- Decorator
A decorator that wraps the provided function.
Debugger & Utility Functions§
(Goto Table of Contents)
Debug functions interact with the environment the script runs in, and output relevant information to the console.
These functions do accept arguments only as buffers, this being, arguments given have no impact in the output, but serve the purpose of executing code in the same line, such as starting a timer for example.
- pt.debug(*buffer) List[String] | None: §
Debug Traceback.
- Examples:
Try: (…)
Except: printnl(*debug())
- Rationale:
Returns the traceback, if any.
- pt.clear(*buffer) None: §
Clear Screen.
- Rationale:
Simple command to clear the console feed.
- pt.eof(*buffer) SystemExit: §
End of File.
- Rationale:
Logs into a .log file, waits for user input, and then exits the system.
- pt.deepframe(*buffer) None: §
Deep Frame.
- Rationale:
Prints the full depth of the current path and the frame stack.
Operator & Instantiated Classes§
(Goto Table of Contents)
Operator Classes are classes able to be used as functions, objects, contexts and as the name sugests, come with pre-loaded instances that are ready-to-use.
- The class definition for these objects is given in UPPERCASE, as in:
- class TIME:
(…)
- Where the instances are given in PascalCase, as is with other non-operator classes, so:
Time = TIME(std=’now’)
Runtime = TIME(std=’lap’)
Crono = TIME(std=’epoch’)
Are all instance examples of the operator class ‘TIME()’
- class pt.TIME§
Execution Timer.
A running timer that starts immediately when instantiated.
- Examples:
- X = TIME()
Starts ‘X’ as a timer.
- with X:
Starts a timed context with ‘X’; prints time on exit.
- X.show
Prints the current time in string format.
- Args:
- add: Float = 0.0
Time to add to the timer.
- std: String = ‘now’
Initial standard mode (‘now’, ‘lap’, or ‘epoch’).
- Methods:
- .mode(std: String = ‘’) -> Class
Changes the standard mode of the timer.
- .now -> Float
Returns the time since the last call.
- .lap -> Float
Returns the current time.
- .reset -> Class
Resets the timer.
- .string -> String
Returns the time as a string.
- .show -> String
Prints the current time in string format.
- .epoch -> List[Float]
Returns recorded times.
- Instances:
- Time = TIME(std=’now’)
Timer that returns the time since the last call.
- Runtime = TIME(std=’lap’)
Timer that returns the total elapsed time.
- Crono = TIME(std=’epoch’)
Timer that returns the entire history of recorded times.
- Returns:
- R: Float | List[Float]
Time in seconds.milliseconds (e.g. 1.234).
- class pt.STUB§
Decorator @Stub | Object Stub.
Decorates an incomplete function, indicating it has not been implemented yet.
- Examples:
- @Stub
Prints the stub location when the function is called.
- Stub()
Prints the stub status, current line and module of call.
- Stub
Null object with empty representation.
- Instances:
Stub = STUB()
- Returns:
- R: Class | Callable
Decorated function or Stub object.
- class pt.NULL§
Null Object Pattern.
A class that implements the Null Object Pattern by defining methods and operations that return neutral values or perform no actions.
- Examples:
- Nil = NULL()
Assigns an instance of the NULL class.
Default instance is ‘Null’.
- Null + 5
Performs a no-op and returns Null itself.
Null
- str(Null)
Returns an empty string.
‘’
- Null.attribute
Accesses a non-existent attribute, returns Null.
Null
- Null == None
Null has equality to None.
True
- print(Null)
Prints nothing.
Same as print().
- Instances:
Null = NULL()
- class pt.ERROR(NULL, Exception)§
Error Object.
A specialized version of the NULL class that represents an error state, overriding string and representation methods to return ‘Error’.
- Example:
- print(Error)
Error
- raise Error:
PlainTools.ERROR: Error
- Instances:
Error = ERROR()
- class pt.MAIN§
Main script guard.
Evaluates if the script is being executed directly; Similar to __name__ == ‘__main__’.
- Examples:
- if Main:
Evaluates if __name__ == ‘__main__’.
- with Main:
Enters the ‘Main’ context, only executes if Main.
- Main(*args, **kwargs)
Invokes the ‘Main’ context; runs local ‘main(*args, **kwargs)’.
main(*args, **kwargs) # Inside ‘with Main:’ context.
- Methods:
- .time -> Float
Returns the script execution time.
- .showtime -> String
Displays the script execution time.
- .clear -> Self
Clears the console; Executed by .start.
- .start -> Self
Invokes .time & .clear.
- .end -> Self
Ends the program after debugging and logging.
- Instances:
Main = MAIN()
- Returns:
R: Bool = True if the script is being executed directly.
- class pt.SILENCE§
Context manager that suppresses console output.
Redirects stdout and stderr to /dev/null, effectively silencing all output within the context.
- Examples:
- with Silence:
Silences all console output within the context.
- Instances:
Silence = SILENCE()
- Returns:
R: Class = Context manager that suppresses console output.
- class pt.LOGGING§
Functional Logging.
Stores provided strings or objects in an internal list; Writes them to a (filename).log file.
- Examples:
- Logging(“message”)
Logs “message” in the internal list.
- Logging([1, 2, 3])
Logs each element of the list on separate lines.
- Args:
- obj: Any
Object(s) to be logged.
- Methods:
- .get -> List
Returns the internal list of logged entries.
- .flush -> Self
Writes the current log to a file and clears the internal list.
This is automatically done at exiting the ‘with Main’ context.
- .show -> Self
Displays the stored messages from the log list.
- .reset -> list or None
Resets the internal list of logs to empty.
- Instances:
Logging = LOGGING()
- class pt.TRY§
Try Context.
A simpler ‘try’ context, with no direct error handling; Exits the context instead.
Can be done in a verbose way by the use of ‘with Try.show:’ method.
- Examples:
- with Try:
Begins execution and tracks its success or failure.
- Methods:
- .show -> Self
Enables verbose mode to print the context’s progress and results.
- Properties:
- verbose: Bool = False
Controls whether to print the result to the console.
- result: String
Stores the result of the try block, indicating success or failure.
- class pt.LINES§
Line Number Context Manager.
A context manager that prefixes each line of output with the line number.
- Examples:
- with Lines:
print(“Hello, World!”) # Output will be prefixed with line no.
- Instances:
Lines = LINES()
- class pt.SEVAL§
Safe Expression Evaluator.
A secure alternative to Python’s eval() function, designed to evaluate mathematical and basic expressions while preventing access to unsafe operations and functions.
- Examples:
- Seval(“2 + 2”)
4
- Seval(“round(math.pi * 2, 2)”)
6.28 # Only if ‘math’ is imported in the current namespace.
- Seval(“”import shutil; shutil.rmtree(‘/.’)”)
Raises UnsafeError.
- Raises:
UnsafeError: Raised when tries unsafe operation, function, or module.
- Attributes:
- UnsafeError: TypeError
Custom error for handling unsafe operations.
- blacklist: dict
Defines disallowed functions and modules that are prohibited.
This can be changed by creating a new SEVAL() instance and modfying its ‘.blacklist’ dictionary.
The original dictionary contains 2 keys: .blacklist[‘functions’] and .blacklist[‘modules’] each with a set of strings as its value.
- Disallowed Functions:
__import__
eval
exec
compile
encode
decode
open
exit
print
input
base64
bytearray
bytes
getattr
main
Main
- Disallowed Package Functions:
- Disallowed Constructor|Instances:
- Disallowed Modules:
builtins
os
sys
code
shutils
json
multiprocessing
platform
http
sqlite3
getpass
crypt
ftplib
uuid
turtle
ctypes
atexit
tk
re
mmap
pathlib
compileall
tempfile
faulthandler
stat
urllib
ssl
threading
resource
signal
hashlib
unittest
secrets
grp
dbm
glob
asyncio
pwd
gc
base64
pdb
webbrowser
subprocess
codeop
smtlib
xmlrpc
sysconfig
socket
Constructor Classes & Custom Objects§
(Goto Table of Contents)
Constructor Classes have the purpose of creating Custom Objects that can be manipulated in specific, useful ways. There is a variety of Custom Objects introduced in the module, so a more in-depth explanation is provided in each’s documentation below.
- class pt.Container§
Container Class; dict Subclass.
A flexible dict-class that supports various operations and transformations. Unlike a standard dictionary, a Container is unpacked by its items rather than by its keys.
Note: Containers can’t have numeric keys due to how their keys are directly associated to its instance attributes. However, any String type is a valid key type. Attempting to update a Container instance with enumerated dictionaries will raise a TypeError.
The Container supports basic arithmetic operations on a per-key basis, meaning that you can operate an iterable to a Container, where each ordered element operates each key’s value until exhaustion; Where as single, non-iterable operations are performed on the entire Container.
Containers can have its values accessed as attributes when calling for their keys. This means that assigned attributes into this class are also added to the Container’s keys with the designated value.
- Example:
- C1 = Container(a=1, b=2)
Creates a Container as {‘a’: 1, ‘b’: 2}
- C2 = Container(‘c’)
Creates a Container as {‘c’: None}
- C1(C2) # Same as C1 += C2
Aggregates C1 and C2 for {‘a’: 1, ‘b’: 2, ‘c’: None}
- C1.fill(4)
Alocates ‘4’ to the first encounter of None value in C1.
- Methods:
- .sort(*args, **kwargs): Self
Sorts the keys (or values) of the Container; Optional lambda.
- .shove(*vals): Self
Adds the values to the keys following the current order of keys.
- .fill(*vals, target=None, exhaust=True): Self
Fills in any target vals in the Container with provided vals.
target argument can be a lambda|function|builtin|singleton.
exhaust argument defines if fill is finite or cyclic infinite.
- .order(*keys): Self
Orders the keys of the Container as provided.
- .only(*keys): Self
Returns a Container containing only the specified keys.
- .without(*keys): Self
Returns a Container without the specified keys.
- .keyval(): dict
Returns a copy of the dictionary object as {keys: values}.
- .key(*keys): list
Returns a list of keys in Container; Optional filter for values.
- .val(*vals): list
Returns a list of values in Container; Optional filter for keys.
- .sub(): Tuple[Container]
Returns a tuple of each k: v pair in Container, as Containers.
- .copy(): Container
Returns a deepcopy of the current Container.
- Operators:
Any basic arithmetic operator is supported as in:
Container <> Container
;Container <> other
Operations with non-iterables are valid as long as the operation to everyContainer[N] <> other
is valid for all given N.Container(f=1, g=2, h=3) * 2 == Container(f=2, g=4, h=6)
Container(Bob=’Foo’) - 5 == Container(Bob=’Foo’, Bob_1=5)
Operations with iterables are valid as long as the operation to every pairContainer[N] <> other[N]
is valid for the max possible N.Container(R=5, S=10) * (2,3,4) == Container(R=10, S=30)
Container(T=2,U=4,V=6) - {2,3} == Container(T=0, U=1, V=6)
Remainder ofContainer <> other
operations are ignored, as theresult is a Container type with the same keys as the involved Container.Container(i=2, j=3) * [2, 3, 4] == Container(i=4, j=9)
Remainer ofContainer <> Container
operations aggregate non-similarkeys into the final result, unmodified, as no C1[K] <> C2[K] is valid.Container(f=5) - Container(g=10) == Container(f=5, g=10)
- add (+)
Adds the values of another Container, or from a sequence.
i.e. Container(a=5) + (b=4) == Container(a=5, b=4)
i.e. Container(a=5, b=4) + [3, 4] == Container(a=8, b=8)
- sub (-)
Subtracts the values of another Container or from a sequence.
i.e. Container(x=5, y=10) - 3 == Container(x=2, y=7)
i.e. Container(a=5, b=4) - Container(c=3, d=2)
- mul (*)
Multiplies the values of another Container or from a sequence.
i.e. Container(x=5) * 2 == Container(x=10)
i.e. Container(x=5, y=4) * (3, 4) == Container(x=15, y=16)
- truediv (/)
Divides the values of another Container or from a sequence.
i.e.Container(T=2,U=4,V=6)/[1,2,3]==Container(T=2.0,U=2.0,V=2.0)
- floordiv (//)
Floor divides the values of another Cont. or from a sequence.
i.e. Container(A=12.5) // Container(A=3.5) == Container(A=3.0)
- mod (%)
Modulo operates on the values of another Cont. or from a seq.
i.e. Container(B=7.5) % Container(B=2) == Container(B=1.5)
- pow (**)
Raises the values of the Container to the power of.
i.e. Container(C=5) ** Container(C=3) == Container(C=125)
- Returns:
- Container
A
dict
subclass object that is callable.
- class pt.Constant§
Immutable Constants.
Wraps a value and provides a constant, immutable interface to it.
Overrides most of the standard dunder methods to ensure immutability.
Non-dunder methods can be called, but will only return the Constant’s value and won’t modify the Constant itself or it’s value in any way.
- Examples:
- x = Constant(5)
Create an immutable constant with a value of 5
i.e. x + 5 == 10
i.e. x += 5 ; x == 5
- pi = Constant(math.pi)
Assign ‘math.pi’ to ‘pi’ as an immutable constant
i.e. const(rpi=pi*2) # ‘rpi’ is also a Constant now.
- Args:
- value: Any
The value to be wrapped as a Constant.
- Returns:
- Constant
An immutable Constant instance wrapping the provided value.