pyflyby 1.9.7__tar.gz → 1.9.8__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of pyflyby might be problematic. Click here for more details.

Files changed (158) hide show
  1. {pyflyby-1.9.7/lib/python/pyflyby.egg-info → pyflyby-1.9.8}/PKG-INFO +11 -11
  2. {pyflyby-1.9.7 → pyflyby-1.9.8}/README.rst +9 -9
  3. {pyflyby-1.9.7 → pyflyby-1.9.8}/bin/pyflyby/_autoimp.py +45 -17
  4. {pyflyby-1.9.7/lib/python → pyflyby-1.9.8/bin}/pyflyby/_importdb.py +5 -3
  5. {pyflyby-1.9.7 → pyflyby-1.9.8}/bin/pyflyby/_importstmt.py +1 -1
  6. {pyflyby-1.9.7 → pyflyby-1.9.8}/bin/pyflyby/_interactive.py +13 -6
  7. {pyflyby-1.9.7/lib/python → pyflyby-1.9.8/bin}/pyflyby/_parse.py +27 -18
  8. {pyflyby-1.9.7/lib/python → pyflyby-1.9.8/bin}/pyflyby/_py.py +18 -18
  9. {pyflyby-1.9.7 → pyflyby-1.9.8}/bin/pyflyby/_util.py +1 -2
  10. {pyflyby-1.9.7/lib/python → pyflyby-1.9.8/bin}/pyflyby/_version.py +1 -1
  11. {pyflyby-1.9.7 → pyflyby-1.9.8}/lib/python/pyflyby/_autoimp.py +45 -17
  12. {pyflyby-1.9.7/bin → pyflyby-1.9.8/lib/python}/pyflyby/_importdb.py +5 -3
  13. {pyflyby-1.9.7 → pyflyby-1.9.8}/lib/python/pyflyby/_importstmt.py +1 -1
  14. {pyflyby-1.9.7 → pyflyby-1.9.8}/lib/python/pyflyby/_interactive.py +13 -6
  15. {pyflyby-1.9.7/bin → pyflyby-1.9.8/lib/python}/pyflyby/_parse.py +27 -18
  16. {pyflyby-1.9.7/bin → pyflyby-1.9.8/lib/python}/pyflyby/_py.py +18 -18
  17. {pyflyby-1.9.7 → pyflyby-1.9.8}/lib/python/pyflyby/_util.py +1 -2
  18. {pyflyby-1.9.7/bin → pyflyby-1.9.8/lib/python}/pyflyby/_version.py +1 -1
  19. {pyflyby-1.9.7 → pyflyby-1.9.8/lib/python/pyflyby.egg-info}/PKG-INFO +11 -11
  20. {pyflyby-1.9.7 → pyflyby-1.9.8}/setup.py +1 -1
  21. {pyflyby-1.9.7 → pyflyby-1.9.8}/tests/test_autoimp.py +11 -1
  22. {pyflyby-1.9.7 → pyflyby-1.9.8}/tests/test_modules.py +3 -1
  23. {pyflyby-1.9.7 → pyflyby-1.9.8}/tests/test_parse.py +36 -0
  24. {pyflyby-1.9.7 → pyflyby-1.9.8}/.pyflyby +0 -0
  25. {pyflyby-1.9.7 → pyflyby-1.9.8}/LICENSE.txt +0 -0
  26. {pyflyby-1.9.7 → pyflyby-1.9.8}/MANIFEST.in +0 -0
  27. {pyflyby-1.9.7 → pyflyby-1.9.8}/bin/autoipython +0 -0
  28. {pyflyby-1.9.7 → pyflyby-1.9.8}/bin/autopython +0 -0
  29. {pyflyby-1.9.7 → pyflyby-1.9.8}/bin/collect-exports +0 -0
  30. {pyflyby-1.9.7 → pyflyby-1.9.8}/bin/collect-imports +0 -0
  31. {pyflyby-1.9.7 → pyflyby-1.9.8}/bin/create-imports +0 -0
  32. {pyflyby-1.9.7 → pyflyby-1.9.8}/bin/find-import +0 -0
  33. {pyflyby-1.9.7 → pyflyby-1.9.8}/bin/list-bad-xrefs +0 -0
  34. {pyflyby-1.9.7 → pyflyby-1.9.8}/bin/prune-broken-imports +0 -0
  35. {pyflyby-1.9.7 → pyflyby-1.9.8}/bin/py +0 -0
  36. {pyflyby-1.9.7 → pyflyby-1.9.8}/bin/pyflyby/__init__.py +0 -0
  37. {pyflyby-1.9.7 → pyflyby-1.9.8}/bin/pyflyby/__main__.py +0 -0
  38. {pyflyby-1.9.7 → pyflyby-1.9.8}/bin/pyflyby/_cmdline.py +0 -0
  39. {pyflyby-1.9.7 → pyflyby-1.9.8}/bin/pyflyby/_comms.py +0 -0
  40. {pyflyby-1.9.7 → pyflyby-1.9.8}/bin/pyflyby/_dbg.py +0 -0
  41. {pyflyby-1.9.7 → pyflyby-1.9.8}/bin/pyflyby/_docxref.py +0 -0
  42. {pyflyby-1.9.7 → pyflyby-1.9.8}/bin/pyflyby/_dynimp.py +0 -0
  43. {pyflyby-1.9.7 → pyflyby-1.9.8}/bin/pyflyby/_file.py +0 -0
  44. {pyflyby-1.9.7 → pyflyby-1.9.8}/bin/pyflyby/_flags.py +0 -0
  45. {pyflyby-1.9.7 → pyflyby-1.9.8}/bin/pyflyby/_format.py +0 -0
  46. {pyflyby-1.9.7 → pyflyby-1.9.8}/bin/pyflyby/_idents.py +0 -0
  47. {pyflyby-1.9.7 → pyflyby-1.9.8}/bin/pyflyby/_import_sorting.py +0 -0
  48. {pyflyby-1.9.7 → pyflyby-1.9.8}/bin/pyflyby/_importclns.py +0 -0
  49. {pyflyby-1.9.7 → pyflyby-1.9.8}/bin/pyflyby/_imports2s.py +0 -0
  50. {pyflyby-1.9.7 → pyflyby-1.9.8}/bin/pyflyby/_livepatch.py +0 -0
  51. {pyflyby-1.9.7 → pyflyby-1.9.8}/bin/pyflyby/_log.py +0 -0
  52. {pyflyby-1.9.7 → pyflyby-1.9.8}/bin/pyflyby/_modules.py +0 -0
  53. {pyflyby-1.9.7 → pyflyby-1.9.8}/bin/pyflyby/_saveframe.py +0 -0
  54. {pyflyby-1.9.7 → pyflyby-1.9.8}/bin/pyflyby/autoimport.py +0 -0
  55. {pyflyby-1.9.7 → pyflyby-1.9.8}/bin/pyflyby/importdb.py +0 -0
  56. {pyflyby-1.9.7 → pyflyby-1.9.8}/bin/pyflyby-diff +0 -0
  57. {pyflyby-1.9.7 → pyflyby-1.9.8}/bin/reformat-imports +0 -0
  58. {pyflyby-1.9.7 → pyflyby-1.9.8}/bin/replace-star-imports +0 -0
  59. {pyflyby-1.9.7 → pyflyby-1.9.8}/bin/saveframe +0 -0
  60. {pyflyby-1.9.7 → pyflyby-1.9.8}/bin/tidy-imports +0 -0
  61. {pyflyby-1.9.7 → pyflyby-1.9.8}/bin/transform-imports +0 -0
  62. {pyflyby-1.9.7 → pyflyby-1.9.8}/doc/LICENSE.txt +0 -0
  63. {pyflyby-1.9.7 → pyflyby-1.9.8}/doc/Makefile +0 -0
  64. {pyflyby-1.9.7 → pyflyby-1.9.8}/doc/TODO.txt +0 -0
  65. {pyflyby-1.9.7 → pyflyby-1.9.8}/doc/__init__.py +0 -0
  66. {pyflyby-1.9.7 → pyflyby-1.9.8}/doc/api/api.rst +0 -0
  67. {pyflyby-1.9.7 → pyflyby-1.9.8}/doc/api/autoimp.rst +0 -0
  68. {pyflyby-1.9.7 → pyflyby-1.9.8}/doc/api/cmdline.rst +0 -0
  69. {pyflyby-1.9.7 → pyflyby-1.9.8}/doc/api/comms.rst +0 -0
  70. {pyflyby-1.9.7 → pyflyby-1.9.8}/doc/api/dbg.rst +0 -0
  71. {pyflyby-1.9.7 → pyflyby-1.9.8}/doc/api/file.rst +0 -0
  72. {pyflyby-1.9.7 → pyflyby-1.9.8}/doc/api/flags.rst +0 -0
  73. {pyflyby-1.9.7 → pyflyby-1.9.8}/doc/api/format.rst +0 -0
  74. {pyflyby-1.9.7 → pyflyby-1.9.8}/doc/api/idents.rst +0 -0
  75. {pyflyby-1.9.7 → pyflyby-1.9.8}/doc/api/importclns.rst +0 -0
  76. {pyflyby-1.9.7 → pyflyby-1.9.8}/doc/api/importdb.rst +0 -0
  77. {pyflyby-1.9.7 → pyflyby-1.9.8}/doc/api/imports2s.rst +0 -0
  78. {pyflyby-1.9.7 → pyflyby-1.9.8}/doc/api/importstmt.rst +0 -0
  79. {pyflyby-1.9.7 → pyflyby-1.9.8}/doc/api/interactive.rst +0 -0
  80. {pyflyby-1.9.7 → pyflyby-1.9.8}/doc/api/livepatch.rst +0 -0
  81. {pyflyby-1.9.7 → pyflyby-1.9.8}/doc/api/log.rst +0 -0
  82. {pyflyby-1.9.7 → pyflyby-1.9.8}/doc/api/modules.rst +0 -0
  83. {pyflyby-1.9.7 → pyflyby-1.9.8}/doc/api/parse.rst +0 -0
  84. {pyflyby-1.9.7 → pyflyby-1.9.8}/doc/api/py.rst +0 -0
  85. {pyflyby-1.9.7 → pyflyby-1.9.8}/doc/api/util.rst +0 -0
  86. {pyflyby-1.9.7 → pyflyby-1.9.8}/doc/cli/autoipython.rst +0 -0
  87. {pyflyby-1.9.7 → pyflyby-1.9.8}/doc/cli/cli.rst +0 -0
  88. {pyflyby-1.9.7 → pyflyby-1.9.8}/doc/cli/collect_exports.rst +0 -0
  89. {pyflyby-1.9.7 → pyflyby-1.9.8}/doc/cli/collect_imports.rst +0 -0
  90. {pyflyby-1.9.7 → pyflyby-1.9.8}/doc/cli/find_import.rst +0 -0
  91. {pyflyby-1.9.7 → pyflyby-1.9.8}/doc/cli/prune_broken_imports.rst +0 -0
  92. {pyflyby-1.9.7 → pyflyby-1.9.8}/doc/cli/py.rst +0 -0
  93. {pyflyby-1.9.7 → pyflyby-1.9.8}/doc/cli/pyflyby_diff.rst +0 -0
  94. {pyflyby-1.9.7 → pyflyby-1.9.8}/doc/cli/reformat_imports.rst +0 -0
  95. {pyflyby-1.9.7 → pyflyby-1.9.8}/doc/cli/replace_star_imports.rst +0 -0
  96. {pyflyby-1.9.7 → pyflyby-1.9.8}/doc/cli/tidy_imports.rst +0 -0
  97. {pyflyby-1.9.7 → pyflyby-1.9.8}/doc/cli/transform_imports.rst +0 -0
  98. {pyflyby-1.9.7 → pyflyby-1.9.8}/doc/conf.py +0 -0
  99. {pyflyby-1.9.7 → pyflyby-1.9.8}/doc/index.rst +0 -0
  100. {pyflyby-1.9.7 → pyflyby-1.9.8}/doc/make.bat +0 -0
  101. {pyflyby-1.9.7 → pyflyby-1.9.8}/doc/testing.txt +0 -0
  102. {pyflyby-1.9.7 → pyflyby-1.9.8}/etc/pyflyby/canonical.py +0 -0
  103. {pyflyby-1.9.7 → pyflyby-1.9.8}/etc/pyflyby/common.py +0 -0
  104. {pyflyby-1.9.7 → pyflyby-1.9.8}/etc/pyflyby/forget.py +0 -0
  105. {pyflyby-1.9.7 → pyflyby-1.9.8}/etc/pyflyby/mandatory.py +0 -0
  106. {pyflyby-1.9.7 → pyflyby-1.9.8}/etc/pyflyby/numpy.py +0 -0
  107. {pyflyby-1.9.7 → pyflyby-1.9.8}/etc/pyflyby/std.py +0 -0
  108. {pyflyby-1.9.7 → pyflyby-1.9.8}/lib/emacs/pyflyby.el +0 -0
  109. {pyflyby-1.9.7 → pyflyby-1.9.8}/lib/python/pyflyby/__init__.py +0 -0
  110. {pyflyby-1.9.7 → pyflyby-1.9.8}/lib/python/pyflyby/__main__.py +0 -0
  111. {pyflyby-1.9.7 → pyflyby-1.9.8}/lib/python/pyflyby/_cmdline.py +0 -0
  112. {pyflyby-1.9.7 → pyflyby-1.9.8}/lib/python/pyflyby/_comms.py +0 -0
  113. {pyflyby-1.9.7 → pyflyby-1.9.8}/lib/python/pyflyby/_dbg.py +0 -0
  114. {pyflyby-1.9.7 → pyflyby-1.9.8}/lib/python/pyflyby/_docxref.py +0 -0
  115. {pyflyby-1.9.7 → pyflyby-1.9.8}/lib/python/pyflyby/_dynimp.py +0 -0
  116. {pyflyby-1.9.7 → pyflyby-1.9.8}/lib/python/pyflyby/_file.py +0 -0
  117. {pyflyby-1.9.7 → pyflyby-1.9.8}/lib/python/pyflyby/_flags.py +0 -0
  118. {pyflyby-1.9.7 → pyflyby-1.9.8}/lib/python/pyflyby/_format.py +0 -0
  119. {pyflyby-1.9.7 → pyflyby-1.9.8}/lib/python/pyflyby/_idents.py +0 -0
  120. {pyflyby-1.9.7 → pyflyby-1.9.8}/lib/python/pyflyby/_import_sorting.py +0 -0
  121. {pyflyby-1.9.7 → pyflyby-1.9.8}/lib/python/pyflyby/_importclns.py +0 -0
  122. {pyflyby-1.9.7 → pyflyby-1.9.8}/lib/python/pyflyby/_imports2s.py +0 -0
  123. {pyflyby-1.9.7 → pyflyby-1.9.8}/lib/python/pyflyby/_livepatch.py +0 -0
  124. {pyflyby-1.9.7 → pyflyby-1.9.8}/lib/python/pyflyby/_log.py +0 -0
  125. {pyflyby-1.9.7 → pyflyby-1.9.8}/lib/python/pyflyby/_modules.py +0 -0
  126. {pyflyby-1.9.7 → pyflyby-1.9.8}/lib/python/pyflyby/_saveframe.py +0 -0
  127. {pyflyby-1.9.7 → pyflyby-1.9.8}/lib/python/pyflyby/autoimport.py +0 -0
  128. {pyflyby-1.9.7 → pyflyby-1.9.8}/lib/python/pyflyby/importdb.py +0 -0
  129. {pyflyby-1.9.7 → pyflyby-1.9.8}/lib/python/pyflyby.egg-info/SOURCES.txt +0 -0
  130. {pyflyby-1.9.7 → pyflyby-1.9.8}/lib/python/pyflyby.egg-info/dependency_links.txt +0 -0
  131. {pyflyby-1.9.7 → pyflyby-1.9.8}/lib/python/pyflyby.egg-info/entry_points.txt +0 -0
  132. {pyflyby-1.9.7 → pyflyby-1.9.8}/lib/python/pyflyby.egg-info/requires.txt +0 -0
  133. {pyflyby-1.9.7 → pyflyby-1.9.8}/lib/python/pyflyby.egg-info/top_level.txt +0 -0
  134. {pyflyby-1.9.7 → pyflyby-1.9.8}/libexec/pyflyby/colordiff +0 -0
  135. {pyflyby-1.9.7 → pyflyby-1.9.8}/libexec/pyflyby/diff-colorize +0 -0
  136. {pyflyby-1.9.7 → pyflyby-1.9.8}/pyproject.toml +0 -0
  137. {pyflyby-1.9.7 → pyflyby-1.9.8}/setup.cfg +0 -0
  138. {pyflyby-1.9.7 → pyflyby-1.9.8}/tests/__init__.py +0 -0
  139. {pyflyby-1.9.7 → pyflyby-1.9.8}/tests/test_0testconfig.py +0 -0
  140. {pyflyby-1.9.7 → pyflyby-1.9.8}/tests/test_cmdline.py +0 -0
  141. {pyflyby-1.9.7 → pyflyby-1.9.8}/tests/test_docxref.py +0 -0
  142. {pyflyby-1.9.7 → pyflyby-1.9.8}/tests/test_file.py +0 -0
  143. {pyflyby-1.9.7 → pyflyby-1.9.8}/tests/test_flags.py +0 -0
  144. {pyflyby-1.9.7 → pyflyby-1.9.8}/tests/test_format.py +0 -0
  145. {pyflyby-1.9.7 → pyflyby-1.9.8}/tests/test_idents.py +0 -0
  146. {pyflyby-1.9.7 → pyflyby-1.9.8}/tests/test_importclns.py +0 -0
  147. {pyflyby-1.9.7 → pyflyby-1.9.8}/tests/test_importdb.py +0 -0
  148. {pyflyby-1.9.7 → pyflyby-1.9.8}/tests/test_imports2s.py +0 -0
  149. {pyflyby-1.9.7 → pyflyby-1.9.8}/tests/test_importstmt.py +0 -0
  150. {pyflyby-1.9.7 → pyflyby-1.9.8}/tests/test_interactive.py +0 -0
  151. {pyflyby-1.9.7 → pyflyby-1.9.8}/tests/test_jupyterlab_pyflyby.py +0 -0
  152. {pyflyby-1.9.7 → pyflyby-1.9.8}/tests/test_livepatch.py +0 -0
  153. {pyflyby-1.9.7 → pyflyby-1.9.8}/tests/test_py.py +0 -0
  154. {pyflyby-1.9.7 → pyflyby-1.9.8}/tests/test_saveframe.py +0 -0
  155. {pyflyby-1.9.7 → pyflyby-1.9.8}/tests/test_util.py +0 -0
  156. {pyflyby-1.9.7 → pyflyby-1.9.8}/tests/tests_sorts.py +0 -0
  157. {pyflyby-1.9.7 → pyflyby-1.9.8}/tests/xrefs.py +0 -0
  158. {pyflyby-1.9.7 → pyflyby-1.9.8}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pyflyby
3
- Version: 1.9.7
3
+ Version: 1.9.8
4
4
  Summary: pyflyby - Python development productivity tools, in particular automatic import management
5
5
  Home-page: https://pypi.org/project/pyflyby/
6
6
  Author: Karl Chen
@@ -16,7 +16,7 @@ Classifier: Topic :: Software Development :: Interpreters
16
16
  Classifier: Intended Audience :: Developers
17
17
  Classifier: License :: OSI Approved :: MIT License
18
18
  Classifier: Programming Language :: Python
19
- Requires-Python: >3.8, <4
19
+ Requires-Python: >3.9, <4
20
20
  License-File: LICENSE.txt
21
21
 
22
22
  #########
@@ -113,7 +113,7 @@ configuration file:
113
113
 
114
114
  .. code:: python
115
115
 
116
-
116
+
117
117
  from pyflyby import add_import
118
118
 
119
119
  add_import("foo", "foo = 1")
@@ -484,29 +484,29 @@ Emacs support
484
484
  saveframe: A utility for debugging / reproducing an issue
485
485
  =========================================================
486
486
 
487
- PyFlyBy provides a utility named **saveframe** which can be used to save
487
+ PyFlyBy provides a utility named **saveframe** which can be used to save
488
488
  information for debugging / reproducing an issue.
489
489
 
490
- **Usage**: If you have a piece of code or a script that is failing due an issue
491
- originating from upstream code, and you cannot share your private code as a reproducer,
492
- use this utility to save relevant information to a file. Share the generated file with
490
+ **Usage**: If you have a piece of code or a script that is failing due an issue
491
+ originating from upstream code, and you cannot share your private code as a reproducer,
492
+ use this utility to save relevant information to a file. Share the generated file with
493
493
  the upstream team, enabling them to reproduce and diagnose the issue independently.
494
494
 
495
- **Information saved in the file**: This utility captures and saves *error stack frames*
496
- to a file. It includes the values of local variables from each stack frame, as well
495
+ **Information saved in the file**: This utility captures and saves *error stack frames*
496
+ to a file. It includes the values of local variables from each stack frame, as well
497
497
  as metadata about each frame and the exception raised by your code.
498
498
 
499
499
  This utility comes with 2 interfaces:
500
500
 
501
501
  1. **A function**: For interactive usages such as IPython, Jupyter Notebook, or a
502
- debugger (pdb/ipdb), use **pyflyby.saveframe** function. To know how to use this
502
+ debugger (pdb/ipdb), use **pyflyby.saveframe** function. To know how to use this
503
503
  function, checkout it's documentation:
504
504
 
505
505
  .. code::
506
506
 
507
507
  In [1]: saveframe?
508
508
 
509
- 2. **A script**: For cli usages (like a failing script), use **pyflyby/bin/saveframe**
509
+ 2. **A script**: For cli usages (like a failing script), use **pyflyby/bin/saveframe**
510
510
  script. To know how to use this script, checkout its documentation:
511
511
 
512
512
  .. code::
@@ -92,7 +92,7 @@ configuration file:
92
92
 
93
93
  .. code:: python
94
94
 
95
-
95
+
96
96
  from pyflyby import add_import
97
97
 
98
98
  add_import("foo", "foo = 1")
@@ -463,29 +463,29 @@ Emacs support
463
463
  saveframe: A utility for debugging / reproducing an issue
464
464
  =========================================================
465
465
 
466
- PyFlyBy provides a utility named **saveframe** which can be used to save
466
+ PyFlyBy provides a utility named **saveframe** which can be used to save
467
467
  information for debugging / reproducing an issue.
468
468
 
469
- **Usage**: If you have a piece of code or a script that is failing due an issue
470
- originating from upstream code, and you cannot share your private code as a reproducer,
471
- use this utility to save relevant information to a file. Share the generated file with
469
+ **Usage**: If you have a piece of code or a script that is failing due an issue
470
+ originating from upstream code, and you cannot share your private code as a reproducer,
471
+ use this utility to save relevant information to a file. Share the generated file with
472
472
  the upstream team, enabling them to reproduce and diagnose the issue independently.
473
473
 
474
- **Information saved in the file**: This utility captures and saves *error stack frames*
475
- to a file. It includes the values of local variables from each stack frame, as well
474
+ **Information saved in the file**: This utility captures and saves *error stack frames*
475
+ to a file. It includes the values of local variables from each stack frame, as well
476
476
  as metadata about each frame and the exception raised by your code.
477
477
 
478
478
  This utility comes with 2 interfaces:
479
479
 
480
480
  1. **A function**: For interactive usages such as IPython, Jupyter Notebook, or a
481
- debugger (pdb/ipdb), use **pyflyby.saveframe** function. To know how to use this
481
+ debugger (pdb/ipdb), use **pyflyby.saveframe** function. To know how to use this
482
482
  function, checkout it's documentation:
483
483
 
484
484
  .. code::
485
485
 
486
486
  In [1]: saveframe?
487
487
 
488
- 2. **A script**: For cli usages (like a failing script), use **pyflyby/bin/saveframe**
488
+ 2. **A script**: For cli usages (like a failing script), use **pyflyby/bin/saveframe**
489
489
  script. To know how to use this script, checkout its documentation:
490
490
 
491
491
  .. code::
@@ -1,5 +1,5 @@
1
1
  # pyflyby/_autoimp.py.
2
- # Copyright (C) 2011, 2012, 2013, 2014, 2015, 2018, 2019 Karl Chen.
2
+ # Copyright (C) 2011, 2012, 2013, 2014, 2015, 2018, 2019, 2024 Karl Chen.
3
3
  # License: MIT http://opensource.org/licenses/MIT
4
4
 
5
5
 
@@ -24,7 +24,7 @@ from pyflyby._parse import (PythonBlock, _is_ast_str,
24
24
  from six import reraise
25
25
  import sys
26
26
  import types
27
- from typing import Any, Set
27
+ from typing import Any, Set, Optional, List, Tuple
28
28
 
29
29
  if sys.version_info >= (3, 12):
30
30
  ATTRIBUTE_NAME = "value"
@@ -341,19 +341,26 @@ def symbol_needs_import(fullname, namespaces):
341
341
  return True
342
342
 
343
343
 
344
- class _UseChecker(object):
344
+ class _UseChecker:
345
345
  """
346
346
  An object that can check whether it was used.
347
347
  """
348
- used = False
349
348
 
350
- def __init__(self, name, source, lineno):
349
+ used: bool = False
350
+ name: str
351
+ source: str
352
+ lineno: int
353
+
354
+ def __init__(self, name: str, source: str, lineno: int):
351
355
  self.name = name
352
356
  self.source = source # generally an Import
353
357
  self.lineno = lineno
354
358
 
359
+ def __repr__(self):
360
+ return f"<{type(self).__name__}: name:{self.name} source:{self.source!r} lineno:{self.lineno} used:{self.used}>"
361
+
355
362
 
356
- class _MissingImportFinder(object):
363
+ class _MissingImportFinder:
357
364
  """
358
365
  A helper class to be used only by `_find_missing_imports_in_ast`.
359
366
 
@@ -371,8 +378,14 @@ class _MissingImportFinder(object):
371
378
 
372
379
  """
373
380
 
374
- def __init__(self, scopestack, find_unused_imports=False,
375
- parse_docstrings=False):
381
+ scopestack: ScopeStack
382
+ _lineno: Optional[int]
383
+ missing_imports: List[Tuple[Optional[int], DottedIdentifier]]
384
+ parse_docstrings: bool
385
+ unused_imports: Optional[List[Tuple[int, str]]]
386
+ _deferred_load_checks: list[tuple[str, ScopeStack, Optional[int]]]
387
+
388
+ def __init__(self, scopestack, *, find_unused_imports:bool, parse_docstrings:bool):
376
389
  """
377
390
  Construct the AST visitor.
378
391
 
@@ -385,19 +398,26 @@ class _MissingImportFinder(object):
385
398
  # includes the globals dictionary. ScopeStack() will make sure this
386
399
  # includes builtins.
387
400
  scopestack = ScopeStack(scopestack)
401
+
388
402
  # Add an empty namespace to the stack. This facilitates adding stuff
389
403
  # to scopestack[-1] without ever modifying user globals.
390
404
  scopestack = scopestack.with_new_scope()
405
+
391
406
  self.scopestack = scopestack
407
+
392
408
  # Create data structure to hold the result.
393
409
  # missing_imports is a list of (lineno, DottedIdentifier) tuples.
394
410
  self.missing_imports = []
411
+
395
412
  # unused_imports is a list of (lineno, Import) tuples, if enabled.
396
413
  self.unused_imports = [] if find_unused_imports else None
414
+
397
415
  self.parse_docstrings = parse_docstrings
416
+
398
417
  # Function bodies that we need to check after defining names in this
399
418
  # function scope.
400
419
  self._deferred_load_checks = []
420
+
401
421
  # Whether we're currently in a FunctionDef.
402
422
  self._in_FunctionDef = False
403
423
  # Current lineno.
@@ -419,7 +439,8 @@ class _MissingImportFinder(object):
419
439
  finally:
420
440
  self.scopestack = oldscopestack
421
441
 
422
- def scan_for_import_issues(self, codeblock):
442
+ def scan_for_import_issues(self, codeblock: PythonBlock):
443
+ assert isinstance(codeblock, PythonBlock)
423
444
  # See global `scan_for_import_issues`
424
445
  if not isinstance(codeblock, PythonBlock):
425
446
  codeblock = PythonBlock(codeblock)
@@ -588,7 +609,7 @@ class _MissingImportFinder(object):
588
609
  return
589
610
  if (len(node.targets) == 1 and isinstance(node.targets[0], ast.Name)
590
611
  and node.targets[0].id == '__all__'):
591
- if not isinstance(node.value, ast.List):
612
+ if not isinstance(node.value, (ast.List, ast.Tuple)):
592
613
  logger.warning("Don't know how to handle __all__ as (%s)" % node.value)
593
614
  return
594
615
  if not all(_is_ast_str(e) for e in node.value.elts):
@@ -909,9 +930,8 @@ class _MissingImportFinder(object):
909
930
 
910
931
  def _visit_StoreImport(self, node, modulename):
911
932
  name = node.asname or node.name
912
- logger.debug("_visit_StoreImport(asname=%r,name=%r)",
913
- node.asname, node.name)
914
- is_star = node.name == '*'
933
+ logger.debug("_visit_StoreImport(asname=%r, name=%r)", node.asname, node.name)
934
+ is_star = node.name == "*"
915
935
  if is_star:
916
936
  logger.debug("Got star import: line %s: 'from %s import *'",
917
937
  self._lineno, modulename)
@@ -998,10 +1018,11 @@ class _MissingImportFinder(object):
998
1018
  # Don't call generic_visit(node) here. Reason: We already visit the
999
1019
  # parts above, if relevant.
1000
1020
 
1001
- def _visit_Load_defered_global(self, fullname):
1021
+ def _visit_Load_defered_global(self, fullname:str):
1002
1022
  """
1003
1023
  Some things will be resolved in global scope later.
1004
1024
  """
1025
+ assert isinstance(fullname, str), fullname
1005
1026
  logger.debug("_visit_Load_defered_global(%r)", fullname)
1006
1027
  if symbol_needs_import(fullname, self.scopestack):
1007
1028
  data = (fullname, self.scopestack, self._lineno)
@@ -1090,7 +1111,11 @@ class _MissingImportFinder(object):
1090
1111
  unused_imports.sort()
1091
1112
 
1092
1113
 
1093
- def scan_for_import_issues(codeblock, find_unused_imports=True, parse_docstrings=False):
1114
+ def scan_for_import_issues(
1115
+ codeblock: PythonBlock,
1116
+ find_unused_imports: bool = True,
1117
+ parse_docstrings: bool = False,
1118
+ ):
1094
1119
  """
1095
1120
  Find missing and unused imports, by lineno.
1096
1121
 
@@ -1117,7 +1142,7 @@ def scan_for_import_issues(codeblock, find_unused_imports=True, parse_docstrings
1117
1142
  ([], [(1, Import('import baz'))])
1118
1143
 
1119
1144
  """
1120
- logger.debug("scan_for_import_issues()")
1145
+ logger.debug("global scan_for_import_issues()")
1121
1146
  if not isinstance(codeblock, PythonBlock):
1122
1147
  codeblock = PythonBlock(codeblock)
1123
1148
  namespaces = ScopeStack([{}])
@@ -1148,7 +1173,10 @@ def _find_missing_imports_in_ast(node, namespaces):
1148
1173
  # Traverse the abstract syntax tree.
1149
1174
  if logger.debug_enabled:
1150
1175
  logger.debug("ast=%s", ast.dump(node))
1151
- return _MissingImportFinder(namespaces).find_missing_imports(node)
1176
+ return _MissingImportFinder(
1177
+ namespaces,
1178
+ find_unused_imports=False,
1179
+ parse_docstrings=False).find_missing_imports(node)
1152
1180
 
1153
1181
  # TODO: maybe we should replace _find_missing_imports_in_ast with
1154
1182
  # _find_missing_imports_in_code(compile(node)). The method of parsing opcodes
@@ -560,9 +560,11 @@ class ImportDB:
560
560
  filenames = [filenames]
561
561
  for f in filenames:
562
562
  assert isinstance(f, Filename)
563
- logger.debug("ImportDB: loading [%s], mandatory=[%s]",
564
- ', '.join(map(str, filenames)),
565
- ', '.join(map(str, _mandatory_filenames_deprecated)))
563
+ logger.debug(
564
+ "ImportDB: loading %r, mandatory=%r",
565
+ [str(f) for f in filenames],
566
+ [str(f) for f in _mandatory_filenames_deprecated],
567
+ )
566
568
  if SUPPORT_DEPRECATED_BEHAVIOR:
567
569
  # Before 2014-10, pyflyby read the following:
568
570
  # * known_imports from $PYFLYBY_PATH/known_imports/**/*.py or
@@ -96,7 +96,7 @@ If <module_name> is ``None``, then there is no "from" clause; instead just::
96
96
  """
97
97
 
98
98
  @total_ordering
99
- class Import(object):
99
+ class Import:
100
100
  """
101
101
  Representation of the desire to import a single name into the current
102
102
  namespace.
@@ -15,7 +15,7 @@ import re
15
15
  import subprocess
16
16
  import sys
17
17
 
18
- from typing import List, Any, Dict
18
+ from typing import List, Any, Dict, Union, Literal
19
19
 
20
20
 
21
21
  from pyflyby._autoimp import (LoadSymbolError, ScopeStack, auto_eval,
@@ -2269,7 +2269,9 @@ class AutoImporter:
2269
2269
 
2270
2270
  def _safe_call(self, function, *args, **kwargs):
2271
2271
  on_error = kwargs.pop("on_error", None)
2272
- raise_on_error = kwargs.pop("raise_on_error", "if_debug")
2272
+ raise_on_error: Union[bool, Literal["if_debug"]] = kwargs.pop(
2273
+ "raise_on_error", "if_debug"
2274
+ )
2273
2275
  if self._errored:
2274
2276
  # If we previously errored, then we should already have
2275
2277
  # unregistered the hook that led to here. However, in some corner
@@ -2295,7 +2297,7 @@ class AutoImporter:
2295
2297
  logger.error("Error trying to disable: %s: %s",
2296
2298
  type(e2).__name__, e2)
2297
2299
  # Raise or print traceback in debug mode.
2298
- if raise_on_error == True:
2300
+ if raise_on_error is True:
2299
2301
  raise
2300
2302
  elif raise_on_error == 'if_debug':
2301
2303
  if logger.debug_enabled:
@@ -2305,7 +2307,7 @@ class AutoImporter:
2305
2307
  import traceback
2306
2308
  traceback.print_exc()
2307
2309
  raise
2308
- elif raise_on_error == False:
2310
+ elif raise_on_error is False:
2309
2311
  if logger.debug_enabled:
2310
2312
  import traceback
2311
2313
  traceback.print_exc()
@@ -2328,8 +2330,13 @@ class AutoImporter:
2328
2330
  sorted([k for k,v in autoimported.items() if not v]))
2329
2331
  self._autoimported_this_cell = {}
2330
2332
 
2331
- def auto_import(self, arg, namespaces=None,
2332
- raise_on_error='if_debug', on_error=None):
2333
+ def auto_import(
2334
+ self,
2335
+ arg,
2336
+ namespaces=None,
2337
+ raise_on_error: Union[bool, Literal["if_debug"]] = "if_debug",
2338
+ on_error=None,
2339
+ ):
2333
2340
  if namespaces is None:
2334
2341
  namespaces = get_global_namespaces(self._ip)
2335
2342
 
@@ -20,7 +20,7 @@ import re
20
20
  import sys
21
21
  from textwrap import dedent
22
22
  import types
23
- from typing import Any, List, Optional, Tuple, Union, cast
23
+ from typing import Any, List, Optional, Tuple, Union, cast, Literal
24
24
  import warnings
25
25
 
26
26
 
@@ -353,7 +353,7 @@ def _annotate_ast_nodes(ast_node: ast.AST) -> AnnotatedAst:
353
353
 
354
354
 
355
355
  def _annotate_ast_startpos(
356
- ast_node: ast.AST, parent_ast_node, minpos, text, flags
356
+ ast_node: ast.AST, parent_ast_node, minpos: FilePos, text: FileText, flags
357
357
  ) -> bool:
358
358
  r"""
359
359
  Annotate ``ast_node``. Set ``ast_node.startpos`` to the starting position
@@ -410,8 +410,8 @@ def _annotate_ast_startpos(
410
410
  # Walk all nodes/fields of the AST. We implement this as a custom
411
411
  # depth-first search instead of using ast.walk() or ast.NodeVisitor
412
412
  # so that we can easily keep track of the preceding node's lineno.
413
- child_minpos = minpos
414
- is_first_child = True
413
+ child_minpos: FilePos = minpos
414
+ is_first_child: bool = True
415
415
  leftstr_node = None
416
416
  for child_node in _iter_child_nodes_in_order(aast_node):
417
417
  leftstr = _annotate_ast_startpos(
@@ -469,7 +469,16 @@ def _annotate_ast_startpos(
469
469
  # Not a multiline string literal. (I.e., it could be a non-string or
470
470
  # a single-line string.)
471
471
  # Easy.
472
- startpos = text.startpos + delta
472
+ if sys.version_info < (3, 12):
473
+ """There is an issue for f-strings at the begining of a file in 3.11 and
474
+ before
475
+
476
+ https://github.com/deshaw/pyflyby/issues/361,
477
+ here we ensure a child node min pos, can't be before it's parent.
478
+ """
479
+ startpos = max(text.startpos + delta, minpos)
480
+ else:
481
+ startpos = text.startpos + delta
473
482
 
474
483
  # Special case for 'with' statements. Consider the code:
475
484
  # with X: pass
@@ -668,7 +677,7 @@ def _ast_node_is_in_docstring_position(ast_node):
668
677
  return False
669
678
 
670
679
 
671
- def infer_compile_mode(arg):
680
+ def infer_compile_mode(arg:ast.AST) -> Literal['exec','eval','single']:
672
681
  """
673
682
  Infer the mode needed to compile ``arg``.
674
683
 
@@ -679,19 +688,18 @@ def infer_compile_mode(arg):
679
688
  """
680
689
  # Infer mode from ast object.
681
690
  if isinstance(arg, ast.Module):
682
- mode = "exec"
691
+ return "exec"
683
692
  elif isinstance(arg, ast.Expression):
684
- mode = "eval"
693
+ return "eval"
685
694
  elif isinstance(arg, ast.Interactive):
686
- mode = "single"
695
+ return "single"
687
696
  else:
688
697
  raise TypeError(
689
698
  "Expected Module/Expression/Interactive ast node; got %s"
690
699
  % (type(arg).__name__))
691
- return mode
692
700
 
693
701
 
694
- class _DummyAst_Node(object):
702
+ class _DummyAst_Node:
695
703
  pass
696
704
 
697
705
 
@@ -945,8 +953,9 @@ class PythonBlock:
945
953
  return cls.from_text(Filename(filename))
946
954
 
947
955
  @classmethod
948
- def from_text(cls, text, filename=None, startpos=None, flags=None,
949
- auto_flags=False):
956
+ def from_text(
957
+ cls, text, filename=None, startpos=None, flags=None, auto_flags: bool = False
958
+ ):
950
959
  """
951
960
  :type text:
952
961
  `FileText` or convertible
@@ -1144,7 +1153,7 @@ class PythonBlock:
1144
1153
  else:
1145
1154
  return None
1146
1155
 
1147
- def parse(self, mode=None) -> Union[ast.Expression, ast.Module]:
1156
+ def parse(self, mode: Optional[str] = None) -> Union[ast.Expression, ast.Module]:
1148
1157
  """
1149
1158
  Parse the source text into an AST.
1150
1159
 
@@ -1165,7 +1174,7 @@ class PythonBlock:
1165
1174
  return self.expression_ast_node
1166
1175
  else:
1167
1176
  raise SyntaxError
1168
- elif mode == None:
1177
+ elif mode is None:
1169
1178
  if self.expression_ast_node:
1170
1179
  return self.expression_ast_node
1171
1180
  else:
@@ -1176,7 +1185,7 @@ class PythonBlock:
1176
1185
  else:
1177
1186
  raise ValueError("parse(): invalid mode=%r" % (mode,))
1178
1187
 
1179
- def compile(self, mode=None):
1188
+ def compile(self, mode: Optional[str] = None):
1180
1189
  """
1181
1190
  Parse into AST and compile AST into code.
1182
1191
 
@@ -1184,9 +1193,9 @@ class PythonBlock:
1184
1193
  ``CodeType``
1185
1194
  """
1186
1195
  ast_node = self.parse(mode=mode)
1187
- mode = infer_compile_mode(ast_node)
1196
+ c_mode = infer_compile_mode(ast_node)
1188
1197
  filename = str(self.filename or "<unknown>")
1189
- return compile(ast_node, filename, mode)
1198
+ return compile(ast_node, filename, c_mode)
1190
1199
 
1191
1200
  @cached_property
1192
1201
  def statements(self) -> Tuple[PythonStatement, ...]:
@@ -286,19 +286,6 @@ from typing import Any
286
286
  from pyflyby._util import cmp
287
287
  from shlex import quote as shquote
288
288
 
289
- usage = """
290
- py --- command-line python multitool with automatic importing
291
-
292
- $ py [--file] filename.py arg1 arg2 Execute file
293
- $ py [--apply] function arg1 arg2 Call function
294
- $ py [--eval] 'function(arg1, arg2)' Evaluate code
295
- $ py [--module] modname arg1 arg2 Run a module
296
-
297
- $ py --debug file/code... args... Debug code
298
- $ py --debug PID Attach debugger to PID
299
-
300
- $ py IPython shell
301
- """.strip()
302
289
 
303
290
  # TODO: add --tidy-imports, etc
304
291
 
@@ -377,6 +364,19 @@ from pyflyby._modules import ModuleHandle
377
364
  from pyflyby._parse import PythonBlock
378
365
  from pyflyby._util import indent, prefixes
379
366
 
367
+ usage = """
368
+ py --- command-line python multitool with automatic importing
369
+
370
+ $ py [--file] filename.py arg1 arg2 Execute file
371
+ $ py [--apply] function arg1 arg2 Call function
372
+ $ py [--eval] 'function(arg1, arg2)' Evaluate code
373
+ $ py [--module] modname arg1 arg2 Run a module
374
+
375
+ $ py --debug file/code... args... Debug code
376
+ $ py --debug PID Attach debugger to PID
377
+
378
+ $ py IPython shell
379
+ """.strip()
380
380
 
381
381
  # Default compiler flags (feature flags) used for all user code. We include
382
382
  # "print_function" here, but we also use auto_flags=True, which means
@@ -409,7 +409,7 @@ def _get_argspec(arg:Any) -> inspect.FullArgSpec:
409
409
  "_get_argspec: unexpected %s" % (type(arg).__name__,))
410
410
 
411
411
 
412
- def _requires_parens_as_function(function_name:str):
412
+ def _requires_parens_as_function(function_name:str) -> bool:
413
413
  """
414
414
  Returns whether the given string of a callable would require parentheses
415
415
  around it to call it.
@@ -552,7 +552,7 @@ class _ParseInterruptedWantSource(Exception):
552
552
  pass
553
553
 
554
554
 
555
- class UserExpr(object):
555
+ class UserExpr:
556
556
  """
557
557
  An expression from user input, and its evaluated value.
558
558
 
@@ -647,7 +647,7 @@ class UserExpr(object):
647
647
  else:
648
648
  raise ValueError("UserExpr(): bad arg_mode=%r" % (arg_mode,))
649
649
 
650
- def _infer_and_evaluate(self):
650
+ def _infer_and_evaluate(self) -> None:
651
651
  if self._original_arg_mode == "raw_value":
652
652
  pass
653
653
  elif self._original_arg_mode == "eval":
@@ -891,7 +891,7 @@ class NotAFunctionError(Exception):
891
891
  pass
892
892
 
893
893
 
894
- def _get_help(expr, verbosity=1):
894
+ def _get_help(expr:UserExpr, verbosity:int=1) -> str:
895
895
  """
896
896
  Construct a help string.
897
897
 
@@ -1053,7 +1053,7 @@ def auto_apply(function, commandline_args, namespace, arg_mode=None,
1053
1053
 
1054
1054
 
1055
1055
  @total_ordering
1056
- class LoggedList(object):
1056
+ class LoggedList:
1057
1057
  """
1058
1058
  List that logs which members have not yet been accessed (nor removed).
1059
1059
  """
@@ -4,7 +4,7 @@
4
4
 
5
5
 
6
6
 
7
- from contextlib import contextmanager
7
+ from contextlib import contextmanager, ExitStack
8
8
  import inspect
9
9
  import os
10
10
  import sys
@@ -451,7 +451,6 @@ def cmp(a, b):
451
451
 
452
452
 
453
453
  # Create a context manager with an arbitrary number of contexts.
454
- from contextlib import ExitStack
455
454
  @contextmanager
456
455
  def nested(*mgrs):
457
456
  with ExitStack() as stack:
@@ -4,4 +4,4 @@
4
4
  # http://creativecommons.org/publicdomain/zero/1.0/
5
5
 
6
6
 
7
- __version__ = "1.9.7"
7
+ __version__ = "1.9.8"