Single and multiple line status updates with minimal update sequences.
Project description
Single and multiple line status updates with minimal update sequences.
Latest release 20230212:
- BREAKING: replace @upd_proxy (which fiddled upd.state) with @with_upd_proxy which supplies an upd_proxy parameter.
- UpdProxy.text: bugfix spelling of _text_auto.
- Upd now subclasses HasThreadState, replace global "state" with "Upd.state", related adjustments.
- UpdProxy: new optional update_period parameter to limit the update frequency based on the time since last update.
- Upd.insert: support keyword parameters for the created UpdProxy.
This is available as an output mode in cs.logutils
.
Single line example:
from cs.upd import Upd, nl, print
.....
with Upd() as U:
for filename in filenames:
U.out(filename)
... process filename ...
U.nl('an informational line to stderr')
print('a line to stdout')
Multiline multithread example:
from threading import Thread
from cs.upd import Upd, print
.....
def runner(filename, proxy):
# initial status message
proxy.text = "process %r" % filename
... at various points:
# update the status message with current progress
proxy.text = '%r: progress status here' % filename
# completed, remove the status message
proxy.close()
# print completion message to stdout
print("completed", filename)
.....
with Upd() as U:
U.out("process files: %r", filenames)
Ts = []
for filename in filenames:
proxy = U.insert(1) # allocate an additional status line
T = Thread(
"process "+filename,
target=runner,
args=(filename, proxy))
Ts.append(T)
T.start()
for T in Ts:
T.join()
A note about Upd and terminals
I routinely use an Upd()
as a progress reporting tool for commands
running on a terminal. This attaches to sys.stderr
by default.
However, it is usually not desirable to run an Upd
display
if the backend is not a tty/terminal.
Therefore, an Upd
has a "disabled" mode
which performs no output;
the default behaviour is that this mode activates
if the backend is not a tty (as tested by backend.isatty()
).
The constructor has an optional parameter disabled
to override
this default behaviour.
Function demo()
A tiny demo function for visual checking of the basic functionality.
Function nl(msg, *a, upd, **kw)
Write msg
to file
(default sys.stdout
),
without interfering with the Upd
instance.
This is a thin shim for Upd.print
.
Function out(msg, *a, upd, **outkw)
Update the status line of the default Upd
instance.
Parameters are as for Upd.out()
.
Function pfxprint(*a, upd, **kw)
Wrapper for cs.pfx.pfxprint
to pass print_func=cs.upd.print
.
Programmes integrating cs.upd
with use of the cs.pfx.pfxprint
function should use this at import time:
from cs.upd import pfxprint
Function print(*a, upd, end='\n', **kw)
Wrapper for the builtin print function
to call it inside Upd.above()
and enforce a flush.
The function supports an addition parameter beyond the builtin print:
upd
: theUpd
instance to use, defaultUpd()
Programmes integrating cs.upd
with use of the builtin print
function should use this at import time:
from cs.upd import print
Function run_task(*a, upd, **kw)
Top level run_task
function to call Upd.run_task
.
Class Upd(cs.obj.SingletonMixin, cs.threads.HasThreadState, cs.context.ContextManagerMixin)
A SingletonMixin
subclass for maintaining a regularly updated status line.
The default backend is sys.stderr
.
Method Upd.__init__(self, backend=None, columns=None, disabled=None)
:
Initialise the Upd
.
Parameters:
backend
: the output file, defaultsys.stderr
columns
: the width of the output, default from the width of thebackend
tty if it is a tty,80
otherwisedisabled
: if true, disable the output - just keep state; default true if the output is not a tty; this automatically silences theUpd
if stderr is not a tty
Class UpdProxy
A proxy for a status line of a multiline Upd
.
This provides a stable reference to a status line after it has been
instantiated by Upd.insert
.
The status line can be accessed and set via the .text
property.
An UpdProxy
is also a context manager which self deletes on exit:
U = Upd()
....
with U.insert(1, 'hello!') as proxy:
.... set proxy.text as needed ...
# proxy now removed
Method UpdProxy.__init__(self, text: Optional[str] = None, *, upd: cs.upd.Upd, index: int = 1, prefix: Optional[str] = None, suffix: Optional[str] = None, text_auto=None, update_period: Optional[float] = None)
:
Initialise a new UpdProxy
status line.
Parameters:
index
: optional position for the new proxy as forUpd.insert
, default1
(directly above the bottom status line)upd
: theUpd
instance with which to associate this proxy, default the defaultUpd
instance (associated withsys.stderr
)text
: optional initial text for the new status line
Function uses_upd(func)
Decorator for functions accepting an optional upd=Upd()
parameter,
default from Upd.state.current
.
Function with_upd_proxy(*da, **dkw)
Decorator to run func
with an additional parameter upd_proxy
being an UpdProxy
for progress reporting.
Example:
@with_upd_proxy
def func(*a, upd_proxy:UpdProxy, **kw):
... perform task, updating upd_proxy ...
Release Log
Release 20230212:
- BREAKING: replace @upd_proxy (which fiddled upd.state) with @with_upd_proxy which supplies an upd_proxy parameter.
- UpdProxy.text: bugfix spelling of _text_auto.
- Upd now subclasses HasThreadState, replace global "state" with "Upd.state", related adjustments.
- UpdProxy: new optional update_period parameter to limit the update frequency based on the time since last update.
- Upd.insert: support keyword parameters for the created UpdProxy.
Release 20221228: Bugfix print: plumb the end= parameter.
Release 20220918:
- DROPPING PYTHON 2 SUPPORT.
- New @uses_upd decorator for things accepting an optional upd=Upd().
- UpdProxy.init: use @uses_upd, make text the only optional positional parameter.
- New top level
run_task
context manager wrappingUpd.run_task
. - Make all the top level functions accept an optional upd=Upd() parameter.
- Upd.run_task: wrap the yield in a try/finally to manage the RunState.
- Upd.run_task: set default tick_delay=0.3, 0.15 was too fast.
- UpdProxy: new optional text_auto() callable parameter, used to compute proxy.text if proxy._text is empty.
- UpdProxy.width: account for the suffix.
Release 20220619: Upd.cursor_visible,cursor_invisible: actually send the escape sequence.
Release 20220606: Upd.insert: insert(1) on empty slots autocreates slot 0.
Release 20220605:
- New Upd.run_task to add a status line for the duration of some task.
- UpdProxy.extend_prefix: new optional print_elapsed parameter.
Release 20220530:
- UpdProxy: new .suffix property.
- Upd: new run_task context manager to display an UpdProxy while something runs, with optional ticker.
- Small bugfix.
Release 20220504:
- Upd.above: do a disable/enable around the yield, use try/finally for reliability.
- Upd.delete: just warn about index out of range, seems it can happen during interpreter shutdown; to be debugged later.
Release 20220429:
- UpdProxy: accept optional prefix= parameter.
- New pfxprint wrapper for cs.pfx.pfxprint, like the print wrapper.
Release 20210717: Docstring update.
Release 20210507: Upgrade dependency on cs.context for StackableState.
Release 20210428.4: Another dummy release during debugging.
Release 20210428.3: Repeat the previous release, again again.
Release 20210428.2: Repeat the previous release, again.
Release 20210428.1: Repeat the previous release.
Release 20210428: Do curses.setupterm() during iinit, avoid failure when stdout is not a tty.
Release 20210316:
- New UpdProxy.extend_prefix context manager to extend the proxy prefix around a suite.
- New global "state" StackableStatei object with an automatic .upd attribute.
- New @upd_proxy decorator to create an UpdProxy for the duration of a function call and record it as state.proxy.
- Bugfix Upd.insert: add slots.insert and proxies.insert missing from the no-display path.
- Rename private method Upd._adjust_text_v to public method Upd.diff.
Release 20210122:
- Autocreate slot 0 on first use.
- Reliable cleanup at exit.
- Fix a display small display issue.
Release 20201202:
- Fix for batch mode - handle failure of curses.setupterm(), throws TypeError.
- Upd.insert: defer check for cuu1 capability until there's at least one line already.
Release 20201102:
- Upd.nl: simple approach when there are no status lines.
- Upd: new cursor_visible and cursor_invisible methods to show and hide the cursor.
Release 20201026.1: Bugfix Upd.nl: simple output if there are no status lines to accomodate.
Release 20201026: Bugfix Upd.insert: accept insert(1) when len(self)==0.
Release 20201025:
- Upd: new .disabled property to allow inspection of disabledness.
- Upd.insert: accept negative insert indices to position from the top of the list.
- Upd.nl: use clear-to-end-of-line at the end of the message if available.
- UpdProxy: turn .prefix into a property which causes a redraw when changed.
- Upd.proxy(index): return None if the index is out of range, accomodates racy or incorrect behaviour by a user.
- UpdProxy: cropped overflowing text gets a leading '<' to make it apparent.
- UpdProxy: new .insert() method to support insterting new proxies with respect to an existing proxy.
- UpdProxy: new reset() method, clears prefix and text.
- UpdProxy.init: BREAKING: make all arguments optional to aid use.
- Upd: do not make any slots unless required.
- Make the compute-redraw-strings methods private.
Release 20200914: Bugfix UpdProxy.enter: return self.
Release 20200716.1: DISTINFO: make the cs.obj requirement more specific due to the SingletonMixin API change.
Release 20200716: Update for changed cs.obj.SingletonMixin API.
Release 20200626.1: Upd.exit: bugfix test of SystemExit exceptions.
Release 20200626:
- UpdProxy: call self.delete on del.
- If self._backend is None act as if disabled, occurs during shutdown.
- Upd.delete: ignore attempts to delete the last line, also occurs during shutdown.
Release 20200621: New "disabled" mode, triggered by default if not backend.isatty().
Release 20200613:
- New UpdProxy.call which sets the .text property in the manner of logging calls, with (msg,*a).
- New Upd.normalise static method exposing the text normalisation
unctrl(text.rstrip())
. - New UpdProxy.prefix attribute with a fixed prefix for status updates;
prefix+text
is left cropped for display purposes when updated. - New UpdProxy.width property computing the space available after the prefix, useful for sizing things like progress bars.
- Make UpdProxy a context manager which self deletes on exit.
- Upd: make default backend=sys.stderr, eases the common case.
- New Upd.above() context manager to support interleaving another stream with the output, as when stdout (for print) is using the same terminal as stderr (for Upd).
- New out() top level function for convenience use with the default Upd().
- New nl() top level function for writing a line to stderr.
- New print() top level function wrapping the builtin print; callers can use "from cs.upd import print" to easily interleave print() with cs.upd use.
Release 20200517:
- Multiline support!
- Multiline support!
- Multiline support!
- New UpdProxy class to track a status line of a multiline Upd in the face of further inserts and deletes.
- Upd(...) now returns a context manager to clean up the display on its exit.
- Upd(...) is now a SingletonMixin in order to use the same state if set up in multiple places.
Release 20200229:
- Upd: can now be used as a context manager, clearing the line on exit.
- Upd.without is now a context manager, returning the older state, and accepting an optional inner state (default "").
- Upd is now a singleton factory, obsoleting upd_for.
- Upd.nl: use "insert line above" mode if supported.
Release 20181108: Documentation improvements.
Release 20170903:
- New function upd_for(stream) returning singleton Upds.
- Drop noStrip keyword argument/mode - always strip trailing whitespace.
Release 20160828:
- Use "install_requires" instead of "requires" in DISTINFO.
- Add Upd.flush method.
- Upd.out: fix longstanding trailing text erasure bug.
- Upd.nl,out: accept optional positional parameters, use with %-formatting if supplied, just like logging.
Release 20150118: metadata fix
Release 20150116: Initial PyPI release.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for cs.upd-20230212-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 3231c1f7e1748d46befa278235be54e160c6e0b3b9f02de2ac1102e9f7010785 |
|
MD5 | fbef76654061f39b18df9d107ba4c855 |
|
BLAKE2b-256 | cf3b2128d635a1a3bd2dcfd81b0484d8c9a45c7afb5478e08fa86e3ca10d70d9 |