Metadata-Version: 2.1
Name: pyux-track
Version: 0.1.1
Summary: Python ux tools to ease tracking scripts
Home-page: https://pyux.readthedocs.io/en/stable/
Author: Romain Damian
Author-email: damian.romain@gmail.com
License: UNKNOWN
Description: Pyux - Python ux tools to ease tracking scripts
        ===============================================
        
        **version** 0.1.1 **license** MIT
        
        *Pyux contains a set of functions and classes that help with keeping
        track of what is happening during a script execution. It contains simple
        but helpful classes.* `Contributions`_ *to the package are welcomed !*
        
        *Three modules are available :* console *provide tools to print
        stuff to console while a script is executing ;* time *provide
        tools in relation with time, which is measuring it or waiting for it
        ;* logging *contains a wrapper around a logger from* ``logging``
        *module to spare you configuring one.*
        
        Installation
        ============
        
        You can download ``pyux`` from PyPi. There is only one requirement which
        is package `colorama`_, which will be automatically installed with
        ``pyux``.
        
        .. code:: bash
        
           pip install pyux-track
        
        Demonstration script
        ~~~~~~~~~~~~~~~~~~~~
        
        Once installed, the package comes with a demonstration script that you
        can use to see the how the available classes behave. The demo is exhaustive
        and interactive so you can skip some sections if you want, or quit it
        if you get bored. Launch the demo by typing in a terminal :
        
        .. code:: bash
        
           python -m pyux
        
        Please note that the demo does not provide any information on how to
        use the classes : that you will find below.
        
        --------------
        
        Module ``console``
        ==================
        
        This module contains classes that print things to the terminal during
        execution. Most of them are meant to be used as decorators of a for
        statement, where they can help track where you are in the loop.
        
        You can also use them manually to customise behaviour within a loop
        or anywhere else in your scripts.
        
        Wheel
        ~~~~~
        
        Use ``Wheel`` as an iterable’s decoration to have a turning *wheel*
        printed during a ``for`` loop, turning as fast as the iterations go. By
        default the iteration index is printed next to the wheel, but you can
        choose to print the iteration value instead of the iteration index with
        argument ``print_value = True``.
        
        When used over a standard ``range(n)``, it accepts ``n`` as an argument
        for the iterable.
        
        .. code:: python
        
           from pyux.console import Wheel
           from time import sleep
           
           myrange = 'An iterable string'
           for step in Wheel(myrange, print_value = True):
              sleep(0.2)
           
           for step in Wheel(20):
              sleep(0.1)
        
        If you must, you can also instantiate ``Wheel`` outside of a loop then
        trigger it manually. It is useful mainly to customise the message you
        want to print (otherwise it is either the iteration index or iteration value).
        
        Note that when using it manually, you may want to *close* the wheel when
        you're done : it prints the length of the iterable or a message if provided,
        and flushes a new line (otherwise the console cursor is still on the
        previous line). When decorating a for statement, it is automatically called when
        the loop finishes.
        
        .. code:: python
        
           from time import sleep
           from pyux.console import Wheel 
        
           wheel = Wheel()                  # no need for an iterator argument in that case
           for index, word in enumerate(['coffee', 'vanilla', 'cocoa']):
               wheel.print(step = index, message = 'Running on word %s            ' % word)
               sleep(1)                  # renders best if iterations are not too fast
           wheel.close(message = 'No more words to think about.')
        
        ``Wheel`` can also be used to decorate a generator object rather than an iterable,
        which is especially useful with ``os.walk()``, for instance, to know both if
        your script is still running and the total number of read paths. This also makes
        it compatible with `enumerate`.
        
        ProgressBar
        ~~~~~~~~~~~
        
        Use ``ProgressBar`` as an iteratable’s decoration to have a progress bar
        printed during a ``for`` loop. It mimics, in a extremely simplified way,
        the behavior of the great `tqdm`_ progress bar. As for ``Wheel``, you
        can also use it manually.
        
        Integers for ``iterable`` argument are read as ``range(n)``.
        
        .. code:: python
        
           from pyux.console import ProgressBar
           from time import sleep
           
           for index in ProgressBar(2500):     
               sleep(0.001)
        
        Since ``ProgressBar`` needs to know at initialisation the total number
        of iterations (to calculate the bar's width and the percentage),
        it is not usable with generators. A workaround is to give it an approximate
        number of iterations as ``iterable`` argument, and use it manually. Careful
        though, should the approximation be too short, the bar will expand further
        than the console width (or never reach 100% if too big).
        
        .. code:: python
        
           from pyux.console import ProgressBar
           from time import sleep
           
           def simple_generator(n):
              for i in range(n):
                 yield i
           
           bar = ProgressBar(1000)
           for value in simple_generator(1200):
              sleep(0.002)
              bar.print(step = value)
           print('Too long !')
           
           bar.current_console_step = 0    # resetting bar to zero
           for value in simple_generator(800):
               sleep(0.002)
               bar.print(step = value)
           print('Too short !')
        
        A *manual* ProgressBar can also be used to track progression on scripts
        with distinct stages (if there are so many of them that it makes sense)
        that are not necessarily in the form of a loop. 
        
        Do use ``ProgressBar.close()`` method to be sure that the 100% iteration
        will be printed and the console cursor flushed to a new line when you
        use it manually (when decorating a for statement, it is automatically
        called when the loop finishes).
        
        .. code:: python
        
           bar = ProgressBar()
        
           # here goes stage 1
           bar.print(step = 1)
        
           # here goes ...
           bar.print(step = ...)
        
           bar.close()
        
        ColourPen
        ~~~~~~~~~
        
        Use ``ColourPen`` as its name indicates : to write colored text in
        terminal. It uses ``colorama`` package. Use a single instance for
        different styles thanks to the possibility of chaining ``write``
        instructions.
        
        .. code:: python
        
           from pyux.console import ColourPen
        
           pen = ColourPen()
           pen.write('Hello', color = 'cyan', style = 'normal')\
               .write(' this is another', color = 'red')\
               .write(' color on the same line.', color = 'green', newline = True)\
               .write("The same color on a new line. I'm reseting styles after that.", newline = True, reset = True)\
               .write('A normal goodbye.')\
               .close()
        
        ``ColourPen.close()`` resets styles to normal, flushes to a new line and closes
        ``colorama``, which means that if you do not initialise a pen instance again,
        the colouring and styling won't work anymore.
        
        Module ``time``
        ===============
        
        This module contains classes that handle time : either measure it, or
        wait.
        
        Timer
        ~~~~~
        
        ``Timer`` pause your script for the given number of seconds. With quite
        the same design as wheel, you may add a message next to the timer.
        
        .. code:: python
        
           from pyux.time import Timer
        
           # A timer for 3 seconds with a message
           Timer(delay = 3, message = 'Pausing 3 secs, tired')
        
           # A timer with no message
           Timer(delay = 3)
        
        The timer can also be used as an iterable's decoration within a for statement,
        when you repeatedly have to await the same delay at each iteration.
        Specifying ``overwrite = True`` allows each iteration to be
        rewritten on the same line, which is advised when used in that case.
        
        Note that the first argument to ``Timer`` is ``iterable`` and not ``delay``, and
        all of them have default values, so ``Timer(5)`` won't have the expected
        behaviour !
        
        By default, a timer in a for loop prints the iteration index next to the timer. 
        Use ``pattern`` argument to specify a prefix to add to the default iteration
        index (default to ``''``), or ``print_value`` to print the iteration
        value rather than the index.
        
        .. code:: python
           
           from pyux.time import Timer
           
           for fruit in Timer(['banana', 'apple', 'tomato'], delay = 3, print_value = True):
              pass
        
        Again the ``Timer.close()`` make the counter go to zero included and flushes a new
        line. It is called automatically when used as a loop's decoration.
        
        Chronos
        ~~~~~~~
        
        Use ``Chronos`` to measure user execution time, for a script or a loop.
        It works as a stopwatch : rather than wrapping around and timing an
        expression, it triggers at start, then the method ``Chronos.lap()``
        notes time with ``timeit.default_timer()`` each time it is called (thus
        resembling a lap button on a stopwatch).
        
        .. code:: python
        
           from time import sleep
           from pyux.time import Chronos
        
           chrono = Chronos()
           print('Step one with duration approx. 1.512 secs')
           sleep(1.512)
           chrono.lap(name = 'step 1')
        
           print('Step two with duration approx. 1.834 secs')
           sleep(1.834)
           chrono.lap(name = 'step 2')
        
           chrono.compute_durations(ms = True)
        
           print('\nNow printing durations :')
           for name, time in chrono.durations.items():
               print('Time for step %s : %d ms' % (name, time))
        
        Durations can be written in a tsv file with ``Chronos.write_tsv``.
        The method uses an append mode, so you can append times to the same
        †racking file for different code executions, for instance. 
        
        Argument ``run_name`` in that method allows you to give a name to an execution
        especially for that purpose (the name appear as the first column of
        the written file).
        
        Three columns are written, with default names ``Execution`` (the one
        presented just above), ``Step`` and ``Duration (secs)``. These names
        can be changed with argument ``col_names``.
        
        If you want to time iterations from a for loop, you can use it as a
        decoration for the iterable. Since you won't be able to assign the
        object back when the loop finishes, you can choose to print durations
        in console, or write them into a tsv file.
        
        .. code:: python
        
           from pyux.time import Chronos
           from pyux.time import Timer
           
           for index, value in enumerate(Chronos(range(1, 4), console_print = True, ms = True)):
              Timer(delay = value, message = 'At iteration %d' % index, overwrite = True)
        
        Depending on the number of arguments you provide, declaration in the for
        statement can become rather verbose. Feel free to initiate the chrono outside of the
        loop, in which case the object remains available after the loop, if you need to add
        steps from the code afterwards, for instance.
        
        .. code:: python
        
           from pyux.time import Chronos
           from time import sleep
           from os import unlink
           
           timed_iterable = Chronos(
              iterable = range(25),
              console_print = True,
              write_tsv = True,
              run_name = 'verbose_declaration',
              path = 'example_times.tsv',
              col_names = ('run', 'lap', 'duration (msecs)'),
              ms = True
           )
           for value in timed_iterable:
               sleep(value / 1000)
           # unlink('example_times.tsv')
        
        
        Module ``logging``
        ~~~~~~~~~~~~~~~~~~
        
        The module contains a function ``init_logger`` that returns a logger
        from `logging package`_ with fixed formatting, but choice in the log
        file name. The default name contains the date and time of execution.
        
        A different log file is created in a given folder at each main
        execution, if the default name is used. If the name is fixed and equal
        from one execution to another, log will be written to the same log file.
        
        ``pyux`` comes with a default format for the logger, but you can specify
        your own ``logging.conf``. Feel free to use ``ColourPen`` to color
        logger messages :
        
        .. code:: python
        
           from pyux.logging import init_logger
           from pyux.console import ColourPen
           from shutil import rmtree
        
           logger = init_logger(folder = 'logs', filename = 'activity', run_name = 'exemple', time_format = '%Y%m%d')
           pen = ColourPen
        
           # writes in green for debug
           pen.write(color = 'green')
           logger.debug('This ia a debug')
        
           # writes in red for critical
           pen.write(color = 'red', style = 'bright')
           logger.critical('This is a critical')
        
           # go back to normal for info
           pen.write(style = 'RESET_ALL')
           logger.info('This is an info')
        
           # rmtree('logs')
        
        The same logger can be used throughout a whole project by calling
        ``logger = logging.getLogger(__name__)`` in submodules.
        
        .. _Contributions: https://gitlab.com/roamdam/pyux
        .. _colorama: https://pypi.org/project/colorama
        .. _tqdm: https://github.com/tqdm/tqdm
        .. _logging package: https://docs.python.org/3/howto/logging.html
        
Platform: UNKNOWN
Description-Content-Type: text/x-rst
