Skip to content

Support with statements - #120

Closed
kbairak wants to merge 1 commit into
astanin:masterfrom
kbairak:context_manager
Closed

Support with statements#120
kbairak wants to merge 1 commit into
astanin:masterfrom
kbairak:context_manager

Conversation

@kbairak

@kbairak kbairak commented Mar 14, 2021

Copy link
Copy Markdown

This is a re-implementation of #81

Copying from README:

Usage as a context manager

You can call TabulateContextManager in a with statement to incrementally
add rows to the table. Upon exit, the whole table will be printed to the
standard output:

with TabulateContextManager() as t:
    t("Bill", 25)
    t("Mary", 26)

# <<< ----  --
# ... Bill  25
# ... Mary  26
# ... ----  --

TabulateContextManager accepts the same parameters as tabulate:

with TabulateContextManager(headers="firstrow", tablefmt="github") as t:
    t('name', 'age')
    t("Bill", 25)
    t("Mary", 26)
# <<< | name   |   age |
# ... |--------|-------|
# ... | Bill   |    25 |
# ... | Mary   |    26 |

If you don't want to print to the standard output, you can supply the
print_fn keyword argument which will be called on exit:

with open('output.txt', 'w') as f:
    with TabulateContextManager(print_fn=f.write) as t:
        t("Bill", 25)
        t("Mary", 26)

@kbairak kbairak mentioned this pull request Mar 14, 2021
@vrza

vrza commented Nov 30, 2021

Copy link
Copy Markdown
Contributor

On first glance this doesn't seem to be in line with the intended use of with statements, which is factoring out standard uses of try/except/finally.

The code in included unit tests doesn't throw any exceptions. Although __exit__ should return a boolean value, both the default function and the one included in the test return None -- which means any exception caught by the with block will always be re-thrown. I.e. __exit__ is here used purely for side-effect, and not to decide whether to re-raise the exception.

The example in the README:

with TabulateContextManager() as t:
    t("Bill", 25)
    t("Mary", 26)

is roughly equivalent to:

try: 
    rows = []
    rows.append("Bill", 25)
    rows.append("Mary", 26)
except:
    raise
finally:
    print(tabulate(rows))

I suggest reading through PEP-0343 and reconsidering if the above is really a common use case for users of this library. Is your use case really that on exceptions while adding rows you want to print whatever made its way into the table data and then re-throw exception? Because this is what the code in this PR does, albeit through use of syntactic sugar.

If your use case is really this:

    rows = []
    rows.append("Bill", 25)
    rows.append("Mary", 26)
    print(tabulate(rows))

then it is IMHO a use case where there's no need for context management (that array with data in the example can reside in whatever context programmer wants it in, e.g. the scope of a function or in some object) and exception handling (non-existent in the example, so there's nothing for the wtih block to factor out), and so the with block doesn't add any value. On the contrary, it could make the code (especially the exception handling part) harder to understand.

@kbairak

kbairak commented Dec 1, 2021

Copy link
Copy Markdown
Author

TBH I was only looking after the "syntactic sugar" part. I agree with your concerns and that this "feature" is not important. Please feel free to close this PR if you want.

@vrza

vrza commented Dec 1, 2021

Copy link
Copy Markdown
Contributor

Thank you @kbairak for confirming, glad that we could get on the same page.

@astanin I do recommend closing this PR to avoid "feature creep".

@astanin

astanin commented Jun 22, 2022

Copy link
Copy Markdown
Owner

I agree with you that it is feature creep at the moment, and it goes against "Explicit is better than implicit" principle.

@astanin astanin closed this Jun 22, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants