Skip to content

output via generator - #461

Merged
meeuw merged 19 commits into
masterfrom
feature/output_via_generator
Aug 8, 2017
Merged

output via generator#461
meeuw merged 19 commits into
masterfrom
feature/output_via_generator

Conversation

@meeuw

@meeuwmeeuw commented Jun 9, 2017

Copy link
Copy Markdown
Contributor

Description

output via generator to prevent:

  • buffering of the complete output
  • joining and splitting the output

Checklist

  • I've added this contribution to the changelog.md.

@meeuw
meeuwforce-pushed the feature/output_via_generator branch from 7c9066a to 6d0e7fbCompareJune 9, 2017 13:00
Comment threadmycli/main.py Outdated
rows, headers, format_name='vertical')

output.append(formatted)
if isinstance(formatted, str) or isinstance(formatted, unicode):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might want to try adding from mycli.encodingutils import text_type to main.py so you can use that here.

Comment threadmycli/main.py Outdated
from .lexer import MyCliLexer
from .__init__ import __version__

from mycli.encodingutils import text_type

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like I told you wrong - you can add this to line 39 where we are already importing from encodingutils ;) Sorry about that!

Comment threadmycli/main.py Outdated

output.append(formatted)
if isinstance(formatted, text_type):
formatted = formatted.splitlines()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When is formatted not a text_type? I think CLI Helpers always returns a text_type.

@tsroten

Copy link
Copy Markdown
Member

@meeuw Thanks for looking for more ways to improve mycli 😄

So, I'm wondering, what's the advantage of operating on the line level? I'm having trouble understanding what that gets us versus what we have now.

Tabulate and Terminaltables don't return lists or iterables, so it's not like we can process the lines separately. This seems like it calls quite a bit of code for every line.

@meeuw

Copy link
Copy Markdown
ContributorAuthor

Terminaltables is capable of returning an iterable, I'm working on a fix for cli_helpers. Terminaltables still needs to process the complete result set before outputting (to calculate the column width). But for csv/json/xml/tsv/wide output it's possible to iterate the database cursor and format/output the data without buffering the complete result set in memory.

@tsroten

Copy link
Copy Markdown
Member

@meeuw Cool, sounds good to me 😄. Should I review this pull request? Or, wait until the CLI Helpers pull request?

@meeuw
meeuwforce-pushed the feature/output_via_generator branch 2 times, most recently from 1e49d7f to 2ad542aCompareJune 18, 2017 09:28
@codecov-io

codecov-io commented Jun 18, 2017

Copy link
Copy Markdown

Codecov Report

Merging #461 into master will increase coverage by 0.78%.
The diff coverage is 97.36%.

Impacted file tree graph

@@ Coverage Diff @@## master #461 +/- ##
==========================================
+ Coverage 77.83% 78.61% +0.78% 
==========================================
Files 22 22 Lines 2012 2034 +22 ==========================================
+ Hits 1566 1599 +33 + Misses 446 435 -11
Impacted FilesCoverage Δ
mycli/main.py79.76% <97.36%> (+2.39%)⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 2934073...e9b3949. Read the comment docs.

@meeuw

Copy link
Copy Markdown
ContributorAuthor

Related to dbcli/cli_helpers#13

Comment threadmycli/main.py Outdated
click.secho(output)
size = self.cli.output.get_size()

margin = self.get_reserved_space() + self.get_prompt(self.prompt_format).count('\n') + 1

@tsrotentsrotenJun 19, 2017

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get why you're not calling output_fits_on_screen any longer (it compares the entire output), but let's rework that function so we can call it to get the margin so the margin code isn't directly in the output() function.

Since output_fits_on_screen is not used elsewhere, we can rename it and tweak it.

E.g. get_output_margin or something.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I accidentally removed output_fits_on_screen when I was resolving the merge conflicts, thanks for noticing, I'll try to fix it as soon as possible 😄

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm that's a good idea, fixed this.

Comment threadmycli/main.py Outdated

output.append(formatted)
if not isinstance(formatted, types.GeneratorType):
formatted = formatted.splitlines()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@meeuw, so if I understand this correctly, this line won't be needed once the CLI helpers changes are made, right?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

exactly

@tsroten

Copy link
Copy Markdown
Member

@meeuw I'd like to get this in for our next mycli release (so mycli will be ready whenever the next CLI Helpers is released with the generator change).

I'll test it out this weekend. Other than that, the only change I think would be good is this one.

@meeuw
meeuwforce-pushed the feature/output_via_generator branch 4 times, most recently from 5d60435 to 162e824CompareJune 24, 2017 19:30
@tsroten

Copy link
Copy Markdown
Member

So, one thing that's come up in my testing is that the output is always outputted to the pager, even if it fits on the screen. That's how mycli used to output results, but we recently changed it to only output via the pager if it doesn't fit (or there is the explicit pager).

@meeuw
meeuwforce-pushed the feature/output_via_generator branch from 162e824 to 107be90CompareJune 25, 2017 11:44
@meeuw

Copy link
Copy Markdown
ContributorAuthor

Ah you're right. I think I fixed it but I'd like to add additional tests.

@meeuw
meeuwforce-pushed the feature/output_via_generator branch 2 times, most recently from aecef31 to 0614e08CompareJune 29, 2017 08:32
@meeuw

Copy link
Copy Markdown
ContributorAuthor

@tsroten I've added the additional tests but I think they could be a little bit more Pythonic and/or use more pytest features.

@meeuw
meeuwforce-pushed the feature/output_via_generator branch from 0614e08 to 80185c8CompareJuly 2, 2017 06:27
@meeuw
meeuwforce-pushed the feature/output_via_generator branch from 80185c8 to 9e96d36CompareJuly 2, 2017 06:52
@meeuw

meeuw commented Jul 2, 2017

Copy link
Copy Markdown
ContributorAuthor

I'm thinking of using this to check if a generator returned from cli_helpers, but I don't like to add six as a dependency.

@meeuw

meeuw commented Jul 5, 2017

Copy link
Copy Markdown
ContributorAuthor

I've created a PR: pallets/click#815 to allow outputting to the pager using a generator

@meeuw

meeuw commented Jul 9, 2017

Copy link
Copy Markdown
ContributorAuthor

@tsroten thanks, could you please update the tests or tell me how, "if the output doesn't fit and it's not going to be output via a pager, then we lose all the rows after fits is set to False?"

@tsroten

Copy link
Copy Markdown
Member

@meeuw Ok, I added a test that is failing. You can replicate it by:

  1. opening mycli
  2. turn off the pager by running nopager.
  3. run a query that will give you results longer or wider than the console.

You should see the results cut off because the output stops appending to buf.

@meeuw

Copy link
Copy Markdown
ContributorAuthor

You're the best 😄 thanks a lot! Fixed.

Comment threadmycli/main.py Outdated
for i, line in enumerate(output, 1):
self.log_output(line)
# line needs to be casted to unicode for click with Python 2.7
special.write_tee(text_type(line))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to fix whatever is not returning unicode. Do you know what it is? I know the CSV part of CLI Helpers wasn't at one point, but that should be fixed in the version that mycli requires.

If we can't fix it, then, we'll need to convert to unicode for the call to write_once() as well (line 715).

Comment threadmycli/main.py Outdated
**output_kwargs)
first_line = formatted[:formatted.find('\n')]

if isinstance(formatted, (str, text_type)):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can drop str now that the unicode problems in CLI Helpers were fixed.

Comment threadmycli/main.py Outdated
len(first_line) > max_width):
formatted = self.formatter.format_output(
cur, headers, format_name='vertical', column_types=column_types, **output_kwargs)
if isinstance(formatted, (str, text_type)):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here ^^

@meeuw

meeuw commented Aug 7, 2017

Copy link
Copy Markdown
ContributorAuthor

👍 thanks, the cast isn't required anymore.

@tsroten

Copy link
Copy Markdown
Member

@meeuw Good work! I think this is ready to merge. If you could just move the changelog line up to the pending release, we'll be all set.

I wonder if there is a way to word this change so that the end-user understands it.

@meeuw

meeuw commented Aug 7, 2017

Copy link
Copy Markdown
ContributorAuthor

I've rephrased the changelog, English isn't my first language, could you please review? Feel free to change the text.

@tsroten

Copy link
Copy Markdown
Member

@meeuw Ok, I reworded the changelog to be a bit shorter. It indicates that this is preliminary work to use less memory (preliminary, since CLI Helpers is still returning a string and not a generator).

If you agree with the change, then go ahead and merge this in! It'll be good to get this one in finally. Sorry it took so long!

👍 🚀

@meeuw
meeuw merged commit e05cdcf into masterAug 8, 2017
@meeuw
meeuw deleted the feature/output_via_generator branch August 8, 2017 17:07
@meeuw

meeuw commented Aug 8, 2017

Copy link
Copy Markdown
ContributorAuthor

I'm not in a hurry, thanks for your help!

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@meeuw@tsroten@codecov-io@amjith