evolver-tools 20.0.0__tar.gz → 21.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 (258) hide show
  1. {evolver_tools-20.0.0/src/evolver_tools.egg-info → evolver_tools-21.0.0}/PKG-INFO +2 -2
  2. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/pyproject.toml +2 -2
  3. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/cli.py +1 -1
  4. evolver_tools-21.0.0/src/evolver_tools/vendor/csv_merge.py +158 -0
  5. evolver_tools-21.0.0/src/evolver_tools/vendor/diff_files.py +86 -0
  6. evolver_tools-21.0.0/src/evolver_tools/vendor/http_server.py +66 -0
  7. evolver_tools-21.0.0/src/evolver_tools/vendor/json_flatten.py +81 -0
  8. evolver_tools-21.0.0/src/evolver_tools/vendor/pdf_info.py +106 -0
  9. {evolver_tools-20.0.0 → evolver_tools-21.0.0/src/evolver_tools.egg-info}/PKG-INFO +2 -2
  10. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools.egg-info/SOURCES.txt +5 -0
  11. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/LICENSE +0 -0
  12. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/README.md +0 -0
  13. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/setup.cfg +0 -0
  14. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/__init__.py +0 -0
  15. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/__main__.py +0 -0
  16. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/autoreg.py +0 -0
  17. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/__init__.py +0 -0
  18. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/agent_b_tool.py +0 -0
  19. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/ansi_strip.py +0 -0
  20. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/api_tester.py +0 -0
  21. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/ascii_gen.py +0 -0
  22. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/audit_log.py +0 -0
  23. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/b64/__init__.py +0 -0
  24. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/b64/b64.py +0 -0
  25. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/backup.py +0 -0
  26. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/banner/__init__.py +0 -0
  27. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/banner/banner.py +0 -0
  28. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/banner.py +0 -0
  29. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/base32.py +0 -0
  30. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/bookmark.py +0 -0
  31. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/cal_tool/__init__.py +0 -0
  32. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/cal_tool/cli.py +0 -0
  33. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/calendar_cli.py +0 -0
  34. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/cert_check.py +0 -0
  35. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/cert_info.py +0 -0
  36. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/changelog_gen/__init__.py +0 -0
  37. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/changelog_gen/changelog_gen.py +0 -0
  38. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/changelog_gen.py +0 -0
  39. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/chart_cli/__init__.py +0 -0
  40. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/chart_cli/__main__.py +0 -0
  41. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/checksum_dir.py +0 -0
  42. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/clipboard/__init__.py +0 -0
  43. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/clipboard/clipboard.py +0 -0
  44. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/code_auditor.py +0 -0
  45. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/code_stats.py +0 -0
  46. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/colorize.py +0 -0
  47. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/colors/__init__.py +0 -0
  48. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/colors/__main__.py +0 -0
  49. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/config_validator.py +0 -0
  50. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/config_vault.py +0 -0
  51. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/cowsay.py +0 -0
  52. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/cron/__init__.py +0 -0
  53. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/cron/__main__.py +0 -0
  54. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/cron_pretty.py +0 -0
  55. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/crontab_helper.py +0 -0
  56. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/crypto_box.py +0 -0
  57. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/crypto_price.py +0 -0
  58. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/csv2json.py +0 -0
  59. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/csv_stats/__init__.py +0 -0
  60. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/csv_stats/__main__.py +0 -0
  61. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/csv_stats/analyzer.py +0 -0
  62. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/csv_stats/cli.py +0 -0
  63. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/csv_validate.py +0 -0
  64. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/csv_view.py +0 -0
  65. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/db_mate.py +0 -0
  66. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/db_schema.py +0 -0
  67. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/dep_graph.py +0 -0
  68. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/dev_dashboard.py +0 -0
  69. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/dice_roll.py +0 -0
  70. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/diff_csv.py +0 -0
  71. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/diff_tool/__init__.py +0 -0
  72. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/diff_tool/__main__.py +0 -0
  73. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/dirsize/__init__.py +0 -0
  74. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/disk_cleanup.py +0 -0
  75. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/disk_usage/__init__.py +0 -0
  76. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/disk_usage/disk_usage.py +0 -0
  77. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/dns_lookup.py +0 -0
  78. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/docker_helper.py +0 -0
  79. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/dt_convert.py +0 -0
  80. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/env_diff.py +0 -0
  81. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/env_manager.py +0 -0
  82. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/envcheck/__init__.py +0 -0
  83. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/epoch.py +0 -0
  84. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/excel2csv.py +0 -0
  85. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/factor.py +0 -0
  86. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/ff/__init__.py +0 -0
  87. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/ff/__main__.py +0 -0
  88. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/figlet_cli.py +0 -0
  89. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/figlet_tool.py +0 -0
  90. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/file_encrypt.py +0 -0
  91. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/file_joiner.py +0 -0
  92. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/file_splitter.py +0 -0
  93. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/file_watch.py +0 -0
  94. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/find_dups/__init__.py +0 -0
  95. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/find_dups/cli.py +0 -0
  96. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/firewall_rule.py +0 -0
  97. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/fmt/__init__.py +0 -0
  98. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/fmt/fmt.py +0 -0
  99. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/fold.py +0 -0
  100. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/geo_ip.py +0 -0
  101. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/git_branch_cleaner.py +0 -0
  102. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/git_log_pretty.py +0 -0
  103. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/git_stats.py +0 -0
  104. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/hash_check.py +0 -0
  105. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/hash_file.py +0 -0
  106. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/hashsum/__init__.py +0 -0
  107. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/hashsum/__main__.py +0 -0
  108. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/hex_tool.py +0 -0
  109. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/hexdump.py +0 -0
  110. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/html2markdown.py +0 -0
  111. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/html2md.py +0 -0
  112. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/http_headers.py +0 -0
  113. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/http_live/__init__.py +0 -0
  114. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/http_live/__main__.py +0 -0
  115. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/image_meta.py +0 -0
  116. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/ini2json.py +0 -0
  117. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/ini_parser/__init__.py +0 -0
  118. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/ini_parser/ini_parser.py +0 -0
  119. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/ip_location.py +0 -0
  120. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/ipcalc/__init__.py +0 -0
  121. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/ipcalc/__main__.py +0 -0
  122. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/ipinfo/__init__.py +0 -0
  123. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/ipinfo/__main__.py +0 -0
  124. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/join.py +0 -0
  125. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/joke.py +0 -0
  126. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/jq_lite/__init__.py +0 -0
  127. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/jq_lite/__main__.py +0 -0
  128. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/json2csv/__init__.py +0 -0
  129. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/json2csv/__main__.py +0 -0
  130. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/json2ini.py +0 -0
  131. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/json_pretty/__init__.py +0 -0
  132. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/json_pretty/json_pretty.py +0 -0
  133. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/json_schema_validate.py +0 -0
  134. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/jsonql/__init__.py +0 -0
  135. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/jsonql/__main__.py +0 -0
  136. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/key_value_store.py +0 -0
  137. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/license.py +0 -0
  138. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/license_cli/__init__.py +0 -0
  139. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/license_cli/__main__.py +0 -0
  140. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/license_cli/cli.py +0 -0
  141. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/log_analyzer.py +0 -0
  142. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/log_hawk.py +0 -0
  143. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/log_tail.py +0 -0
  144. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/macrogen.py +0 -0
  145. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/markdown_check/__init__.py +0 -0
  146. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/markdown_preview.py +0 -0
  147. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/markdown_toc.py +0 -0
  148. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/media_studio.py +0 -0
  149. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/morse.py +0 -0
  150. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/nb/__init__.py +0 -0
  151. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/nb/__main__.py +0 -0
  152. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/net_analyzer.py +0 -0
  153. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/net_speed.py +0 -0
  154. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/network_scan.py +0 -0
  155. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/nl.py +0 -0
  156. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/note_taker.py +0 -0
  157. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/otp_gen.py +0 -0
  158. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/passgen/__init__.py +0 -0
  159. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/password_strength.py +0 -0
  160. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/pdf_text.py +0 -0
  161. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/pipe_viewer.py +0 -0
  162. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/pomodoro.py +0 -0
  163. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/port_scan.py +0 -0
  164. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/portcheck/__init__.py +0 -0
  165. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/portcheck/__main__.py +0 -0
  166. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/pr_tool/__init__.py +0 -0
  167. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/pr_tool/pr_tool.py +0 -0
  168. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/process_kill.py +0 -0
  169. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/progress_bar.py +0 -0
  170. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/project_doctor/__init__.py +0 -0
  171. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/project_doctor/__main__.py +0 -0
  172. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/qc_calc.py +0 -0
  173. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/qc_report.py +0 -0
  174. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/qc_sample.py +0 -0
  175. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/qr_cli.py +0 -0
  176. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/qrcode.py +0 -0
  177. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/quote.py +0 -0
  178. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/quote_tool/__init__.py +0 -0
  179. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/quote_tool/quote.py +0 -0
  180. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/rainbow.py +0 -0
  181. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/random.py +0 -0
  182. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/reminder.py +0 -0
  183. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/ren/__init__.py +0 -0
  184. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/ren/__main__.py +0 -0
  185. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/replace_text.py +0 -0
  186. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/restore.py +0 -0
  187. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/rot13.py +0 -0
  188. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/route_trace.py +0 -0
  189. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/scan_ports.py +0 -0
  190. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/screen_recorder.py +0 -0
  191. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/screenshot_cli.py +0 -0
  192. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/search_files.py +0 -0
  193. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/search_history.py +0 -0
  194. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/secret_scanner.py +0 -0
  195. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/seq.py +0 -0
  196. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/service_check.py +0 -0
  197. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/shuffle.py +0 -0
  198. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/siege_lite/__init__.py +0 -0
  199. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/siege_lite/__main__.py +0 -0
  200. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/smellfinder/__init__.py +0 -0
  201. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/smellfinder/__main__.py +0 -0
  202. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/sort/__init__.py +0 -0
  203. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/sort/sort.py +0 -0
  204. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/spinner.py +0 -0
  205. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/split.py +0 -0
  206. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/split_tool/__init__.py +0 -0
  207. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/split_tool/split.py +0 -0
  208. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/sql2csv.py +0 -0
  209. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/sqlite_cli/__init__.py +0 -0
  210. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/sqlite_cli/__main__.py +0 -0
  211. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/ssh_key_gen.py +0 -0
  212. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/ssl_check.py +0 -0
  213. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/stopwatch.py +0 -0
  214. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/subnet.py +0 -0
  215. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/sysmon/__init__.py +0 -0
  216. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/sysmon/__main__.py +0 -0
  217. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/sysmon_pro.py +0 -0
  218. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/system_info.py +0 -0
  219. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/temp_cleaner.py +0 -0
  220. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/template.py +0 -0
  221. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/text_stats.py +0 -0
  222. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/timeout.py +0 -0
  223. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/timer/__init__.py +0 -0
  224. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/timer_pro/__init__.py +0 -0
  225. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/timer_pro/timer_pro.py +0 -0
  226. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/timer_pro.py +0 -0
  227. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/todo_cli.py +0 -0
  228. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/toml2json.py +0 -0
  229. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/tr.py +0 -0
  230. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/tree.py +0 -0
  231. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/treedir/__init__.py +0 -0
  232. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/treedir/__main__.py +0 -0
  233. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/uniq_tool/__init__.py +0 -0
  234. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/uniq_tool/uniq.py +0 -0
  235. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/unit_convert.py +0 -0
  236. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/uri_encode.py +0 -0
  237. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/url_parser.py +0 -0
  238. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/urlparse_tool/__init__.py +0 -0
  239. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/urlparse_tool/cli.py +0 -0
  240. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/uuid_tool/__init__.py +0 -0
  241. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/uuid_tool/__main__.py +0 -0
  242. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/watch.py +0 -0
  243. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/weather_cli.py +0 -0
  244. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/web_download.py +0 -0
  245. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/web_summary/__init__.py +0 -0
  246. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/web_summary/__main__.py +0 -0
  247. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/whois_lookup.py +0 -0
  248. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/wordcount/__init__.py +0 -0
  249. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/wordcount/__main__.py +0 -0
  250. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/xml2json.py +0 -0
  251. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/yaml2json/__init__.py +0 -0
  252. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/yaml2json/yaml2json.py +0 -0
  253. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/yaml2toml.py +0 -0
  254. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/yaml_validate.py +0 -0
  255. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools/vendor/yes.py +0 -0
  256. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools.egg-info/dependency_links.txt +0 -0
  257. {evolver_tools-20.0.0 → evolver_tools-21.0.0}/src/evolver_tools.egg-info/entry_points.txt +0 -0
  258. {evolver_tools-20.0.0 → evolver_tools-21.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: 20.0.0
4
- Summary: 186 CLI tools + 9 flagship projects — one pip install
3
+ Version: 21.0.0
4
+ Summary: 191 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 = "20.0.0"
8
- description = "186 CLI tools + 9 flagship projects — one pip install"
7
+ version = "21.0.0"
8
+ description = "191 CLI tools + 9 flagship projects — one pip install"
9
9
  readme = "README.md"
10
10
  license = "MIT"
11
11
  requires-python = ">=3.8"
@@ -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 v20.0.0 =====\x1b[0m')
17
+ print(f'\x1b[1;36m===== EVOLVER Tools v21.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,158 @@
1
+ #!/usr/bin/env python3
2
+ """csv_merge — Merge multiple CSV files by a common column.
3
+
4
+ Usage: csv_merge file1.csv file2.csv --on id
5
+ csv_merge file1.csv file2.csv --on id --how outer
6
+ csv_merge *.csv --on user_id --output merged.csv
7
+
8
+ Joins CSV files on a common key column, like SQL JOIN.
9
+ Supports inner, left, and outer joins.
10
+ Zero external dependencies.
11
+ """
12
+
13
+ import csv
14
+ import sys
15
+ import os
16
+ from collections import OrderedDict
17
+
18
+ TOOL_META = {
19
+ "name": "csv_merge",
20
+ "func": "main",
21
+ "desc": "Merge CSV files by common column (inner/left/outer join)",
22
+ }
23
+
24
+ def load_csv(path):
25
+ with open(path, newline='', encoding='utf-8-sig') as f:
26
+ reader = csv.DictReader(f)
27
+ rows = list(reader)
28
+ if not rows:
29
+ return [], []
30
+ return rows, list(rows[0].keys())
31
+
32
+
33
+ def main():
34
+ args = sys.argv[1:]
35
+ if not args or args[0] in ('-h', '--help'):
36
+ print(__doc__)
37
+ return
38
+
39
+ # Parse --on, --how, --output
40
+ on_col = None
41
+ how = 'inner'
42
+ output = None
43
+ files = []
44
+
45
+ i = 0
46
+ while i < len(args):
47
+ if args[i] == '--on' and i + 1 < len(args):
48
+ on_col = args[i + 1]
49
+ i += 2
50
+ elif args[i] == '--how' and i + 1 < len(args):
51
+ how = args[i + 1].lower()
52
+ i += 2
53
+ elif args[i] == '--output' and i + 1 < len(args):
54
+ output = args[i + 1]
55
+ i += 2
56
+ else:
57
+ files.append(args[i])
58
+ i += 1
59
+
60
+ if len(files) < 2:
61
+ print("Error: need at least 2 CSV files", file=sys.stderr)
62
+ sys.exit(1)
63
+
64
+ if not on_col:
65
+ print("Error: --on <column> required", file=sys.stderr)
66
+ sys.exit(1)
67
+
68
+ # Load all CSVs
69
+ tables = []
70
+ for f in files:
71
+ if not os.path.exists(f):
72
+ print(f"Error: file not found: {f}", file=sys.stderr)
73
+ sys.exit(1)
74
+ rows, cols = load_csv(f)
75
+ tables.append((os.path.basename(f), rows, cols))
76
+
77
+ # Build lookup from first file
78
+ lookup = {}
79
+ for row in tables[0][1]:
80
+ key = row.get(on_col, '')
81
+ lookup[key] = row
82
+
83
+ # Merge subsequent files
84
+ merged = []
85
+ all_cols_set = OrderedDict()
86
+ for t in tables:
87
+ for c in t[2]:
88
+ all_cols_set[c] = True
89
+
90
+ all_cols = list(all_cols_set.keys())
91
+
92
+ if how == 'inner':
93
+ for t in tables[1:]:
94
+ for row in t[1]:
95
+ key = row.get(on_col, '')
96
+ if key in lookup:
97
+ merged_row = OrderedDict()
98
+ for c in all_cols:
99
+ merged_row[c] = lookup[key].get(c, '') or row.get(c, '')
100
+ merged.append(merged_row)
101
+ # For inner, merge first two then subsequent
102
+ if len(tables) > 2:
103
+ # Re-merge with remaining tables
104
+ temp = merged
105
+ for t in tables[2:]:
106
+ merged2 = []
107
+ t_lookup = {r.get(on_col, ''): r for r in t[1]}
108
+ for row in temp:
109
+ key = row.get(on_col, '')
110
+ if key in t_lookup:
111
+ merged_row = OrderedDict(row)
112
+ for c in t_lookup[key]:
113
+ if c != on_col and c not in merged_row:
114
+ merged_row[c] = t_lookup[key][c]
115
+ merged2.append(merged_row)
116
+ temp = merged2
117
+ merged = temp
118
+ elif how == 'left':
119
+ merged = list(lookup.values())
120
+ for t in tables[1:]:
121
+ t_lookup = {r.get(on_col, ''): r for r in t[1]}
122
+ for row in merged:
123
+ key = row.get(on_col, '')
124
+ if key in t_lookup:
125
+ for c, v in t_lookup[key].items():
126
+ if c != on_col and c not in row:
127
+ row[c] = v
128
+ elif how == 'outer':
129
+ all_keys = set()
130
+ for t in tables:
131
+ for r in t[1]:
132
+ all_keys.add(r.get(on_col, ''))
133
+ key_rows = {}
134
+ for t in tables:
135
+ for r in t[1]:
136
+ k = r.get(on_col, '')
137
+ if k not in key_rows:
138
+ key_rows[k] = OrderedDict()
139
+ key_rows[k][on_col] = k
140
+ for c, v in r.items():
141
+ if c != on_col and v:
142
+ key_rows[k][c] = v
143
+ merged = list(key_rows.values())
144
+ else:
145
+ print(f"Error: unknown join type: {how} (use inner/left/outer)", file=sys.stderr)
146
+ sys.exit(1)
147
+
148
+ # Write output
149
+ if output:
150
+ with open(output, 'w', newline='', encoding='utf-8') as f:
151
+ writer = csv.DictWriter(f, fieldnames=list(all_cols_set.keys()))
152
+ writer.writeheader()
153
+ writer.writerows(merged)
154
+ print(f"Merged {len(merged)} rows -> {output}")
155
+ else:
156
+ writer = csv.DictWriter(sys.stdout, fieldnames=list(all_cols_set.keys()))
157
+ writer.writeheader()
158
+ writer.writerows(merged)
@@ -0,0 +1,86 @@
1
+ #!/usr/bin/env python3
2
+ """diff_files — Line-by-line file comparison.
3
+
4
+ Usage: diff_files file1.txt file2.txt
5
+ diff_files file1.txt file2.txt --context 3
6
+ diff_files file1.txt file2.txt --brief
7
+
8
+ Simple diff tool. Shows added/removed lines with +/- markers.
9
+ Zero external dependencies (pure Python difflib).
10
+ """
11
+
12
+ import difflib
13
+ import sys
14
+ import os
15
+
16
+ TOOL_META = {
17
+ "name": "diff_files",
18
+ "func": "main",
19
+ "desc": "Line-by-line file comparison",
20
+ }
21
+
22
+
23
+ def main():
24
+ args = sys.argv[1:]
25
+ context = 3
26
+ brief = False
27
+ files = []
28
+
29
+ i = 0
30
+ while i < len(args):
31
+ if args[i] == '--context' and i + 1 < len(args):
32
+ context = int(args[i + 1])
33
+ i += 2
34
+ elif args[i] == '--brief' or args[i] == '-q':
35
+ brief = True
36
+ i += 1
37
+ elif args[i] in ('-h', '--help'):
38
+ print(__doc__)
39
+ return
40
+ else:
41
+ files.append(args[i])
42
+ i += 1
43
+
44
+ if len(files) != 2:
45
+ print("Error: need exactly 2 files", file=sys.stderr)
46
+ print(__doc__)
47
+ sys.exit(1)
48
+
49
+ file1, file2 = files
50
+ for f in (file1, file2):
51
+ if not os.path.exists(f):
52
+ print(f"Error: file not found: {f}", file=sys.stderr)
53
+ sys.exit(1)
54
+
55
+ with open(file1) as f:
56
+ lines1 = f.readlines()
57
+ with open(file2) as f:
58
+ lines2 = f.readlines()
59
+
60
+ if brief:
61
+ if lines1 != lines2:
62
+ print(f"Files {file1} and {file2} differ")
63
+ else:
64
+ print(f"Files {file1} and {file2} are identical")
65
+ return
66
+
67
+ diff = difflib.unified_diff(
68
+ lines1, lines2,
69
+ fromfile=file1, tofile=file2,
70
+ n=context
71
+ )
72
+
73
+ output = list(diff)
74
+ if not output:
75
+ print("Files are identical.")
76
+ return
77
+
78
+ for line in output:
79
+ if line.startswith('+') and not line.startswith('+++'):
80
+ sys.stdout.write(f'\033[32m{line}\033[0m')
81
+ elif line.startswith('-') and not line.startswith('---'):
82
+ sys.stdout.write(f'\033[31m{line}\033[0m')
83
+ elif line.startswith('@@'):
84
+ sys.stdout.write(f'\033[36m{line}\033[0m')
85
+ else:
86
+ sys.stdout.write(line)
@@ -0,0 +1,66 @@
1
+ #!/usr/bin/env python3
2
+ """http_server — Simple static file HTTP server.
3
+
4
+ Usage: http_server # Port 8080, current dir
5
+ http_server 3000 # Port 3000
6
+ http_server 8080 ./docs # Port 8080, serve ./docs
7
+ http_server --bind 0.0.0.0 9090
8
+
9
+ Lightweight alternative to 'python -m http.server' with
10
+ better defaults and cleaner output.
11
+ """
12
+
13
+ import os
14
+ import sys
15
+ import http.server
16
+ import socketserver
17
+
18
+ TOOL_META = {
19
+ "name": "http_server",
20
+ "func": "main",
21
+ "desc": "Simple static file HTTP server",
22
+ }
23
+
24
+
25
+ def main():
26
+ args = sys.argv[1:]
27
+ port = 8080
28
+ directory = os.getcwd()
29
+ bind = '127.0.0.1'
30
+
31
+ i = 0
32
+ while i < len(args):
33
+ if args[i] == '--bind' and i + 1 < len(args):
34
+ bind = args[i + 1]
35
+ i += 2
36
+ elif args[i] in ('-h', '--help'):
37
+ print(__doc__)
38
+ return
39
+ else:
40
+ try:
41
+ port = int(args[i])
42
+ except ValueError:
43
+ directory = os.path.abspath(args[i])
44
+ i += 1
45
+
46
+ if not os.path.isdir(directory):
47
+ print(f"Error: directory not found: {directory}", file=sys.stderr)
48
+ sys.exit(1)
49
+
50
+ os.chdir(directory)
51
+ handler = http.server.SimpleHTTPRequestHandler
52
+
53
+ class SilentHandler(handler):
54
+ def log_message(self, fmt, *args):
55
+ sys.stderr.write(f"[HTTP] {args[0]} {args[1]} {args[2]}\n")
56
+
57
+ try:
58
+ with socketserver.TCPServer((bind, port), SilentHandler) as httpd:
59
+ print(f"Serving {directory} at http://{bind}:{port}")
60
+ print("Press Ctrl+C to stop")
61
+ httpd.serve_forever()
62
+ except OSError as e:
63
+ print(f"Error: {e}", file=sys.stderr)
64
+ sys.exit(1)
65
+ except KeyboardInterrupt:
66
+ print("\nStopped.")
@@ -0,0 +1,81 @@
1
+ #!/usr/bin/env python3
2
+ """json_flatten — Flatten nested JSON to dot-notation key=value pairs.
3
+
4
+ Usage: json_flatten data.json
5
+ json_flatten data.json --sep /
6
+ cat data.json | json_flatten
7
+
8
+ Useful for converting nested JSON to flat key-value format
9
+ for CSV export, env files, or debugging.
10
+ """
11
+
12
+ import json
13
+ import sys
14
+ import os
15
+
16
+ TOOL_META = {
17
+ "name": "json_flatten",
18
+ "func": "main",
19
+ "desc": "Flatten nested JSON to dot-notation key=value pairs",
20
+ }
21
+
22
+ def flatten(obj, parent_key='', sep='.'):
23
+ items = []
24
+ if isinstance(obj, dict):
25
+ for k, v in obj.items():
26
+ new_key = f"{parent_key}{sep}{k}" if parent_key else k
27
+ if isinstance(v, (dict, list)):
28
+ items.extend(flatten(v, new_key, sep=sep))
29
+ else:
30
+ items.append((new_key, v))
31
+ elif isinstance(obj, list):
32
+ for i, v in enumerate(obj):
33
+ new_key = f"{parent_key}{sep}{i}" if parent_key else str(i)
34
+ if isinstance(v, (dict, list)):
35
+ items.extend(flatten(v, new_key, sep=sep))
36
+ else:
37
+ items.append((new_key, v))
38
+ else:
39
+ items.append((parent_key, obj))
40
+ return items
41
+
42
+
43
+ def main():
44
+ args = sys.argv[1:]
45
+ sep = '.'
46
+ files = []
47
+
48
+ i = 0
49
+ while i < len(args):
50
+ if args[i] == '--sep' and i + 1 < len(args):
51
+ sep = args[i + 1]
52
+ i += 2
53
+ elif args[i] in ('-h', '--help'):
54
+ print(__doc__)
55
+ return
56
+ else:
57
+ files.append(args[i])
58
+ i += 1
59
+
60
+ if files:
61
+ data = []
62
+ for f in files:
63
+ if not os.path.exists(f):
64
+ print(f"Error: file not found: {f}", file=sys.stderr)
65
+ sys.exit(1)
66
+ with open(f) as fp:
67
+ data.append(json.load(fp))
68
+ if len(data) == 1:
69
+ data = data[0]
70
+ else:
71
+ data = json.load(sys.stdin)
72
+
73
+ items = flatten(data, sep=sep)
74
+ for key, val in items:
75
+ if val is None:
76
+ val = 'null'
77
+ elif isinstance(val, bool):
78
+ val = str(val).lower()
79
+ elif isinstance(val, (int, float)):
80
+ val = str(val)
81
+ print(f"{key}={val}")
@@ -0,0 +1,106 @@
1
+ #!/usr/bin/env python3
2
+ """pdf_info — Extract PDF metadata (pages, author, title, size, etc.)
3
+
4
+ Usage: pdf_info file.pdf
5
+ pdf_info --json file.pdf
6
+
7
+ Zero-dependency PDF parser (basic metadata from PDF header/objects).
8
+ Full metadata requires PyMuPDF or similar — shows what's available.
9
+ """
10
+
11
+ import os
12
+ import re
13
+ import sys
14
+
15
+ TOOL_META = {
16
+ "name": "pdf_info",
17
+ "func": "main",
18
+ "desc": "Extract PDF metadata — pages, title, author, size",
19
+ }
20
+
21
+ def _scan_objects(data):
22
+ """Scan PDF for key metadata objects."""
23
+ info = {}
24
+ # Find /Info dictionary
25
+ m = re.search(rb'/Info\s+(\d+)\s+(\d+)\s+R', data)
26
+ if m:
27
+ obj_num = int(m.group(1))
28
+ gen_num = int(m.group(2))
29
+ # Find the actual Info object
30
+ pattern = rf'{obj_num}\s+{gen_num}\s+obj.*?endobj'.encode()
31
+ om = re.search(pattern, data, re.DOTALL)
32
+ if om:
33
+ chunk = om.group().decode('latin-1', errors='replace')
34
+ for key in ['Title', 'Author', 'Subject', 'Keywords', 'Creator', 'Producer']:
35
+ m2 = re.search(rf'/{key}\s+\(([^)]*)\)', chunk)
36
+ if m2:
37
+ info[key.lower()] = m2.group(1)
38
+ # Creation/Mod date
39
+ m2 = re.search(r'/CreationDate\s+\(D:([^)]*)\)', chunk)
40
+ if m2:
41
+ info['creation_date'] = m2.group(1)
42
+ m2 = re.search(r'/ModDate\s+\(D:([^)]*)\)', chunk)
43
+ if m2:
44
+ info['mod_date'] = m2.group(1)
45
+ return info
46
+
47
+
48
+ def main():
49
+ args = sys.argv[1:]
50
+ if not args or args[0] in ('-h', '--help'):
51
+ print(__doc__)
52
+ return
53
+
54
+ path = args[0]
55
+ json_mode = '--json' in args or '-j' in args
56
+
57
+ if not os.path.exists(path):
58
+ print(f"Error: file not found: {path}", file=sys.stderr)
59
+ sys.exit(1)
60
+
61
+ size = os.path.getsize(path)
62
+ with open(path, 'rb') as f:
63
+ data = f.read()
64
+
65
+ # Basic info
66
+ result = {
67
+ 'file': os.path.basename(path),
68
+ 'size_bytes': size,
69
+ 'size_kb': round(size / 1024, 1),
70
+ }
71
+
72
+ # PDF version
73
+ m = re.search(rb'%PDF-(\d+\.\d+)', data)
74
+ if m:
75
+ result['pdf_version'] = m.group(1).decode()
76
+
77
+ # Page count (count Pages objects)
78
+ pages = re.findall(rb'/Type\s*/Pages[^}]*/Count\s+(\d+)', data)
79
+ if pages:
80
+ result['pages'] = int(pages[0])
81
+
82
+ # Encrypted?
83
+ result['encrypted'] = '/Encrypt' in data.decode('latin-1', errors='replace')
84
+
85
+ # Metadata from Info dict
86
+ info = _scan_objects(data)
87
+ result.update(info)
88
+
89
+ if json_mode:
90
+ import json
91
+ print(json.dumps(result, indent=2))
92
+ return
93
+
94
+ print(f" File: {result['file']}")
95
+ print(f" Size: {result['size_kb']} KB ({result['size_bytes']} bytes)")
96
+ if 'pdf_version' in result:
97
+ print(f" PDF: {result['pdf_version']}")
98
+ if 'pages' in result:
99
+ print(f" Pages: {result['pages']}")
100
+ print(f" Encrypted: {result['encrypted']}")
101
+ for key in ('title', 'author', 'subject', 'creator', 'producer'):
102
+ if key in result:
103
+ print(f" {key.title()}: {result[key]}")
104
+ for key in ('creation_date', 'mod_date'):
105
+ if key in result:
106
+ print(f" {key.replace('_', ' ').title()}: {result[key]}")
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: evolver-tools
3
- Version: 20.0.0
4
- Summary: 186 CLI tools + 9 flagship projects — one pip install
3
+ Version: 21.0.0
4
+ Summary: 191 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
@@ -36,6 +36,7 @@ src/evolver_tools/vendor/crontab_helper.py
36
36
  src/evolver_tools/vendor/crypto_box.py
37
37
  src/evolver_tools/vendor/crypto_price.py
38
38
  src/evolver_tools/vendor/csv2json.py
39
+ src/evolver_tools/vendor/csv_merge.py
39
40
  src/evolver_tools/vendor/csv_validate.py
40
41
  src/evolver_tools/vendor/csv_view.py
41
42
  src/evolver_tools/vendor/db_mate.py
@@ -44,6 +45,7 @@ src/evolver_tools/vendor/dep_graph.py
44
45
  src/evolver_tools/vendor/dev_dashboard.py
45
46
  src/evolver_tools/vendor/dice_roll.py
46
47
  src/evolver_tools/vendor/diff_csv.py
48
+ src/evolver_tools/vendor/diff_files.py
47
49
  src/evolver_tools/vendor/disk_cleanup.py
48
50
  src/evolver_tools/vendor/dns_lookup.py
49
51
  src/evolver_tools/vendor/docker_helper.py
@@ -72,12 +74,14 @@ src/evolver_tools/vendor/hexdump.py
72
74
  src/evolver_tools/vendor/html2markdown.py
73
75
  src/evolver_tools/vendor/html2md.py
74
76
  src/evolver_tools/vendor/http_headers.py
77
+ src/evolver_tools/vendor/http_server.py
75
78
  src/evolver_tools/vendor/image_meta.py
76
79
  src/evolver_tools/vendor/ini2json.py
77
80
  src/evolver_tools/vendor/ip_location.py
78
81
  src/evolver_tools/vendor/join.py
79
82
  src/evolver_tools/vendor/joke.py
80
83
  src/evolver_tools/vendor/json2ini.py
84
+ src/evolver_tools/vendor/json_flatten.py
81
85
  src/evolver_tools/vendor/json_schema_validate.py
82
86
  src/evolver_tools/vendor/key_value_store.py
83
87
  src/evolver_tools/vendor/license.py
@@ -96,6 +100,7 @@ src/evolver_tools/vendor/nl.py
96
100
  src/evolver_tools/vendor/note_taker.py
97
101
  src/evolver_tools/vendor/otp_gen.py
98
102
  src/evolver_tools/vendor/password_strength.py
103
+ src/evolver_tools/vendor/pdf_info.py
99
104
  src/evolver_tools/vendor/pdf_text.py
100
105
  src/evolver_tools/vendor/pipe_viewer.py
101
106
  src/evolver_tools/vendor/pomodoro.py
File without changes
File without changes
File without changes