evolver-tools 24.0.0__tar.gz → 27.0.0__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.
Files changed (278) hide show
  1. {evolver_tools-24.0.0/src/evolver_tools.egg-info → evolver_tools-27.0.0}/PKG-INFO +2 -2
  2. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/pyproject.toml +2 -2
  3. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/__init__.py +1 -1
  4. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/cli.py +1 -1
  5. evolver_tools-27.0.0/src/evolver_tools/vendor/banner.py +296 -0
  6. evolver_tools-27.0.0/src/evolver_tools/vendor/code_review.py +323 -0
  7. evolver_tools-27.0.0/src/evolver_tools/vendor/csv_dedup.py +265 -0
  8. evolver_tools-27.0.0/src/evolver_tools/vendor/json_path.py +261 -0
  9. evolver_tools-27.0.0/src/evolver_tools/vendor/scan_open_ports.py +1182 -0
  10. {evolver_tools-24.0.0 → evolver_tools-27.0.0/src/evolver_tools.egg-info}/PKG-INFO +2 -2
  11. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools.egg-info/SOURCES.txt +4 -0
  12. evolver_tools-24.0.0/src/evolver_tools/vendor/banner.py +0 -77
  13. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/LICENSE +0 -0
  14. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/README.md +0 -0
  15. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/setup.cfg +0 -0
  16. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/__main__.py +0 -0
  17. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/autoreg.py +0 -0
  18. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/__init__.py +0 -0
  19. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/agent_b_tool.py +0 -0
  20. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/ansi_strip.py +0 -0
  21. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/api_tester.py +0 -0
  22. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/ascii_gen.py +0 -0
  23. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/audit_log.py +0 -0
  24. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/b64/__init__.py +0 -0
  25. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/b64/b64.py +0 -0
  26. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/backup.py +0 -0
  27. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/banner/__init__.py +0 -0
  28. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/banner/banner.py +0 -0
  29. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/base32.py +0 -0
  30. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/base58.py +0 -0
  31. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/bookmark.py +0 -0
  32. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/cal_tool/__init__.py +0 -0
  33. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/cal_tool/cli.py +0 -0
  34. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/calendar_cli.py +0 -0
  35. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/cert_check.py +0 -0
  36. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/cert_info.py +0 -0
  37. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/changelog_gen/__init__.py +0 -0
  38. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/changelog_gen/changelog_gen.py +0 -0
  39. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/changelog_gen.py +0 -0
  40. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/chart_cli/__init__.py +0 -0
  41. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/chart_cli/__main__.py +0 -0
  42. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/checksum_dir.py +0 -0
  43. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/clipboard/__init__.py +0 -0
  44. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/clipboard/clipboard.py +0 -0
  45. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/code_auditor.py +0 -0
  46. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/code_stats.py +0 -0
  47. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/colorize.py +0 -0
  48. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/colors/__init__.py +0 -0
  49. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/colors/__main__.py +0 -0
  50. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/config_validator.py +0 -0
  51. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/config_vault.py +0 -0
  52. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/cowsay.py +0 -0
  53. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/crc_check.py +0 -0
  54. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/cron/__init__.py +0 -0
  55. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/cron/__main__.py +0 -0
  56. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/cron_pretty.py +0 -0
  57. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/crontab_helper.py +0 -0
  58. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/crypto_box.py +0 -0
  59. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/crypto_price.py +0 -0
  60. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/csv2json.py +0 -0
  61. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/csv_merge.py +0 -0
  62. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/csv_stats/__init__.py +0 -0
  63. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/csv_stats/__main__.py +0 -0
  64. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/csv_stats/analyzer.py +0 -0
  65. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/csv_stats/cli.py +0 -0
  66. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/csv_validate.py +0 -0
  67. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/csv_view.py +0 -0
  68. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/date_diff.py +0 -0
  69. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/db_mate.py +0 -0
  70. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/db_schema.py +0 -0
  71. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/dep_graph.py +0 -0
  72. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/dev_dashboard.py +0 -0
  73. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/dice_roll.py +0 -0
  74. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/diff_csv.py +0 -0
  75. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/diff_files.py +0 -0
  76. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/diff_tool/__init__.py +0 -0
  77. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/diff_tool/__main__.py +0 -0
  78. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/dirsize/__init__.py +0 -0
  79. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/disk_cleanup.py +0 -0
  80. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/disk_usage/__init__.py +0 -0
  81. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/disk_usage/disk_usage.py +0 -0
  82. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/dns_lookup.py +0 -0
  83. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/docker_helper.py +0 -0
  84. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/dt_convert.py +0 -0
  85. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/env_diff.py +0 -0
  86. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/env_manager.py +0 -0
  87. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/env_template.py +0 -0
  88. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/envcheck/__init__.py +0 -0
  89. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/epoch.py +0 -0
  90. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/excel2csv.py +0 -0
  91. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/factor.py +0 -0
  92. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/ff/__init__.py +0 -0
  93. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/ff/__main__.py +0 -0
  94. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/figlet_cli.py +0 -0
  95. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/figlet_tool.py +0 -0
  96. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/file_encrypt.py +0 -0
  97. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/file_find.py +0 -0
  98. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/file_joiner.py +0 -0
  99. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/file_splitter.py +0 -0
  100. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/file_watch.py +0 -0
  101. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/find_dups/__init__.py +0 -0
  102. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/find_dups/cli.py +0 -0
  103. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/firewall_rule.py +0 -0
  104. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/fmt/__init__.py +0 -0
  105. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/fmt/fmt.py +0 -0
  106. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/fold.py +0 -0
  107. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/geo_ip.py +0 -0
  108. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/git_branch_cleaner.py +0 -0
  109. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/git_log_pretty.py +0 -0
  110. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/git_stats.py +0 -0
  111. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/gzip_cli.py +0 -0
  112. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/hash_check.py +0 -0
  113. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/hash_file.py +0 -0
  114. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/hashsum/__init__.py +0 -0
  115. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/hashsum/__main__.py +0 -0
  116. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/hex_tool.py +0 -0
  117. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/hexdump.py +0 -0
  118. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/html2markdown.py +0 -0
  119. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/html2md.py +0 -0
  120. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/http_headers.py +0 -0
  121. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/http_live/__init__.py +0 -0
  122. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/http_live/__main__.py +0 -0
  123. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/http_server.py +0 -0
  124. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/image_meta.py +0 -0
  125. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/ini2json.py +0 -0
  126. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/ini_parser/__init__.py +0 -0
  127. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/ini_parser/ini_parser.py +0 -0
  128. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/ip_info.py +0 -0
  129. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/ip_location.py +0 -0
  130. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/ipcalc/__init__.py +0 -0
  131. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/ipcalc/__main__.py +0 -0
  132. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/ipinfo/__init__.py +0 -0
  133. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/ipinfo/__main__.py +0 -0
  134. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/join.py +0 -0
  135. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/joke.py +0 -0
  136. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/jq_lite/__init__.py +0 -0
  137. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/jq_lite/__main__.py +0 -0
  138. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/json2csv/__init__.py +0 -0
  139. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/json2csv/__main__.py +0 -0
  140. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/json2ini.py +0 -0
  141. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/json_diff.py +0 -0
  142. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/json_flatten.py +0 -0
  143. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/json_merge.py +0 -0
  144. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/json_pretty/__init__.py +0 -0
  145. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/json_pretty/json_pretty.py +0 -0
  146. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/json_schema_validate.py +0 -0
  147. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/jsonql/__init__.py +0 -0
  148. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/jsonql/__main__.py +0 -0
  149. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/jwt_decode.py +0 -0
  150. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/key_value_store.py +0 -0
  151. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/license.py +0 -0
  152. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/license_cli/__init__.py +0 -0
  153. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/license_cli/__main__.py +0 -0
  154. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/license_cli/cli.py +0 -0
  155. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/log_analyzer.py +0 -0
  156. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/log_hawk.py +0 -0
  157. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/log_tail.py +0 -0
  158. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/macrogen.py +0 -0
  159. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/markdown_check/__init__.py +0 -0
  160. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/markdown_lint.py +0 -0
  161. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/markdown_preview.py +0 -0
  162. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/markdown_toc.py +0 -0
  163. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/math_eval.py +0 -0
  164. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/media_studio.py +0 -0
  165. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/morse.py +0 -0
  166. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/nb/__init__.py +0 -0
  167. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/nb/__main__.py +0 -0
  168. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/net_analyzer.py +0 -0
  169. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/net_speed.py +0 -0
  170. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/network_scan.py +0 -0
  171. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/nl.py +0 -0
  172. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/note_taker.py +0 -0
  173. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/otp_gen.py +0 -0
  174. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/passgen/__init__.py +0 -0
  175. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/password_strength.py +0 -0
  176. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/pdf_info.py +0 -0
  177. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/pdf_text.py +0 -0
  178. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/pipe_viewer.py +0 -0
  179. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/pomodoro.py +0 -0
  180. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/port_scan.py +0 -0
  181. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/portcheck/__init__.py +0 -0
  182. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/portcheck/__main__.py +0 -0
  183. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/pr_tool/__init__.py +0 -0
  184. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/pr_tool/pr_tool.py +0 -0
  185. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/process_kill.py +0 -0
  186. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/progress_bar.py +0 -0
  187. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/project_doctor/__init__.py +0 -0
  188. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/project_doctor/__main__.py +0 -0
  189. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/qc_calc.py +0 -0
  190. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/qc_report.py +0 -0
  191. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/qc_sample.py +0 -0
  192. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/qr_cli.py +0 -0
  193. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/qrcode.py +0 -0
  194. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/quote.py +0 -0
  195. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/quote_tool/__init__.py +0 -0
  196. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/quote_tool/quote.py +0 -0
  197. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/rainbow.py +0 -0
  198. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/random.py +0 -0
  199. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/reminder.py +0 -0
  200. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/ren/__init__.py +0 -0
  201. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/ren/__main__.py +0 -0
  202. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/replace_text.py +0 -0
  203. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/restore.py +0 -0
  204. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/rot13.py +0 -0
  205. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/route_trace.py +0 -0
  206. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/scan_ports.py +0 -0
  207. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/screen_recorder.py +0 -0
  208. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/screenshot_cli.py +0 -0
  209. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/search_files.py +0 -0
  210. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/search_history.py +0 -0
  211. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/secret_scanner.py +0 -0
  212. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/seq.py +0 -0
  213. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/service_check.py +0 -0
  214. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/shuffle.py +0 -0
  215. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/siege_lite/__init__.py +0 -0
  216. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/siege_lite/__main__.py +0 -0
  217. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/smellfinder/__init__.py +0 -0
  218. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/smellfinder/__main__.py +0 -0
  219. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/sort/__init__.py +0 -0
  220. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/sort/sort.py +0 -0
  221. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/spinner.py +0 -0
  222. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/split.py +0 -0
  223. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/split_tool/__init__.py +0 -0
  224. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/split_tool/split.py +0 -0
  225. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/sql2csv.py +0 -0
  226. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/sqlite_cli/__init__.py +0 -0
  227. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/sqlite_cli/__main__.py +0 -0
  228. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/ssh_key_gen.py +0 -0
  229. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/ssl_check.py +0 -0
  230. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/stopwatch.py +0 -0
  231. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/subnet.py +0 -0
  232. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/sysmon/__init__.py +0 -0
  233. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/sysmon/__main__.py +0 -0
  234. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/sysmon_pro.py +0 -0
  235. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/system_info.py +0 -0
  236. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/temp_cleaner.py +0 -0
  237. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/template.py +0 -0
  238. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/text_stats.py +0 -0
  239. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/timeout.py +0 -0
  240. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/timer/__init__.py +0 -0
  241. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/timer_pro/__init__.py +0 -0
  242. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/timer_pro/timer_pro.py +0 -0
  243. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/timer_pro.py +0 -0
  244. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/todo_cli.py +0 -0
  245. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/toml2json.py +0 -0
  246. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/tr.py +0 -0
  247. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/tree.py +0 -0
  248. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/treedir/__init__.py +0 -0
  249. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/treedir/__main__.py +0 -0
  250. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/tsv2csv.py +0 -0
  251. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/uniq_tool/__init__.py +0 -0
  252. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/uniq_tool/uniq.py +0 -0
  253. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/unit_convert.py +0 -0
  254. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/uri_encode.py +0 -0
  255. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/url_parser.py +0 -0
  256. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/urlparse_tool/__init__.py +0 -0
  257. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/urlparse_tool/cli.py +0 -0
  258. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/uuid_gen.py +0 -0
  259. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/uuid_tool/__init__.py +0 -0
  260. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/uuid_tool/__main__.py +0 -0
  261. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/watch.py +0 -0
  262. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/weather_cli.py +0 -0
  263. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/web_download.py +0 -0
  264. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/web_summary/__init__.py +0 -0
  265. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/web_summary/__main__.py +0 -0
  266. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/whois_lookup.py +0 -0
  267. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/wordcount/__init__.py +0 -0
  268. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/wordcount/__main__.py +0 -0
  269. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/world_clock.py +0 -0
  270. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/xml2json.py +0 -0
  271. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/yaml2json/__init__.py +0 -0
  272. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/yaml2json/yaml2json.py +0 -0
  273. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/yaml2toml.py +0 -0
  274. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/yaml_validate.py +0 -0
  275. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools/vendor/yes.py +0 -0
  276. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools.egg-info/dependency_links.txt +0 -0
  277. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools.egg-info/entry_points.txt +0 -0
  278. {evolver_tools-24.0.0 → evolver_tools-27.0.0}/src/evolver_tools.egg-info/top_level.txt +0 -0
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: evolver-tools
3
- Version: 24.0.0
4
- Summary: 201 CLI tools + 9 flagship projects — one pip install
3
+ Version: 27.0.0
4
+ Summary: 218 CLI tools + 9 flagship projects — one pip install
5
5
  Author: EVOLVER
6
6
  License-Expression: MIT
7
7
  Project-URL: Homepage, https://evolver-dev.github.io/evolver-tools
@@ -4,8 +4,8 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "evolver-tools"
7
- version = "24.0.0"
8
- description = "201 CLI tools + 9 flagship projects — one pip install"
7
+ version = "27.0.0"
8
+ description = "218 CLI tools + 9 flagship projects — one pip install"
9
9
  readme = "README.md"
10
10
  license = "MIT"
11
11
  requires-python = ">=3.8"
@@ -1,4 +1,4 @@
1
1
  """evolver-tools: 23 CLI tools in one package."""
2
- __version__ = "1.0.0"
2
+ __version__ = "27.0.0"
3
3
 
4
4
  from .autoreg import auto_discover
@@ -14,7 +14,7 @@ from evolver_tools.autoreg import auto_discover
14
14
  def list_tools():
15
15
  """Display all available tools."""
16
16
  tools = auto_discover()
17
- print(f'\x1b[1;36m===== EVOLVER Tools v23.0.0 =====\x1b[0m')
17
+ print(f'\x1b[1;36m===== EVOLVER Tools v27.0.0 =====\x1b[0m')
18
18
  print()
19
19
  for name, info in sorted(tools.items()):
20
20
  print(f' \033[1;33m{name:<18}\033[0m {info["desc"]}')
@@ -0,0 +1,296 @@
1
+ #!/usr/bin/env python3
2
+ """banner — ASCII art banner generator.
3
+ Usage: banner [--font=block|simple|wide|big] [--width=N] <text>
4
+ echo text | banner [--font=...] [--width=N]
5
+
6
+ Four built-in fonts:
7
+ block – hash-filled block letters (#)
8
+ simple – star-and-line outline letters (*)
9
+ wide – double-spaced block letters (wider)
10
+ big – uppercase geometric letters
11
+
12
+ Zero-dependency (stdlib only).
13
+ """
14
+ import sys
15
+
16
+ # ── Font data ──────────────────────────────────────────────────────────
17
+ # Each font: {'A': ['row0','row1',...], ...} (5 rows per char)
18
+ # Unknown chars render as blank columns of matching char width.
19
+
20
+ _BLOCK = {
21
+ 'A': [' ### ', ' # # ', ' ##### ', ' # # ', ' # # '],
22
+ 'B': [' #### ', ' # # ', ' #### ', ' # # ', ' #### '],
23
+ 'C': [' #### ', ' # ', ' # ', ' # ', ' #### '],
24
+ 'D': [' #### ', ' # # ', ' # # ', ' # # ', ' #### '],
25
+ 'E': [' ##### ', ' # ', ' #### ', ' # ', ' ##### '],
26
+ 'F': [' ##### ', ' # ', ' #### ', ' # ', ' # '],
27
+ 'G': [' #### ', ' # ', ' # ## ', ' # # ', ' ### '],
28
+ 'H': [' # # ', ' # # ', ' ##### ', ' # # ', ' # # '],
29
+ 'I': [' ##### ', ' # ', ' # ', ' # ', ' ##### '],
30
+ 'J': [' #####', ' # ', ' # ', ' # # ', ' ## '],
31
+ 'K': [' # # ', ' # # ', ' ### ', ' # # ', ' # # '],
32
+ 'L': [' # ', ' # ', ' # ', ' # ', ' ##### '],
33
+ 'M': [' ## ## ', ' #### #', ' # # # ', ' # # ', ' # # '],
34
+ 'N': [' ## # ', ' ### # ', ' # ### ', ' # ## ', ' # # '],
35
+ 'O': [' ### ', ' # # ', ' # # ', ' # # ', ' ### '],
36
+ 'P': [' #### ', ' # # ', ' #### ', ' # ', ' # '],
37
+ 'Q': [' ### ', ' # # ', ' # # ', ' # # ', ' ## # '],
38
+ 'R': [' #### ', ' # # ', ' #### ', ' # # ', ' # # '],
39
+ 'S': [' #### ', ' # ', ' ### ', ' # ', ' #### '],
40
+ 'T': [' ##### ', ' # ', ' # ', ' # ', ' # '],
41
+ 'U': [' # # ', ' # # ', ' # # ', ' # # ', ' ### '],
42
+ 'V': [' # # ', ' # # ', ' # # ', ' # # ', ' # '],
43
+ 'W': [' # # ', ' # # ', ' # # # ', ' #### #', ' ## ## '],
44
+ 'X': [' # # ', ' # # ', ' # ', ' # # ', ' # # '],
45
+ 'Y': [' # # ', ' # # ', ' # ', ' # ', ' # '],
46
+ 'Z': [' ##### ', ' # ', ' # ', ' # ', ' ##### '],
47
+ ' ': [' ', ' ', ' ', ' ', ' '],
48
+ '!': [' # ', ' # ', ' # ', ' ', ' # '],
49
+ '.': [' ', ' ', ' ', ' ', ' # '],
50
+ ',': [' ', ' ', ' ', ' # ', ' # '],
51
+ '?': [' ### ', ' # ', ' # ', ' ', ' # '],
52
+ '0': [' ### ', ' # ## ', ' # # # ', ' ## # ', ' ### '],
53
+ '1': [' # ', ' ## ', ' # ', ' # ', ' ##### '],
54
+ '2': [' ### ', ' # ', ' ### ', ' # ', ' ##### '],
55
+ '3': [' ### ', ' # ', ' ### ', ' # ', ' ### '],
56
+ '4': [' # # ', ' # # ', ' ##### ', ' # ', ' # '],
57
+ '5': [' ##### ', ' # ', ' #### ', ' # ', ' #### '],
58
+ '6': [' #### ', ' # ', ' #### ', ' # # ', ' ### '],
59
+ '7': [' ##### ', ' # ', ' # ', ' # ', ' # '],
60
+ '8': [' ### ', ' # # ', ' ### ', ' # # ', ' ### '],
61
+ '9': [' ### ', ' # # ', ' #### ', ' # ', ' #### '],
62
+ }
63
+
64
+ _SIMPLE = {
65
+ 'A': [' *** ', ' * * ', ' ***** ', ' * * ', ' * * '],
66
+ 'B': [' **** ', ' * * ', ' **** ', ' * * ', ' **** '],
67
+ 'C': [' **** ', ' * ', ' * ', ' * ', ' **** '],
68
+ 'D': [' **** ', ' * * ', ' * * ', ' * * ', ' **** '],
69
+ 'E': [' ***** ', ' * ', ' *** ', ' * ', ' ***** '],
70
+ 'F': [' ***** ', ' * ', ' *** ', ' * ', ' * '],
71
+ 'G': [' **** ', ' * ', ' * ** ', ' * * ', ' *** '],
72
+ 'H': [' * * ', ' * * ', ' ***** ', ' * * ', ' * * '],
73
+ 'I': [' ***** ', ' * ', ' * ', ' * ', ' ***** '],
74
+ 'J': [' *****', ' * ', ' * ', ' * * ', ' ** '],
75
+ 'K': [' * * ', ' * * ', ' *** ', ' * * ', ' * * '],
76
+ 'L': [' * ', ' * ', ' * ', ' * ', ' ***** '],
77
+ 'M': [' ** ** ', ' ***** ', ' * * * ', ' * * ', ' * * '],
78
+ 'N': [' ** * ', ' *** * ', ' * *** ', ' * ** ', ' * * '],
79
+ 'O': [' *** ', ' * * ', ' * * ', ' * * ', ' *** '],
80
+ 'P': [' **** ', ' * * ', ' **** ', ' * ', ' * '],
81
+ 'Q': [' *** ', ' * * ', ' * * * ', ' * * ', ' ** * '],
82
+ 'R': [' **** ', ' * * ', ' **** ', ' * * ', ' * * '],
83
+ 'S': [' **** ', ' * ', ' *** ', ' * ', ' **** '],
84
+ 'T': [' ***** ', ' * ', ' * ', ' * ', ' * '],
85
+ 'U': [' * * ', ' * * ', ' * * ', ' * * ', ' *** '],
86
+ 'V': [' * * ', ' * * ', ' * * ', ' * * ', ' * '],
87
+ 'W': [' * * ', ' * * ', ' * * * ', ' ***** ', ' ** ** '],
88
+ 'X': [' * * ', ' * * ', ' * ', ' * * ', ' * * '],
89
+ 'Y': [' * * ', ' * * ', ' * ', ' * ', ' * '],
90
+ 'Z': [' ***** ', ' * ', ' * ', ' * ', ' ***** '],
91
+ ' ': [' ', ' ', ' ', ' ', ' '],
92
+ '!': [' * ', ' * ', ' * ', ' ', ' * '],
93
+ '.': [' ', ' ', ' ', ' ', ' * '],
94
+ '?': [' *** ', ' * ', ' * ', ' ', ' * '],
95
+ '0': [' *** ', ' * ** ', ' * * * ', ' ** * ', ' *** '],
96
+ '1': [' * ', ' ** ', ' * ', ' * ', ' ***** '],
97
+ '2': [' *** ', ' * ', ' *** ', ' * ', ' ***** '],
98
+ '3': [' *** ', ' * ', ' *** ', ' * ', ' *** '],
99
+ '4': [' * * ', ' * * ', ' ***** ', ' * ', ' * '],
100
+ '5': [' ***** ', ' * ', ' **** ', ' * ', ' **** '],
101
+ '6': [' **** ', ' * ', ' **** ', ' * * ', ' *** '],
102
+ '7': [' ***** ', ' * ', ' * ', ' * ', ' * '],
103
+ '8': [' *** ', ' * * ', ' *** ', ' * * ', ' *** '],
104
+ '9': [' *** ', ' * * ', ' **** ', ' * ', ' **** '],
105
+ }
106
+
107
+ # Wide font: double-spaced block (each row repeated horizontally)
108
+ _WIDE = {k: [r.replace(' ', ' ').replace('#', '##') for r in v]
109
+ for k, v in _BLOCK.items()}
110
+
111
+ # Big font: uppercase geometric letters using hash
112
+ _BIG = {
113
+ 'A': [' ##### ', ' ## ## ', ' ## ## ', ' ####### ', ' ## ## ', ' ## ## ', ' ## ## '],
114
+ 'B': [' ###### ', ' ## ## ', ' ###### ', ' ## ## ', ' ###### '],
115
+ 'C': [' ###### ', ' ## ', ' ## ', ' ## ', ' ###### '],
116
+ 'D': [' ###### ', ' ## ## ', ' ## ## ', ' ## ## ', ' ###### '],
117
+ 'E': [' ####### ', ' ## ', ' ###### ', ' ## ', ' ####### '],
118
+ 'F': [' ####### ', ' ## ', ' ###### ', ' ## ', ' ## '],
119
+ 'G': [' ###### ', ' ## ', ' ## ### ', ' ## ## ', ' ##### '],
120
+ 'H': [' ## ## ', ' ## ## ', ' ####### ', ' ## ## ', ' ## ## '],
121
+ 'I': [' ##### ', ' ### ', ' ### ', ' ### ', ' ##### '],
122
+ 'J': [' ##### ', ' ## ', ' ## ', ' ## ## ', ' ### '],
123
+ 'K': [' ## ## ', ' ## ## ', ' ##### ', ' ## ## ', ' ## ## '],
124
+ 'L': [' ## ', ' ## ', ' ## ', ' ## ', ' ####### '],
125
+ 'M': [' ### ### ', ' ###### #', ' ## # ## ', ' ## ## ', ' ## ## '],
126
+ 'N': [' ### ## ', ' ##### # ', ' ## #### ', ' ## ### ', ' ## ## '],
127
+ 'O': [' ##### ', ' ## ## ', ' ## ## ', ' ## ## ', ' ##### '],
128
+ 'P': [' ###### ', ' ## ## ', ' ###### ', ' ## ', ' ## '],
129
+ 'Q': [' ##### ', ' ## ## ', ' ## ## ', ' ## ### ', ' ### ## '],
130
+ 'R': [' ###### ', ' ## ## ', ' ###### ', ' ## ## ', ' ## ## '],
131
+ 'S': [' ###### ', ' ## ', ' ##### ', ' ## ', ' ###### '],
132
+ 'T': [' ####### ', ' ### ', ' ### ', ' ### ', ' ### '],
133
+ 'U': [' ## ## ', ' ## ## ', ' ## ## ', ' ## ## ', ' ##### '],
134
+ 'V': [' ## ## ', ' ## ## ', ' ## ## ', ' ## ## ', ' ### '],
135
+ 'W': [' ## ## ', ' ## ## ', ' ## # ## ', ' ###### #', ' ### ### '],
136
+ 'X': [' ## ## ', ' ## ## ', ' ### ', ' ## ## ', ' ## ## '],
137
+ 'Y': [' ## ## ', ' ## ## ', ' ### ', ' ### ', ' ### '],
138
+ 'Z': [' ####### ', ' ## ', ' ## ', ' ## ', ' ####### '],
139
+ ' ': [' ', ' ', ' ', ' ', ' '],
140
+ '!': [' ## ', ' ## ', ' ## ', ' ', ' ## '],
141
+ '.': [' ', ' ', ' ', ' ', ' ## '],
142
+ '?': [' ##### ', ' ##', ' ### ', ' ', ' ## '],
143
+ '0': [' ##### ', ' ## ###', ' ## # ##', ' ### ##', ' ##### '],
144
+ '1': [' ### ', ' #### ', ' ### ', ' ### ', ' #######'],
145
+ '2': [' ##### ', ' ##', ' #### ', ' ## ', ' #######'],
146
+ '3': [' ##### ', ' ##', ' #### ', ' ##', ' ##### '],
147
+ '4': [' ## ##', ' ## ##', ' ########', ' ##', ' ##'],
148
+ '5': [' ########', ' ## ', ' #######', ' ##', ' ########'],
149
+ '6': [' #####', ' ## ', ' ###### ', ' ## ##', ' #### '],
150
+ '7': [' #######', ' ## ', ' ## ', ' ## ', ' ## '],
151
+ '8': [' ##### ', ' ## ## ', ' ##### ', ' ## ## ', ' ##### '],
152
+ '9': [' ##### ', ' ## ## ', ' ###### ', ' ## ', ' ##### '],
153
+ }
154
+
155
+ FONTS = {
156
+ 'block': _BLOCK,
157
+ 'simple': _SIMPLE,
158
+ 'wide': _WIDE,
159
+ 'big': _BIG,
160
+ }
161
+
162
+
163
+ def get_char_width(font_name):
164
+ """Return the width of a single character in the given font."""
165
+ font = FONTS.get(font_name, _BLOCK)
166
+ for data in font.values():
167
+ if data:
168
+ return len(data[0])
169
+ return 6 # fallback
170
+
171
+
172
+ def generate_banner(text, font_name='block'):
173
+ """Render text using the named font. Returns list of row strings."""
174
+ font = FONTS.get(font_name, _BLOCK)
175
+ rows = max(len(v) for v in font.values()) if font else 5
176
+ result = ['' for _ in range(rows)]
177
+ for ch in text.upper():
178
+ if ch in font:
179
+ for i, row in enumerate(font[ch]):
180
+ result[i] += row
181
+ else:
182
+ w = get_char_width(font_name)
183
+ for i in range(rows):
184
+ result[i] += ' ' * w
185
+ return result
186
+
187
+
188
+ def wrap_banner(banner_rows, width):
189
+ """Wrap banner lines that exceed width into multiple blocks."""
190
+ if not banner_rows:
191
+ return banner_rows
192
+ line_len = len(banner_rows[0])
193
+ if line_len <= width:
194
+ return banner_rows
195
+ # Chunk every banner row into pieces and stack vertically
196
+ chunk_size = width
197
+ num_chunks = (line_len + chunk_size - 1) // chunk_size
198
+ wrapped = []
199
+ for ci in range(num_chunks):
200
+ start = ci * chunk_size
201
+ end = min(start + chunk_size, line_len)
202
+ for row in banner_rows:
203
+ piece = row[start:end]
204
+ # Padded to chunk_size for alignment
205
+ piece = piece.ljust(chunk_size)
206
+ wrapped.append(piece)
207
+ return wrapped
208
+
209
+
210
+ def print_banner(text, font_name='block', width=None):
211
+ """Render and print a banner."""
212
+ if not text:
213
+ return
214
+ banner_rows = generate_banner(text, font_name)
215
+ if width and width > 0:
216
+ banner_rows = wrap_banner(banner_rows, width)
217
+ for row in banner_rows:
218
+ print(row.rstrip())
219
+
220
+
221
+ def list_fonts():
222
+ """Print available fonts."""
223
+ print("Available fonts:")
224
+ for name in sorted(FONTS):
225
+ desc = {
226
+ 'block': 'hash-filled block letters (#)',
227
+ 'simple': 'star-and-line outline letters (*)',
228
+ 'wide': 'double-spaced block letters',
229
+ 'big': 'uppercase geometric letters (7-row)',
230
+ }.get(name, '')
231
+ print(f" {name:<10} {desc}")
232
+
233
+
234
+ def main():
235
+ args = sys.argv[1:]
236
+
237
+ # Parse --font and --width manually (stdlib only, no argparse)
238
+ font_name = 'block'
239
+ width = None
240
+ text_args = []
241
+
242
+ i = 0
243
+ while i < len(args):
244
+ a = args[i]
245
+ if a == '--font' and i + 1 < len(args):
246
+ font_name = args[i + 1]
247
+ i += 2
248
+ elif a.startswith('--font='):
249
+ font_name = a.split('=', 1)[1]
250
+ i += 1
251
+ elif a == '--width' and i + 1 < len(args):
252
+ try:
253
+ width = int(args[i + 1])
254
+ except ValueError:
255
+ pass
256
+ i += 2
257
+ elif a.startswith('--width='):
258
+ try:
259
+ width = int(a.split('=', 1)[1])
260
+ except ValueError:
261
+ pass
262
+ i += 1
263
+ elif a == '--list':
264
+ list_fonts()
265
+ return
266
+ elif a == '--help' or a == '-h':
267
+ print(__doc__.strip())
268
+ return
269
+ else:
270
+ text_args.append(a)
271
+ i += 1
272
+
273
+ # Check font name
274
+ if font_name not in FONTS:
275
+ print(f"Unknown font '{font_name}'. Use --list to see available fonts.", file=sys.stderr)
276
+ sys.exit(1)
277
+
278
+ # Get text: positional args or stdin
279
+ if text_args:
280
+ text = ' '.join(text_args)
281
+ else:
282
+ stdin_data = sys.stdin.read() if sys.stdin is not None else ''
283
+ text = stdin_data.strip()
284
+
285
+ if not text:
286
+ print("Usage: banner [--font=NAME] [--width=N] [--list] <text>", file=sys.stderr)
287
+ print(" echo text | banner [--font=NAME] [--width=N]", file=sys.stderr)
288
+ sys.exit(1)
289
+
290
+ print_banner(text, font_name, width)
291
+
292
+
293
+ TOOL_META = {"name": "banner", "func": "main", "desc": "ASCII art banner generator — block, simple, wide, big fonts"}
294
+
295
+ if __name__ == '__main__':
296
+ main()
@@ -0,0 +1,323 @@
1
+ #!/usr/bin/env python3
2
+ """code-review — Basic code review helper for Python files.
3
+
4
+ Usage:
5
+ code-review <file.py> [--lines=1-50]
6
+ cat file.py | code-review
7
+
8
+ Checks for: line length, TODOs, missing shebang, trailing whitespace,
9
+ missing docstrings, CRLF line endings, tabs, long functions, bare
10
+ excepts, unused imports (flagged heuristically), and more.
11
+
12
+ Output uses severity tags: [ERROR], [WARN], [INFO].
13
+ """
14
+
15
+ import sys
16
+ import os
17
+ import re
18
+ import ast
19
+ import argparse
20
+
21
+
22
+ # ---------------------------------------------------------------------------
23
+ # Checks
24
+ # ---------------------------------------------------------------------------
25
+
26
+ def check_shebang(lines, path):
27
+ """[ERROR] Python files should start with a shebang."""
28
+ if path and path.endswith('.py'):
29
+ if not lines or not lines[0].startswith('#!'):
30
+ return [("[ERROR] Line 1: Missing shebang "
31
+ "(e.g. #!/usr/bin/env python3)")]
32
+ return []
33
+
34
+
35
+ def check_line_length(lines, max_len=100):
36
+ """[WARN] Lines exceeding max_len characters."""
37
+ issues = []
38
+ for i, line in enumerate(lines, 1):
39
+ # Skip URLs and long string literals to reduce noise
40
+ if len(line.rstrip('\n')) > max_len:
41
+ stripped = line.rstrip('\n')
42
+ if not re.match(r'^\s*#\s*http', stripped):
43
+ issues.append(
44
+ f"[WARN] Line {i}: {len(stripped)} chars "
45
+ f"(max {max_len})"
46
+ )
47
+ return issues
48
+
49
+
50
+ def check_todos(lines):
51
+ """[INFO] Flag TODO / FIXME / XXX comments."""
52
+ issues = []
53
+ pattern = re.compile(r'(TODO|FIXME|XXX|HACK|BUG)\b', re.IGNORECASE)
54
+ for i, line in enumerate(lines, 1):
55
+ m = pattern.search(line)
56
+ if m:
57
+ issues.append(f"[INFO] Line {i}: {m.group(0)} found — "
58
+ f"\"{line.strip()}\"")
59
+ return issues
60
+
61
+
62
+ def check_trailing_whitespace(lines):
63
+ """[WARN] Trailing whitespace on lines."""
64
+ issues = []
65
+ for i, line in enumerate(lines, 1):
66
+ if line != line.rstrip('\n').rstrip() + '\n':
67
+ issues.append(f"[WARN] Line {i}: trailing whitespace")
68
+ return issues
69
+
70
+
71
+ def check_crlf(lines):
72
+ """[WARN] Carriage-return line endings (CRLF)."""
73
+ for i, line in enumerate(lines, 1):
74
+ if '\r\n' in line:
75
+ return ["[WARN] Line {i}: CRLF (\\r\\n) line ending detected"]
76
+ return []
77
+
78
+
79
+ def check_tabs(lines):
80
+ """[ERROR] Tab characters used instead of spaces."""
81
+ issues = []
82
+ for i, line in enumerate(lines, 1):
83
+ if '\t' in line:
84
+ issues.append(f"[ERROR] Line {i}: tab character used")
85
+ return issues
86
+
87
+
88
+ def check_missing_docstrings(code_lines, source):
89
+ """[INFO] Functions, classes, and modules missing docstrings."""
90
+ issues = []
91
+ try:
92
+ tree = ast.parse(source)
93
+ except SyntaxError as e:
94
+ return [f"[ERROR] Syntax error: {e}"]
95
+
96
+ # Module-level docstring
97
+ if (not isinstance(tree.body[0], ast.Expr)
98
+ or not isinstance(tree.body[0].value, ast.Constant)
99
+ or not isinstance(tree.body[0].value.value, str)):
100
+ issues.append("[INFO] Module: missing module-level docstring")
101
+
102
+ for node in ast.walk(tree):
103
+ # Functions / methods
104
+ if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
105
+ doc = ast.get_docstring(node)
106
+ if not doc:
107
+ lineno = getattr(node, 'lineno', '?')
108
+ issues.append(
109
+ f"[INFO] Line {lineno}: "
110
+ f"function '{node.name}' missing docstring"
111
+ )
112
+ # Classes
113
+ elif isinstance(node, ast.ClassDef):
114
+ doc = ast.get_docstring(node)
115
+ if not doc:
116
+ lineno = getattr(node, 'lineno', '?')
117
+ issues.append(
118
+ f"[INFO] Line {lineno}: "
119
+ f"class '{node.name}' missing docstring"
120
+ )
121
+ return issues
122
+
123
+
124
+ def check_long_functions(code_lines, source, max_lines=50):
125
+ """[WARN] Functions that exceed max_lines."""
126
+ issues = []
127
+ try:
128
+ tree = ast.parse(source)
129
+ except SyntaxError:
130
+ return []
131
+ for node in ast.walk(tree):
132
+ if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
133
+ end_lineno = getattr(node, 'end_lineno', node.lineno)
134
+ nlines = end_lineno - node.lineno + 1
135
+ if nlines > max_lines:
136
+ issues.append(
137
+ f"[WARN] Line {node.lineno}: "
138
+ f"function '{node.name}' is {nlines} lines "
139
+ f"(recommended <= {max_lines})"
140
+ )
141
+ return issues
142
+
143
+
144
+ def check_bare_excepts(source):
145
+ """[ERROR] Bare 'except:' clauses without exception type."""
146
+ issues = []
147
+ pattern = re.compile(r'^(\s*?)except\s*:')
148
+ for i, line in enumerate(source.splitlines(), 1):
149
+ if pattern.match(line):
150
+ issues.append(
151
+ f"[ERROR] Line {i}: bare except clause — "
152
+ f"use 'except Exception:' instead"
153
+ )
154
+ return issues
155
+
156
+
157
+ def check_imports(source):
158
+ """[WARN] Wildcard imports."""
159
+ issues = []
160
+ for i, line in enumerate(source.splitlines(), 1):
161
+ stripped = line.strip()
162
+ if stripped.startswith('from ') and ' import *' in stripped:
163
+ issues.append(
164
+ f"[WARN] Line {i}: wildcard import (from ... import *)"
165
+ )
166
+ return issues
167
+
168
+
169
+ # ---------------------------------------------------------------------------
170
+ # Parse --lines argument
171
+ # ---------------------------------------------------------------------------
172
+
173
+ def parse_line_range(lines_arg, total_lines):
174
+ """Return (start, end) 1-indexed slice, or (1, total_lines)."""
175
+ if not lines_arg:
176
+ return (1, total_lines)
177
+ m = re.match(r'^(\d+)(?:-(\d+))?$', lines_arg)
178
+ if not m:
179
+ sys.stderr.write(f"error: invalid --lines format '{lines_arg}'. "
180
+ "Use N-M (e.g. 1-50) or just N.\n")
181
+ sys.exit(1)
182
+ start = int(m.group(1))
183
+ end = int(m.group(2)) if m.group(2) else start
184
+ if start < 1:
185
+ start = 1
186
+ if end > total_lines:
187
+ end = total_lines
188
+ if start > end:
189
+ start, end = end, start
190
+ return (start, end)
191
+
192
+
193
+ # ---------------------------------------------------------------------------
194
+ # Main
195
+ # ---------------------------------------------------------------------------
196
+
197
+ def main():
198
+ parser = argparse.ArgumentParser(
199
+ description="Code review helper for Python files."
200
+ )
201
+ parser.add_argument(
202
+ 'file', nargs='?', default=None,
203
+ help="Path to Python file to review (reads from stdin if omitted)"
204
+ )
205
+ parser.add_argument(
206
+ '--lines', default=None,
207
+ help="Line range to check, e.g. '1-50' or '42'"
208
+ )
209
+ parser.add_argument(
210
+ '--max-line-length', type=int, default=100,
211
+ help="Maximum allowed line length (default: 100)"
212
+ )
213
+ parser.add_argument(
214
+ '--max-function-lines', type=int, default=50,
215
+ help="Maximum function length in lines (default: 50)"
216
+ )
217
+ args = parser.parse_args()
218
+
219
+ if args.file:
220
+ path = args.file
221
+ try:
222
+ with open(path, 'rb') as f:
223
+ raw = f.read()
224
+ except FileNotFoundError:
225
+ sys.stderr.write(f"error: file not found: {path}\n")
226
+ sys.exit(1)
227
+ except PermissionError:
228
+ sys.stderr.write(f"error: permission denied: {path}\n")
229
+ sys.exit(1)
230
+ else:
231
+ path = None
232
+ raw = sys.stdin.buffer.read()
233
+
234
+ # Decode, preserving line endings for CRLF detection
235
+ try:
236
+ text = raw.decode('utf-8')
237
+ except UnicodeDecodeError:
238
+ text = raw.decode('latin-1')
239
+ sys.stderr.write("warning: file is not UTF-8; decoded as latin-1\n")
240
+
241
+ all_lines = text.splitlines(keepends=True)
242
+ total = len(all_lines)
243
+
244
+ start, end = parse_line_range(args.lines, total)
245
+ if not args.lines:
246
+ start, end = 1, total
247
+
248
+ lines = all_lines[start - 1:end]
249
+ source = ''.join(lines)
250
+
251
+ # Collect all issues
252
+ all_issues = []
253
+
254
+ # --lines mode: only run per-line checks on the subset
255
+ all_issues.extend(check_shebang(all_lines, path))
256
+ all_issues.extend(check_line_length(lines, args.max_line_length))
257
+ all_issues.extend(check_todos(lines))
258
+ all_issues.extend(check_trailing_whitespace(lines))
259
+ all_issues.extend(check_crlf(lines))
260
+ all_issues.extend(check_tabs(lines))
261
+ # AST-based checks need the full function boundaries; we always run
262
+ # on the full file for these, but only report issues in the range.
263
+ full_source = ''.join(all_lines)
264
+ for issue in check_missing_docstrings(all_lines, full_source):
265
+ lineno_match = re.search(r'Line (\d+)', issue)
266
+ if lineno_match:
267
+ lineno = int(lineno_match.group(1))
268
+ if start <= lineno <= end:
269
+ all_issues.append(issue)
270
+ else:
271
+ all_issues.append(issue)
272
+ for issue in check_long_functions(all_lines, full_source,
273
+ args.max_function_lines):
274
+ lineno_match = re.search(r'Line (\d+)', issue)
275
+ if lineno_match:
276
+ lineno = int(lineno_match.group(1))
277
+ if start <= lineno <= end:
278
+ all_issues.append(issue)
279
+ else:
280
+ all_issues.append(issue)
281
+ all_issues.extend(check_bare_excepts(source))
282
+ all_issues.extend(check_imports(source))
283
+
284
+ # Sort by line number where possible
285
+ def sort_key(issue):
286
+ m = re.search(r'Line (\d+)', issue)
287
+ return int(m.group(1)) if m else 0
288
+ all_issues.sort(key=sort_key)
289
+
290
+ # Output
291
+ if not all_issues:
292
+ print("No issues found.")
293
+ return
294
+
295
+ for issue in all_issues:
296
+ print(issue)
297
+
298
+ # Summary
299
+ errors = sum(1 for i in all_issues if i.startswith('[ERROR]'))
300
+ warns = sum(1 for i in all_issues if i.startswith('[WARN]'))
301
+ infos = sum(1 for i in all_issues if i.startswith('[INFO]'))
302
+ print(f"\n--- Summary: {errors} errors, {warns} warnings, "
303
+ f"{infos} info items ---")
304
+
305
+ if errors:
306
+ sys.exit(1)
307
+
308
+
309
+ # ---------------------------------------------------------------------------
310
+ # Tool metadata for auto-discovery
311
+ # ---------------------------------------------------------------------------
312
+
313
+ TOOL_META = {
314
+ "name": "code-review",
315
+ "func": "main",
316
+ "desc": "Basic code review: line length, TODOs, shebang, "
317
+ "trailing whitespace, docstrings, CRLF, tabs, "
318
+ "long functions, bare excepts, wildcard imports"
319
+ }
320
+
321
+
322
+ if __name__ == '__main__':
323
+ main()