hio.help.helping
hio.help.helping module
Module Contents
- hio.help.helping.isign(i)
Integer sign function :returns: 1 if i > 0, -1 if i < 0, 0 otherwise :rtype: (int)
- hio.help.helping.sceil(r)
Symmetric ceiling function Returns the symmetric ceiling of r away from zero.
Because int() provides a symmetric floor towards zero, increment int(r) by 1 when r - int(r) > 0 (r positive), -1 when r - int(r) < 0 (r negative), and 0 when r - int(r) == 0 (r integral already).
- hio.help.helping.copyfunc(f, name=None)
Copy a function in detail. To change name of func provide name parameter
functools.update_wrapper assigns and updates attributes in WRAPPER_ASSIGNMENTS (__module__, __name__, __qualname__, __doc__, __annotations__) and WRAPPER_UPDATES (__dict__).
Based on: https://stackoverflow.com/questions/6527633/how-can-i-make-a-deepcopy-of-a-function-in-python https://stackoverflow.com/questions/13503079/how-to-create-a-copy-of-a-python-function
- hio.help.helping.attributize(genie)
Decorator function:
Python generators do not support adding attributes. Adding support for attributes provides a way to pass information from a WSGI App that returns a generator to a WSGI server via the generator after the WSGI app has already started returning its body. The hio.http.Server WSGI server looks for the attributes ._status and ._headers and substitutes these if present. This allows a streaming WSGI App body iterator to later modify the headers and status taht will be returned before the body iterator began iterating. This is useful for web hooks or backend requests that are serviced by an async coroutine based WSGI app so that they may leverage the streaming support of standard WSGI but use a the coroutine based hio.http.Server as an async WSGI server.
This decorator takes a Duck Typing approach to decorating a generator function or method that returns a new function type instance that when called will return a generator like object that supports attributes. the new wrapped object acts like a generator but with attributes.
- Parameters:
genie (generator function, generator method) – is either a generator function that returns a generator object a generator method that returns a generator object
- If genie is a generator function then a reference to its wrapper
is injected as the first positional argument to the orginal generator function. The convention is to use the parameter ‘me’ to refer to the injected reference to the wrapper.
- If genie is a generator method, that is, its first parameter is ‘self’
then a reference to its wrapper is injected as the second positional argument to the original generator method. the convention is to use the parameter ‘me’ to refer to the injected reference to the wrapper so as not to collide with the ‘self’ instance reference.
When wrapped the new type is AttributiveGenerator
Usage:
# decorated generator function @attributize def bar(me, req=None, rep=None): me._status = 400 # or copy from rep.status me._headers = odict(example="Hi") # or copy from rep.headers yield b"" yield b"" yield b"Hello There" return b"Goodbye" gen = bar() msg = next(gen) # attributes set after first next gen._status gen._headers # decorated generator method class R: @attributize def bar(self, me, req=None, rep=None): self.name = "Peter" me._status = 400 # or copy from rep.status me._headers = odict(example="Hi") # or copy from rep.headers yield b"" yield b"" yield b"Hello There " + self.name.encode() return b"Goodbye" r = R() gen = r.bar() msg = next(gen) # attributes set after first next gen._status gen._headers # use as function wrapper directly instead of as decorator def gf(me, x): # convention injected reference to attributed wrapper is 'me' me.x = 5 me.y = 'a' cnt = 0 while cnt < x: yield cnt cnt += 1 agf = attributize(gf) ag = agf(3) # body of gf is not run until first next call assert isIterator(ag) assert not hasattr(ag, 'x') assert not hasattr(ag, 'y') n = next(ag) # first run here which sets up attributes assert n == 0 assert hasattr(ag, 'x') assert hasattr(ag, 'y') assert ag.x == 5 assert ag.y =='a' n = next(ag) assert n == 1
Adding attributes to this injected reference makes them available as attributes of the resultant wrapper.
The HTTP WSGI server at hio.core.http.serving.Server uses an instance of hio.core.http.serving.Responder to generate the response for each WSGI request. The Responder instance checks its WSGI app generator for existence of the attributes ._status and ._headers. If so then it overrides its default response status with ._status and updates its default response headers with the headers in ._header. This allows a backend (webhook) to conveniently influence the response status and headers. The response body is returned by the generator itself.
Background: Unlike Python functions, Python generators do not support custom attributes and the generator locals dict at .gi_frame.f_locals dissappears once the generator is complete so its inconvenient.
Fixed attributes of generator objects:
['.__next__', '__iter__', 'close', 'gi_code', 'gi_frame', 'gi_running', 'gi_yieldfrom', 'send', 'throw']
- hio.help.helping.repack(n, seq, default=None)
Repacks seq into a generator of len n and returns the generator. The purpose is to enable unpacking into n variables. The first n-1 elements of seq are returned as the first n-1 elements of the generator and any remaining elements are returned in a tuple as the last element of the generator default (None) is substituted for missing elements when len(seq) < n
Example:
x = (1, 2, 3, 4) tuple(repack(3, x)) (1, 2, (3, 4)) x = (1, 2, 3) tuple(repack(3, x)) (1, 2, (3,)) x = (1, 2) tuple(repack(3, x)) (1, 2, ()) x = (1, ) tuple(repack(3, x)) (1, None, ()) x = () tuple(repack(3, x)) (None, None, ())
- hio.help.helping.just(n, seq, default=None)
Returns a generator of just the first n elements of seq and substitutes default (None) for any missing elements. This guarantees that a generator of exactly n elements is returned. This is to enable unpacking into n varaibles
Example:
x = (1, 2, 3, 4) tuple(just(3, x)) (1, 2, 3) x = (1, 2, 3) tuple(just(3, x)) (1, 2, 3) x = (1, 2) tuple(just(3, x)) (1, 2, None) x = (1, ) tuple(just(3, x)) (1, None, None) x = () tuple(just(3, x)) (None, None, None)
- class hio.help.helping.NonStringIterable
Allows isinstance check for iterable that is not a string if isinstance(x, NonStringIterable):
- class hio.help.helping.NonStringSequence
Allows isinstance check for sequence that is not a string if isinstance(x, NonStringSequence):
- hio.help.helping.isNonStringIterable(obj)
Returns: (bool) True if obj is non-string iterable, False otherwise
Another way that is less future proof return (hasattr(x, ‘__iter__’) and not isinstance(x, (str, bytes)))
- hio.help.helping.isNonStringSequence(obj)
Returns: (bool) True if obj is non-string sequence, False otherwise
- hio.help.helping.isIterator(obj)
Returns True if obj is an iterator object, that is,
has an __iter__ method has a __next__ method .__iter__ is callable and returns obj
Otherwise returns False
- hio.help.helping.ocfn(path, mode='r+', perm=stat.S_IRUSR | stat.S_IWUSR)
Atomically open or create file from filepath.
If file already exists, open with mode. Otherwise create a new file using write/update mode (binary if “b” in mode). Returns file object. perm uses mode bits like stat.S_IRUSR | stat.S_IWUSR (0o600).
- hio.help.helping.dump(data, path)
Serialize data dict and write to file given by path where serialization is given by path’s extension of either JSON, MsgPack, or CBOR for extension .json, .mgpk, or .cbor respectively
- hio.help.helping.load(path)
Return data read from file path as dict file may be either json, msgpack, or cbor given by extension .json, .mgpk, or .cbor respectively Otherwise raise IOError
- hio.help.helping.intToB64(i, l=1)
Converts int i to at least l Base64 chars as str.
Returns Base64 conversion of i of minimum length l. If more than l chars are needed to represent i in Base64 then the string is lengthened appropriately. When fewer than l chars are needed, the string is left padded with “A”. l is the minimum number of Base64 digits, where Base64 0 is “A”.
- hio.help.helping.intToB64b(i, l=1)
Converts int i to at least l Base64 chars as bytes.
- Returns:
- Base64 conversion of i of length minimum l. If more than
l bytes are needed to represent i in Base64 then returned bytes is extended appropriately. When less then l bytes is needed then returned bytes is prepadded with b’A’ bytes.
- Return type:
b64 (bytes)
- Parameters:
i (int) – to be converted
l (int) – min number of b64 digits. When empty these are left padded with Base64 0 == b’A’ digits. The length of return bytes is extended to accommodate full Base64 encoding of i regardless of l.
- hio.help.helping.b64ToInt(s)
Converts Base64 to int :returns: conversion s (str | bytes) to int :rtype: i (int)
- Parameters:
s (str | bytes) – to be converted
- hio.help.helping.codeB64ToB2(s)
Convert Base64 chars in s to B2 bytes
- Returns:
conversion (decode) of s Base64 chars to Base2 bytes. Where the number of total bytes returned is equal to the minimun number of chars (octet) sufficient to hold the total converted concatenated chars from s, with one sextet per each Base64 char of s. Assumes no pad chars in s.
- Return type:
bs (bytes)
Sextets are left aligned with pad bits in last (rightmost) byte to support mid padding of code portion with respect to rest of primitive. This is useful for decoding as bytes, code characters from the front of a Base64 encoded string of characters.
- Parameters:
s (str | bytes) – Base64 str or bytes to convert
- hio.help.helping.codeB2ToB64(b, l)
Converts first l sextets of base2 b bytes to base64 str and returns
- Returns::
- code (str): conversion (encode) of l Base2 sextets from front of b
to Base64 chars.
One char for each of l sextets from front (left) of b. This is useful for encoding as code characters, sextets from the front of a Base2 bytes (byte string). Must provide l because of ambiguity between l=3 and l=4. Both require 3 bytes in b. Trailing pad bits are removed so returned sextets as characters are right aligned .
- Parameters::
b (bytes | str): target from which to nab sextets l (int): number of sextets to convert from front of b
- hio.help.helping.nabSextets(b, l)
Nab l sextets from front of b.
Returns bytes with the first l sextets from the left of b. Length is the minimum needed to hold all l sextets. The last byte is right padded with zeros to be compatible with mid-padded codes on front of primitives. b is bytes or str, and l is the number of sextets to nab.