1212import shutil
1313import subprocess
1414import json
15+ from datetime import datetime
1516from pathlib import Path
1617from argparse import ArgumentParser , RawTextHelpFormatter
1718from . import utils , piptree , diff , __version__
@@ -286,17 +287,18 @@ def top_level_as_requirements(result, comments=(), source=None, verbose=False):
286287
287288 Plainly, it is that file and nothing else: the entries, plus the notes the
288289 source itself carried, so redirecting the output replaces the source
289- without losing what its author wrote in it. -v adds the reasoning -- where
290- the list came from, and every dropped entry commented out with what pulls
291- it in, so re-asking for one is uncommenting it.
290+ without losing what its author wrote in it. -v adds the reasoning -- what
291+ the list is made from and when, the same counts stderr gives, and every
292+ dropped entry commented out with what pulls it in, so re-asking for one is
293+ uncommenting it.
292294 """
293- kept , dropped = result ["kept" ], result ["dropped" ]
294295 lines = []
295296 if verbose :
296- lines += [f"# { Path (source ).name if source else 'installed packages' } , sorted, with every entry" ,
297- f"# another one already pulls in commented out: { len (kept ) + len (dropped )} entries -> { len (kept )} ." ,
298- "" ]
299- lines += kept
297+ lines += [f"# { Path (source ).name if source else 'installed packages' } , sorted,"
298+ f" { datetime .now ():%Y-%m-%d %H:%M:%S} " ]
299+ lines += top_level_summary (result ) + ["" ]
300+ lines += result ["kept" ]
301+ dropped = result ["dropped" ]
300302 if verbose and dropped :
301303 lines += ["" , "# ---- already pulled in by an entry above ----" ]
302304 for text , pullers in dropped .items ():
@@ -308,8 +310,10 @@ def top_level_as_requirements(result, comments=(), source=None, verbose=False):
308310def top_level_summary (result ):
309311 """What the caller should know about the answer, rather than of it.
310312
311- Commented, though it goes to stderr: someone will fold the two streams
312- into one file sooner or later, and a comment costs nothing.
313+ Goes to stderr, so a redirected list stays a list -- and heads the list
314+ itself under -v, where the reasoning belongs in the file. Commented either
315+ way: someone will fold the two streams into one file sooner or later, and a
316+ comment costs nothing.
313317 """
314318 kept , dropped = result ["kept" ], result ["dropped" ]
315319 notes = [f"{ len (kept ) + len (dropped )} entries -> { len (kept )} kept, { len (dropped )} already pulled in" ]
@@ -384,8 +388,9 @@ def main(test=False):
384388 sys .exit ()
385389 for line in top_level_as_requirements (result , comments , source , args .verbose ):
386390 print (line )
387- for note in top_level_summary (result ): # stderr: a redirected list stays a list
388- print (note , file = sys .stderr )
391+ if not args .verbose : # -v already heads the list with them; don't say it twice
392+ for note in top_level_summary (result ):
393+ print (note , file = sys .stderr )
389394 sys .exit ()
390395 elif args .list :
391396 pip = piptree .PipData (targetpython , args .wheelsource )
0 commit comments