Metadata-Version: 2.1
Name: scolp
Version: 0.1.4
Summary: Streaming Column Printer
Home-page: https://github.com/davidohana/python-scolp
Author: David Ohana
Author-email: davidoha@gmail.com
License: UNKNOWN
Description: # Scolp
        
        ## Introduction
        
        Scolp is Streaming Column Printer for Python 3.6 or later.
        
        Scolp let you easily pretty-print masses of tabular data in a streaming fashion - each value is printed when available, without waiting for end of data. It is perfect for apps that need to print progress reports in columns.
        
        Main features:
        
        * Auto-adjusting column width according to the largest value so far or column header width.
        
        * Control verbosity of printing by:
            - printing ``1`` of each ``n`` rows
            - printing no more than ``1`` row per ``n`` seconds
        
        * Control format of printed values by:
            - setting global defaults
            - setting defaults per variable type (``int``, ``float``, ``str``, ``datetime``)
            - setting explicit formatting per column
        
        * Control alignment of printed values:
            - left
            - right
            - center
            - auto: numbers to the right, strings or other types to the left.
        
        * Control cosmetics of columns (initial width, padding fill char, alignment, and more..) by:
            - setting global defaults
            - setting explicit formatting per column
        
        * Control column title printing style:
            - Inline in each row
            - As headers, repeating each n rows
        
        * Easily print row count or time since execution started without need to keep track of those values yourself.
        
        ## Examples
        
        #### Example 1
        
        Lets start with a simple country statistics output using default settings:
        
        ```python
        import scolp
        
        scolper = scolp.Scolp()
        scolper.config.add_columns("country", "population (mil)", "capital city", "life expectancy (female)",
                                   "life expectancy (male)", "fertility rate")
        scolper.print("Netherlands", 16.81, "Amsterdam", 83, 79, 1.5,
                      "China", 1350.0, "Beijing", 76, 72, 1.8,
                      "Israel", 7.71, "Jerusalem", 84, 80, 2.7,
                      "Nigeria")
        scolper.print(174.51)
        ```
        
        Output: 
        
        (Note how column width is auto adjusting, line breaks are printed automatically after last column, and each value is printed immediately without waiting for end of row)
        
        ```
        country |population (mil)|capital city|life expectancy (female)|life expectancy (male)|fertility rate
        --------|----------------|------------|------------------------|----------------------|--------------
        Netherlands|          16.810|Amsterdam   |                      83|                    79|         1.500
        
        country    |population (mil)|capital city|life expectancy (female)|life expectancy (male)|fertility rate
        -----------|----------------|------------|------------------------|----------------------|--------------
        China      |       1,350.000|Beijing     |                      76|                    72|         1.800
        Israel     |           7.710|Jerusalem   |                      84|                    80|         2.700
        Nigeria    |         174.510|
        ```
        
        #### Example 2
        
        Lets build a program that find prime numbers. We will print the count of primes
        we found so far and the last prime found.
        
        ```python
        import datetime, scolp
        
        def is_prime(num):
            return 2 in [num, 2 ** num % num]
        
        scolper = scolp.Scolp()
        scolper.config.add_columns("time", "elapsed", "inspected_count", "prime_count", "last", "progress %")
        scolper.config.output_each_n_seconds = 1
        
        prime_count = 0
        last_prime = None
        i = 9_999_800
        target_count = 30
        while prime_count < target_count:
            if is_prime(i):
                last_prime = i
                prime_count += 1
            progress = prime_count / target_count * 100
            scolper.print(datetime.datetime.now(), scolper.elapsed_since_init(),
                          scolper.row_index + 1, prime_count, last_prime, progress)
            i += 1
        
        ```
        
        Output: 
        
        (Note how the header repeats, the column width auto-expanding and the numbers are aligned to the right)
        
        ```
        time    |elapsed |inspected_count|prime_count|last    |progress %
        --------|--------|---------------|-----------|--------|----------
        2019-06-05 11:49:31.271191|0:00:00 |              1|          0|None    |     0.000
        
        time                      |elapsed |inspected_count|prime_count|last    |progress %
        --------------------------|--------|---------------|-----------|--------|----------
        2019-06-05 11:49:32.306225|0:00:01 |             27|          1|9,999,823|     3.333
        2019-06-05 11:49:33.325694|0:00:02 |             53|          1|9,999,823|     3.333
        2019-06-05 11:49:34.341678|0:00:03 |             79|          3|9,999,877|    10.000
        2019-06-05 11:49:35.378966|0:00:04 |            105|          6|9,999,901|    20.000
        2019-06-05 11:49:36.399298|0:00:05 |            131|          8|9,999,929|    26.667
        2019-06-05 11:49:37.415522|0:00:06 |            157|         11|9,999,943|    36.667
        2019-06-05 11:49:38.450551|0:00:07 |            183|         13|9,999,973|    43.333
        2019-06-05 11:49:39.478987|0:00:08 |            209|         14|9,999,991|    46.667
        2019-06-05 11:49:40.485409|0:00:09 |            233|         15|10,000,019|    50.000
        
        time                      |elapsed |inspected_count|prime_count|last      |progress %
        --------------------------|--------|---------------|-----------|----------|----------
        2019-06-05 11:49:41.508298|0:00:10 |            259|         15|10,000,019|    50.000
        2019-06-05 11:49:42.543115|0:00:11 |            283|         16|10,000,079|    53.333
        2019-06-05 11:49:43.555733|0:00:12 |            306|         17|10,000,103|    56.667
        2019-06-05 11:49:44.572379|0:00:13 |            328|         18|10,000,121|    60.000
        2019-06-05 11:49:45.574066|0:00:14 |            349|         20|10,000,141|    66.667
        2019-06-05 11:49:46.583462|0:00:15 |            372|         21|10,000,169|    70.000
        2019-06-05 11:49:47.594724|0:00:16 |            396|         22|10,000,189|    73.333
        2019-06-05 11:49:48.639124|0:00:17 |            420|         22|10,000,189|    73.333
        2019-06-05 11:49:49.661211|0:00:18 |            441|         24|10,000,229|    80.000
        2019-06-05 11:49:50.691037|0:00:19 |            463|         27|10,000,261|    90.000
        
        time                      |elapsed |inspected_count|prime_count|last      |progress %
        --------------------------|--------|---------------|-----------|----------|----------
        2019-06-05 11:49:51.721844|0:00:20 |            487|         28|10,000,271|    93.333
        2019-06-05 11:49:52.733437|0:00:22 |            510|         29|10,000,303|    96.667
        2019-06-05 11:49:53.750463|0:00:23 |            534|         29|10,000,303|    96.667
        ```
        
        #### Example 3
        
        Now, lets change the code of the previous example to add a bit of custom formatting:
        
        ```python
        scolper = scolp.Scolp()
        scolper.config.add_column("time", width=20)
        scolper.config.add_columns("elapsed",
                                   "inspected_count",
                                   "prime_count")
        scolper.config.add_column("last", width=11)
        scolper.config.add_column("progress", fmt="{:.1%}")
        scolper.config.output_each_n_seconds = 1
        scolper.config.header_repeat_row_count_first = 0
        scolper.config.default_column.column_separator = " "
        scolper.config.default_column.type_to_format[datetime.datetime] = "{:%Y-%m-%d %H:%M:%S}"
        
        prime_count = 0
        last_prime = None
        i = 9_999_800
        target_count = 30
        while prime_count < target_count:
            if is_prime(i):
                last_prime = i
                prime_count += 1
            progress = prime_count / target_count
            scolper.print(datetime.datetime.now(), scolper.elapsed_since_init(),
                          scolper.row_index + 1, prime_count, last_prime, progress)
            i += 1
        ```
        
        Output:
        
        ```
        time                 elapsed  inspected_count prime_count last        progress
        -------------------- -------- --------------- ----------- ----------- --------
        2019-06-05 11:54:46  0:00:00                1           0 None            0.0%
        2019-06-05 11:54:47  0:00:01               23           0 None            0.0%
        2019-06-05 11:54:48  0:00:02               45           1   9,999,823     3.3%
        2019-06-05 11:54:49  0:00:03               67           2   9,999,863     6.7%
        2019-06-05 11:54:50  0:00:04               90           5   9,999,889    16.7%
        2019-06-05 11:54:51  0:00:05              115           7   9,999,907    23.3%
        2019-06-05 11:54:52  0:00:06              139          10   9,999,937    33.3%
        2019-06-05 11:54:53  0:00:07              164          11   9,999,943    36.7%
        2019-06-05 11:54:54  0:00:08              188          13   9,999,973    43.3%
        2019-06-05 11:54:55  0:00:09              212          14   9,999,991    46.7%
        
        time                 elapsed  inspected_count prime_count last        progress
        -------------------- -------- --------------- ----------- ----------- --------
        2019-06-05 11:54:56  0:00:10              237          15  10,000,019    50.0%
        2019-06-05 11:54:57  0:00:11              261          15  10,000,019    50.0%
        2019-06-05 11:54:58  0:00:12              284          16  10,000,079    53.3%
        2019-06-05 11:54:59  0:00:13              308          17  10,000,103    56.7%
        2019-06-05 11:55:00  0:00:14              331          18  10,000,121    60.0%
        2019-06-05 11:55:01  0:00:15              355          20  10,000,141    66.7%
        2019-06-05 11:55:02  0:00:16              379          21  10,000,169    70.0%
        2019-06-05 11:55:03  0:00:17              403          22  10,000,189    73.3%
        2019-06-05 11:55:04  0:00:18              426          23  10,000,223    76.7%
        2019-06-05 11:55:05  0:00:20              448          25  10,000,247    83.3%
        
        time                 elapsed  inspected_count prime_count last        progress
        -------------------- -------- --------------- ----------- ----------- --------
        2019-06-05 11:55:06  0:00:21              471          27  10,000,261    90.0%
        2019-06-05 11:55:07  0:00:22              493          28  10,000,271    93.3%
        2019-06-05 11:55:08  0:00:23              516          29  10,000,303    96.7%
        2019-06-05 11:55:09  0:00:24              539          29  10,000,303    96.7%
        ```
        
        #### Example 4
        
        Lets build an HTTP big-file downloader.
        
        ```python
        import datetime, urllib3, scolp
        
        url = "http://speedtest.tele2.net/100MB.zip"
        path = "downloaded.tmp"
        chunk_size_bytes = 1000
        
        scolp_cfg = scolp.Config()
        scolp_cfg.add_column("time", fmt="{:%H:%M:%S}")
        scolp_cfg.add_column("elapsed")
        scolp_cfg.add_column("downloaded", width=16, fmt="{:,} B")
        scolp_cfg.add_column("speed", width=14, pad_align=scolp.Alignment.RIGHT, type_to_format={float: "{:,.1f} kB/s"})
        
        scolp_cfg.output_each_n_seconds = 1
        scolp_cfg.title_mode = scolp.TitleMode.INLINE
        scolp_cfg.default_column.column_separator = "  |  "
        
        scolper = scolp.Scolp(scolp_cfg)
        
        http = urllib3.PoolManager()
        r = http.request('GET', url, preload_content=False)
        
        dl_bytes = 0
        
        
        def progress_update():
            elapsed_sec = scolper.elapsed_since_init().total_seconds()
            speed_kbps = dl_bytes / elapsed_sec / 1000 if elapsed_sec > 0 else "unknown"
            scolper.print(datetime.datetime.now(), scolper.elapsed_since_init(), dl_bytes, speed_kbps)
        
        
        with open(path, 'wb') as out:
            while True:
                data = r.read(chunk_size_bytes)
                if not data:
                    break
                out.write(data)
                dl_bytes += len(data)
                progress_update()
        
        scolper.force_print_next_row()
        progress_update()
        r.release_conn()
        
        ```
        
        Output:
        
        ```
        time=14:30:11  |  elapsed=0:00:00   |  downloaded=         1,000 B  |  speed=       unknown
        time=14:30:12  |  elapsed=0:00:01   |  downloaded=       801,000 B  |  speed=    801.0 kB/s
        time=14:30:13  |  elapsed=0:00:02   |  downloaded=     1,743,000 B  |  speed=    871.5 kB/s
        time=14:30:14  |  elapsed=0:00:03   |  downloaded=     2,758,000 B  |  speed=    919.3 kB/s
        time=14:30:15  |  elapsed=0:00:04   |  downloaded=     3,779,000 B  |  speed=    944.8 kB/s
        time=14:30:16  |  elapsed=0:00:05   |  downloaded=     4,794,000 B  |  speed=    958.8 kB/s
        time=14:30:17  |  elapsed=0:00:06   |  downloaded=     5,809,000 B  |  speed=    968.2 kB/s
        time=14:30:18  |  elapsed=0:00:07   |  downloaded=     6,824,000 B  |  speed=    974.9 kB/s
        time=14:30:19  |  elapsed=0:00:08   |  downloaded=     7,839,000 B  |  speed=    979.9 kB/s
        time=14:30:20  |  elapsed=0:00:09   |  downloaded=     8,857,000 B  |  speed=    984.1 kB/s
        time=14:30:21  |  elapsed=0:00:10   |  downloaded=     9,799,000 B  |  speed=    979.9 kB/s
        time=14:30:22  |  elapsed=0:00:11   |  downloaded=    10,814,000 B  |  speed=    983.1 kB/s
        time=14:30:23  |  elapsed=0:00:12   |  downloaded=    11,838,000 B  |  speed=    986.5 kB/s
        time=14:30:24  |  elapsed=0:00:13   |  downloaded=    12,855,000 B  |  speed=    988.8 kB/s
        time=14:30:25  |  elapsed=0:00:14   |  downloaded=    13,870,000 B  |  speed=    990.7 kB/s
        time=14:30:26  |  elapsed=0:00:15   |  downloaded=    14,891,000 B  |  speed=    992.7 kB/s
        time=14:30:27  |  elapsed=0:00:16   |  downloaded=    15,906,000 B  |  speed=    994.1 kB/s
        time=14:30:28  |  elapsed=0:00:18   |  downloaded=    25,600,000 B  |  speed=  1,422.2 kB/s
        time=14:30:29  |  elapsed=0:00:19   |  downloaded=    37,146,000 B  |  speed=  1,955.1 kB/s
        time=14:30:30  |  elapsed=0:00:20   |  downloaded=    47,847,000 B  |  speed=  2,392.3 kB/s
        time=14:30:31  |  elapsed=0:00:21   |  downloaded=    60,962,000 B  |  speed=  2,903.0 kB/s
        time=14:30:32  |  elapsed=0:00:22   |  downloaded=    72,931,000 B  |  speed=  3,315.0 kB/s
        time=14:30:33  |  elapsed=0:00:23   |  downloaded=    85,094,000 B  |  speed=  3,699.7 kB/s
        time=14:30:34  |  elapsed=0:00:24   |  downloaded=   104,857,600 B  |  speed=  4,369.1 kB/s
        ```
        
        
        ## Requirements
        
        Scolp has no 3rd party requirements other than Python 3.6 or later.
        
        
        ## Getting Started
        
        Scolp is available via PyPi and can be installed using:
        
        ```pip install scolp```.
        
        ## Todo
        
        * Document public API of the library
        * Support colors
Platform: UNKNOWN
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Topic :: Software Development :: Libraries
Description-Content-Type: text/markdown
