evolver-tools 31.0.0__tar.gz → 32.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 (304) hide show
  1. {evolver_tools-31.0.0/src/evolver_tools.egg-info → evolver_tools-32.0.0}/PKG-INFO +5 -5
  2. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/README.md +3 -3
  3. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/pyproject.toml +2 -2
  4. evolver_tools-32.0.0/src/evolver_tools/vendor/csv_head.py +234 -0
  5. evolver_tools-32.0.0/src/evolver_tools/vendor/csv_sort.py +125 -0
  6. evolver_tools-32.0.0/src/evolver_tools/vendor/file_type.py +297 -0
  7. evolver_tools-32.0.0/src/evolver_tools/vendor/json_keys.py +160 -0
  8. evolver_tools-32.0.0/src/evolver_tools/vendor/link_check.py +219 -0
  9. {evolver_tools-31.0.0 → evolver_tools-32.0.0/src/evolver_tools.egg-info}/PKG-INFO +5 -5
  10. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools.egg-info/SOURCES.txt +5 -1
  11. evolver_tools-31.0.0/src/evolver_tools/vendor/_test_find_empty.py +0 -1
  12. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/LICENSE +0 -0
  13. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/setup.cfg +0 -0
  14. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/__init__.py +0 -0
  15. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/__main__.py +0 -0
  16. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/autoreg.py +0 -0
  17. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/cli.py +0 -0
  18. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/__init__.py +0 -0
  19. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/agent_b_tool.py +0 -0
  20. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/ansi_strip.py +0 -0
  21. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/api_tester.py +0 -0
  22. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/ascii_banner.py +0 -0
  23. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/ascii_gen.py +0 -0
  24. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/audit_log.py +0 -0
  25. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/b64/__init__.py +0 -0
  26. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/b64/b64.py +0 -0
  27. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/backup.py +0 -0
  28. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/banner/__init__.py +0 -0
  29. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/banner/banner.py +0 -0
  30. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/base32.py +0 -0
  31. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/base58.py +0 -0
  32. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/bookmark.py +0 -0
  33. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/cal_tool/__init__.py +0 -0
  34. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/cal_tool/cli.py +0 -0
  35. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/calendar_cli.py +0 -0
  36. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/case_convert.py +0 -0
  37. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/cert_check.py +0 -0
  38. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/cert_info.py +0 -0
  39. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/changelog_gen/__init__.py +0 -0
  40. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/changelog_gen/changelog_gen.py +0 -0
  41. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/changelog_gen.py +0 -0
  42. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/chart_cli/__init__.py +0 -0
  43. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/chart_cli/__main__.py +0 -0
  44. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/checksum_dir.py +0 -0
  45. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/clipboard/__init__.py +0 -0
  46. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/clipboard/clipboard.py +0 -0
  47. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/code_auditor.py +0 -0
  48. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/code_review.py +0 -0
  49. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/code_stats.py +0 -0
  50. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/colorize.py +0 -0
  51. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/colors/__init__.py +0 -0
  52. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/colors/__main__.py +0 -0
  53. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/config_validator.py +0 -0
  54. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/config_vault.py +0 -0
  55. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/cowsay.py +0 -0
  56. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/crc_check.py +0 -0
  57. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/cron/__init__.py +0 -0
  58. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/cron/__main__.py +0 -0
  59. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/cron_pretty.py +0 -0
  60. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/crontab_helper.py +0 -0
  61. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/crypto_box.py +0 -0
  62. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/crypto_price.py +0 -0
  63. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/csv2json.py +0 -0
  64. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/csv_dedup.py +0 -0
  65. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/csv_filter.py +0 -0
  66. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/csv_merge.py +0 -0
  67. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/csv_slice.py +0 -0
  68. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/csv_stats/__init__.py +0 -0
  69. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/csv_stats/__main__.py +0 -0
  70. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/csv_stats/analyzer.py +0 -0
  71. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/csv_stats/cli.py +0 -0
  72. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/csv_to_table.py +0 -0
  73. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/csv_validate.py +0 -0
  74. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/csv_view.py +0 -0
  75. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/date_diff.py +0 -0
  76. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/db_mate.py +0 -0
  77. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/db_schema.py +0 -0
  78. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/dedup_files.py +0 -0
  79. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/dep_graph.py +0 -0
  80. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/dev_dashboard.py +0 -0
  81. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/dice_roll.py +0 -0
  82. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/diff_csv.py +0 -0
  83. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/diff_files.py +0 -0
  84. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/diff_tool/__init__.py +0 -0
  85. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/diff_tool/__main__.py +0 -0
  86. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/dirsize/__init__.py +0 -0
  87. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/disk_cleanup.py +0 -0
  88. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/disk_usage/__init__.py +0 -0
  89. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/disk_usage/disk_usage.py +0 -0
  90. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/dns_lookup.py +0 -0
  91. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/docker_helper.py +0 -0
  92. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/dt_convert.py +0 -0
  93. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/env_diff.py +0 -0
  94. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/env_manager.py +0 -0
  95. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/env_sorter.py +0 -0
  96. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/env_template.py +0 -0
  97. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/envcheck/__init__.py +0 -0
  98. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/epoch.py +0 -0
  99. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/excel2csv.py +0 -0
  100. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/factor.py +0 -0
  101. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/ff/__init__.py +0 -0
  102. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/ff/__main__.py +0 -0
  103. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/figlet_cli.py +0 -0
  104. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/figlet_tool.py +0 -0
  105. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/file_encrypt.py +0 -0
  106. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/file_find.py +0 -0
  107. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/file_joiner.py +0 -0
  108. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/file_patch.py +0 -0
  109. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/file_splitter.py +0 -0
  110. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/file_watch.py +0 -0
  111. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/find_dups/__init__.py +0 -0
  112. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/find_dups/cli.py +0 -0
  113. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/find_empty.py +0 -0
  114. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/firewall_rule.py +0 -0
  115. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/fmt/__init__.py +0 -0
  116. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/fmt/fmt.py +0 -0
  117. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/fold.py +0 -0
  118. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/geo_ip.py +0 -0
  119. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/git_branch_cleaner.py +0 -0
  120. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/git_log_pretty.py +0 -0
  121. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/git_stats.py +0 -0
  122. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/gzip_cli.py +0 -0
  123. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/hash_check.py +0 -0
  124. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/hash_file.py +0 -0
  125. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/hashsum/__init__.py +0 -0
  126. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/hashsum/__main__.py +0 -0
  127. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/hex_tool.py +0 -0
  128. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/hexdump.py +0 -0
  129. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/html2markdown.py +0 -0
  130. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/html2md.py +0 -0
  131. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/http_headers.py +0 -0
  132. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/http_live/__init__.py +0 -0
  133. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/http_live/__main__.py +0 -0
  134. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/http_server.py +0 -0
  135. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/http_status.py +0 -0
  136. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/image_meta.py +0 -0
  137. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/ini2json.py +0 -0
  138. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/ini_parser/__init__.py +0 -0
  139. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/ini_parser/ini_parser.py +0 -0
  140. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/ip_info.py +0 -0
  141. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/ip_location.py +0 -0
  142. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/ipcalc/__init__.py +0 -0
  143. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/ipcalc/__main__.py +0 -0
  144. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/ipinfo/__init__.py +0 -0
  145. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/ipinfo/__main__.py +0 -0
  146. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/join.py +0 -0
  147. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/joke.py +0 -0
  148. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/jq_lite/__init__.py +0 -0
  149. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/jq_lite/__main__.py +0 -0
  150. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/json2csv/__init__.py +0 -0
  151. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/json2csv/__main__.py +0 -0
  152. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/json2ini.py +0 -0
  153. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/json_diff.py +0 -0
  154. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/json_flatten.py +0 -0
  155. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/json_merge.py +0 -0
  156. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/json_path.py +0 -0
  157. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/json_pretty/__init__.py +0 -0
  158. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/json_pretty/json_pretty.py +0 -0
  159. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/json_schema_validate.py +0 -0
  160. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/json_sort.py +0 -0
  161. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/json_to_table.py +0 -0
  162. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/json_to_yaml.py +0 -0
  163. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/jsonql/__init__.py +0 -0
  164. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/jsonql/__main__.py +0 -0
  165. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/jwt_decode.py +0 -0
  166. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/key_value_store.py +0 -0
  167. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/license.py +0 -0
  168. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/license_cli/__init__.py +0 -0
  169. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/license_cli/__main__.py +0 -0
  170. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/license_cli/cli.py +0 -0
  171. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/log_analyzer.py +0 -0
  172. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/log_hawk.py +0 -0
  173. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/log_tail.py +0 -0
  174. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/mac_address.py +0 -0
  175. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/macrogen.py +0 -0
  176. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/markdown_check/__init__.py +0 -0
  177. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/markdown_lint.py +0 -0
  178. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/markdown_preview.py +0 -0
  179. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/markdown_to_html.py +0 -0
  180. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/markdown_toc.py +0 -0
  181. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/math_eval.py +0 -0
  182. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/media_studio.py +0 -0
  183. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/morse.py +0 -0
  184. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/nb/__init__.py +0 -0
  185. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/nb/__main__.py +0 -0
  186. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/net_analyzer.py +0 -0
  187. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/net_speed.py +0 -0
  188. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/network_scan.py +0 -0
  189. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/nl.py +0 -0
  190. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/note_taker.py +0 -0
  191. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/otp_gen.py +0 -0
  192. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/passgen/__init__.py +0 -0
  193. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/password_strength.py +0 -0
  194. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/pdf_info.py +0 -0
  195. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/pdf_text.py +0 -0
  196. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/pipe_viewer.py +0 -0
  197. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/pomodoro.py +0 -0
  198. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/port_scan.py +0 -0
  199. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/portcheck/__init__.py +0 -0
  200. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/portcheck/__main__.py +0 -0
  201. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/pr_tool/__init__.py +0 -0
  202. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/pr_tool/pr_tool.py +0 -0
  203. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/process_kill.py +0 -0
  204. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/progress_bar.py +0 -0
  205. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/project_doctor/__init__.py +0 -0
  206. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/project_doctor/__main__.py +0 -0
  207. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/qc_calc.py +0 -0
  208. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/qc_report.py +0 -0
  209. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/qc_sample.py +0 -0
  210. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/qr_cli.py +0 -0
  211. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/qrcode.py +0 -0
  212. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/quote.py +0 -0
  213. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/quote_tool/__init__.py +0 -0
  214. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/quote_tool/quote.py +0 -0
  215. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/rainbow.py +0 -0
  216. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/random.py +0 -0
  217. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/random_cli.py +0 -0
  218. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/random_string.py +0 -0
  219. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/reminder.py +0 -0
  220. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/ren/__init__.py +0 -0
  221. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/ren/__main__.py +0 -0
  222. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/replace_text.py +0 -0
  223. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/restore.py +0 -0
  224. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/rot13.py +0 -0
  225. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/route_trace.py +0 -0
  226. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/scan_open_ports.py +0 -0
  227. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/scan_ports.py +0 -0
  228. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/screen_recorder.py +0 -0
  229. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/screenshot_cli.py +0 -0
  230. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/search_files.py +0 -0
  231. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/search_history.py +0 -0
  232. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/secret_scanner.py +0 -0
  233. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/seq.py +0 -0
  234. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/service_check.py +0 -0
  235. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/shuffle.py +0 -0
  236. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/siege_lite/__init__.py +0 -0
  237. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/siege_lite/__main__.py +0 -0
  238. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/slugify.py +0 -0
  239. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/smellfinder/__init__.py +0 -0
  240. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/smellfinder/__main__.py +0 -0
  241. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/sort/__init__.py +0 -0
  242. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/sort/sort.py +0 -0
  243. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/spinner.py +0 -0
  244. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/split.py +0 -0
  245. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/split_tool/__init__.py +0 -0
  246. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/split_tool/split.py +0 -0
  247. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/sql2csv.py +0 -0
  248. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/sqlite_cli/__init__.py +0 -0
  249. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/sqlite_cli/__main__.py +0 -0
  250. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/ssh_key_gen.py +0 -0
  251. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/ssl_check.py +0 -0
  252. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/stopwatch.py +0 -0
  253. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/subnet.py +0 -0
  254. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/sysmon/__init__.py +0 -0
  255. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/sysmon/__main__.py +0 -0
  256. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/sysmon_pro.py +0 -0
  257. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/system_info.py +0 -0
  258. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/temp_cleaner.py +0 -0
  259. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/template.py +0 -0
  260. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/text_dedent.py +0 -0
  261. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/text_stats.py +0 -0
  262. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/text_wrap.py +0 -0
  263. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/time_duration.py +0 -0
  264. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/timeout.py +0 -0
  265. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/timer/__init__.py +0 -0
  266. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/timer_pro/__init__.py +0 -0
  267. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/timer_pro/timer_pro.py +0 -0
  268. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/timer_pro.py +0 -0
  269. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/todo_cli.py +0 -0
  270. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/toml2json.py +0 -0
  271. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/tr.py +0 -0
  272. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/tree.py +0 -0
  273. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/treedir/__init__.py +0 -0
  274. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/treedir/__main__.py +0 -0
  275. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/tsv2csv.py +0 -0
  276. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/uniq_tool/__init__.py +0 -0
  277. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/uniq_tool/uniq.py +0 -0
  278. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/unit_convert.py +0 -0
  279. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/uri_encode.py +0 -0
  280. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/url_parser.py +0 -0
  281. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/urlparse_tool/__init__.py +0 -0
  282. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/urlparse_tool/cli.py +0 -0
  283. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/uuid_gen.py +0 -0
  284. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/uuid_tool/__init__.py +0 -0
  285. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/uuid_tool/__main__.py +0 -0
  286. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/watch.py +0 -0
  287. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/weather_cli.py +0 -0
  288. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/web_download.py +0 -0
  289. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/web_summary/__init__.py +0 -0
  290. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/web_summary/__main__.py +0 -0
  291. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/whois_lookup.py +0 -0
  292. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/wordcount/__init__.py +0 -0
  293. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/wordcount/__main__.py +0 -0
  294. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/world_clock.py +0 -0
  295. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/xml2json.py +0 -0
  296. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/xml_format.py +0 -0
  297. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/yaml2json/__init__.py +0 -0
  298. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/yaml2json/yaml2json.py +0 -0
  299. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/yaml2toml.py +0 -0
  300. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/yaml_validate.py +0 -0
  301. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools/vendor/yes.py +0 -0
  302. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools.egg-info/dependency_links.txt +0 -0
  303. {evolver_tools-31.0.0 → evolver_tools-32.0.0}/src/evolver_tools.egg-info/entry_points.txt +0 -0
  304. {evolver_tools-31.0.0 → evolver_tools-32.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: 31.0.0
4
- Summary: 238 CLI tools + 9 flagship projects — one pip install
3
+ Version: 32.0.0
4
+ Summary: 234 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
@@ -22,11 +22,11 @@ Dynamic: license-file
22
22
 
23
23
  # EVOLVER Tools
24
24
 
25
- **233+ CLI tools + 9 flagship projects — one `pip install`.**
25
+ **238 CLI tools + 9 flagship projects — one `pip install`.**
26
26
 
27
- Zero-dependency (230/233), cross-platform, production-ready. Version **30.0.0**.
27
+ Zero-dependency (235/238), cross-platform, production-ready. Version **31.0.0**.
28
28
  Systems ops, data processing, text manipulation, security, dev tooling, and creative utilities.
29
- All in a single install — not 233 separate packages.
29
+ All in a single install — not 238 separate packages.
30
30
 
31
31
  ## Quick Start
32
32
 
@@ -1,10 +1,10 @@
1
1
  # EVOLVER Tools
2
2
 
3
- **233+ CLI tools + 9 flagship projects — one `pip install`.**
3
+ **238 CLI tools + 9 flagship projects — one `pip install`.**
4
4
 
5
- Zero-dependency (230/233), cross-platform, production-ready. Version **30.0.0**.
5
+ Zero-dependency (235/238), cross-platform, production-ready. Version **31.0.0**.
6
6
  Systems ops, data processing, text manipulation, security, dev tooling, and creative utilities.
7
- All in a single install — not 233 separate packages.
7
+ All in a single install — not 238 separate packages.
8
8
 
9
9
  ## Quick Start
10
10
 
@@ -4,8 +4,8 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "evolver-tools"
7
- version = "31.0.0"
8
- description = "238 CLI tools + 9 flagship projects — one pip install"
7
+ version = "32.0.0"
8
+ description = "234 CLI tools + 9 flagship projects — one pip install"
9
9
  readme = "README.md"
10
10
  license = "MIT"
11
11
  requires-python = ">=3.8"
@@ -0,0 +1,234 @@
1
+ #!/usr/bin/env python3
2
+ """csv-head — Display first N rows of a CSV file.
3
+
4
+ Usage: csv-head data.csv
5
+ csv-head data.csv -n 20
6
+ csv-head data.csv --columns name,email
7
+ csv-head data.csv --format table
8
+ cat data.csv | csv-head -n 5
9
+
10
+ Options:
11
+ -n, --lines N Number of rows to show (default: 10)
12
+ -c, --columns NAMES Comma-separated column names to show
13
+ -f, --format FMT Output format: csv (default) or table
14
+ --no-header Input has no header row
15
+ -h, --help Show this help message
16
+ """
17
+
18
+ import csv
19
+ import io
20
+ import os
21
+ import sys
22
+
23
+ TOOL_META = {
24
+ "name": "csv-head",
25
+ "func": "main",
26
+ "desc": "Display first N rows of a CSV file",
27
+ }
28
+
29
+
30
+ def read_input(filepath=None):
31
+ """Read CSV data from file or stdin. Returns (content, source_name)."""
32
+ if filepath:
33
+ if not os.path.isfile(filepath):
34
+ print(f"Error: file not found: {filepath}", file=sys.stderr)
35
+ sys.exit(1)
36
+ try:
37
+ with open(filepath, "r", encoding="utf-8", errors="replace") as f:
38
+ content = f.read()
39
+ except Exception as e:
40
+ print(f"Error reading file: {e}", file=sys.stderr)
41
+ sys.exit(1)
42
+ return content, filepath
43
+ else:
44
+ try:
45
+ content = sys.stdin.read()
46
+ except KeyboardInterrupt:
47
+ sys.exit(1)
48
+ if not content.strip():
49
+ print("(no input)", file=sys.stderr)
50
+ sys.exit(1)
51
+ return content, "<stdin>"
52
+
53
+
54
+ def parse_csv(content):
55
+ """Parse CSV content into list of rows using csv.reader."""
56
+ reader = csv.reader(io.StringIO(content))
57
+ return [row for row in reader]
58
+
59
+
60
+ def filter_columns(rows, column_names, has_header):
61
+ """Filter rows to only include specified columns.
62
+
63
+ column_names is a list of column names (if has_header) or column indices.
64
+ """
65
+ if not rows or not column_names:
66
+ return rows
67
+
68
+ if has_header:
69
+ header = rows[0]
70
+ indices = []
71
+ for name in column_names:
72
+ name = name.strip()
73
+ found = False
74
+ for i, h in enumerate(header):
75
+ if h.strip() == name:
76
+ indices.append(i)
77
+ found = True
78
+ break
79
+ if not found:
80
+ print(f"Error: column '{name}' not found in header", file=sys.stderr)
81
+ sys.exit(1)
82
+ else:
83
+ # No header — column_names are 1-based indices
84
+ indices = []
85
+ for name in column_names:
86
+ name = name.strip()
87
+ try:
88
+ idx = int(name) - 1
89
+ if idx < 0:
90
+ print(f"Error: column index must be >= 1, got {name}", file=sys.stderr)
91
+ sys.exit(1)
92
+ indices.append(idx)
93
+ except ValueError:
94
+ print(f"Error: without --no-header, column names must be integers, got '{name}'", file=sys.stderr)
95
+ sys.exit(1)
96
+
97
+ filtered = []
98
+ for row in rows:
99
+ new_row = [row[i] if i < len(row) else "" for i in indices]
100
+ filtered.append(new_row)
101
+
102
+ return filtered
103
+
104
+
105
+ def format_csv(rows):
106
+ """Output rows as CSV."""
107
+ writer = csv.writer(sys.stdout)
108
+ for row in rows:
109
+ writer.writerow(row)
110
+
111
+
112
+ def format_table(rows):
113
+ """Output rows as an aligned table."""
114
+ if not rows:
115
+ return
116
+
117
+ num_cols = max(len(row) for row in rows) if rows else 0
118
+ if num_cols == 0:
119
+ return
120
+
121
+ col_widths = [0] * num_cols
122
+ for row in rows:
123
+ for i, cell in enumerate(row):
124
+ if i < num_cols:
125
+ col_widths[i] = max(col_widths[i], len(cell))
126
+
127
+ for row in rows:
128
+ parts = []
129
+ for i in range(num_cols):
130
+ val = row[i] if i < len(row) else ""
131
+ parts.append(val.ljust(col_widths[i]))
132
+ print(" ".join(parts))
133
+
134
+
135
+ def print_usage():
136
+ """Print usage information."""
137
+ print(__doc__.strip())
138
+
139
+
140
+ def main():
141
+ args = sys.argv[1:]
142
+
143
+ filepath = None
144
+ lines = 10
145
+ column_names = None
146
+ output_format = "csv"
147
+ has_header = True
148
+
149
+ i = 0
150
+ while i < len(args):
151
+ arg = args[i]
152
+ if arg in ("-h", "--help"):
153
+ print_usage()
154
+ return
155
+ elif arg in ("-n", "--lines") and i + 1 < len(args):
156
+ try:
157
+ lines = int(args[i + 1])
158
+ if lines < 0:
159
+ print("Error: --lines/-n requires a non-negative integer", file=sys.stderr)
160
+ sys.exit(1)
161
+ except ValueError:
162
+ print("Error: --lines/-n requires an integer", file=sys.stderr)
163
+ sys.exit(1)
164
+ i += 2
165
+ elif arg in ("-c", "--columns") and i + 1 < len(args):
166
+ column_names = [c.strip() for c in args[i + 1].split(",")]
167
+ i += 2
168
+ elif arg in ("-f", "--format") and i + 1 < len(args):
169
+ fmt = args[i + 1].lower()
170
+ if fmt not in ("csv", "table"):
171
+ print(f"Error: --format/-f must be 'csv' or 'table', got '{fmt}'", file=sys.stderr)
172
+ sys.exit(1)
173
+ output_format = fmt
174
+ i += 2
175
+ elif arg == "--no-header":
176
+ has_header = False
177
+ i += 1
178
+ elif arg.startswith("-"):
179
+ print(f"Error: unknown option '{arg}'. Use --help for usage.", file=sys.stderr)
180
+ sys.exit(1)
181
+ else:
182
+ if filepath is not None:
183
+ print(f"Error: unexpected argument '{arg}'. Only one file path allowed.", file=sys.stderr)
184
+ sys.exit(1)
185
+ filepath = arg
186
+ i += 1
187
+
188
+ # Read input
189
+ content, source_name = read_input(filepath)
190
+
191
+ if not content.strip():
192
+ print("(empty file)")
193
+ sys.exit(0)
194
+
195
+ # Parse CSV
196
+ rows = parse_csv(content)
197
+
198
+ if not rows:
199
+ print("(no data)")
200
+ sys.exit(0)
201
+
202
+ total_rows = len(rows)
203
+
204
+ # Determine data rows based on header
205
+ if has_header and total_rows > 0:
206
+ header = rows[0]
207
+ data_rows = rows[1:]
208
+ else:
209
+ header = None
210
+ data_rows = rows
211
+
212
+ # Slice first N data rows
213
+ if lines > 0 and lines < len(data_rows):
214
+ data_rows = data_rows[:lines]
215
+
216
+ # Reconstruct rows with optional header
217
+ if header is not None:
218
+ display_rows = [header] + data_rows
219
+ else:
220
+ display_rows = data_rows
221
+
222
+ # Filter columns if requested
223
+ if column_names:
224
+ display_rows = filter_columns(display_rows, column_names, has_header)
225
+
226
+ # Output
227
+ if output_format == "csv":
228
+ format_csv(display_rows)
229
+ else:
230
+ format_table(display_rows)
231
+
232
+
233
+ if __name__ == "__main__":
234
+ main()
@@ -0,0 +1,125 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ csv-sort — Sort CSV files by column.
4
+
5
+ Usage:
6
+ csv-sort [--column COL] [--reverse] [--numeric] [FILE]
7
+
8
+ Arguments:
9
+ FILE Input CSV file (reads from stdin if omitted)
10
+
11
+ Options:
12
+ -c, --column COL Column name or 1-based index to sort by (default: first column)
13
+ -r, --reverse Sort in descending order
14
+ -n, --numeric Sort values as numbers instead of text
15
+ -h, --help Show this help message and exit
16
+
17
+ Examples:
18
+ csv-sort data.csv
19
+ csv-sort -c 2 -r data.csv
20
+ csv-sort -c "name" -n < data.csv
21
+ cat data.csv | csv-sort -c "age" -n -r
22
+ """
23
+
24
+ import csv
25
+ import sys
26
+
27
+
28
+ def main():
29
+ args = sys.argv[1:]
30
+
31
+ # Parse help
32
+ if '-h' in args or '--help' in args:
33
+ print((__doc__ or '').strip())
34
+ return
35
+
36
+ # Parse --column / -c
37
+ column = None
38
+ if '--column' in args:
39
+ idx = args.index('--column')
40
+ if idx + 1 < len(args):
41
+ column = args[idx + 1]
42
+ args = args[:idx] + args[idx + 2:]
43
+ elif '-c' in args:
44
+ idx = args.index('-c')
45
+ if idx + 1 < len(args):
46
+ column = args[idx + 1]
47
+ args = args[:idx] + args[idx + 2:]
48
+
49
+ # Parse flags
50
+ reverse = '--reverse' in args or '-r' in args
51
+ numeric = '--numeric' in args or '-n' in args
52
+ args = [a for a in args if a not in ('--reverse', '-r', '--numeric', '-n')]
53
+
54
+ # Remaining positional arg is file path (optional)
55
+ filepath = args[0] if args else None
56
+
57
+ try:
58
+ if filepath:
59
+ with open(filepath, newline='') as f:
60
+ reader = csv.reader(f)
61
+ rows = list(reader)
62
+ else:
63
+ reader = csv.reader(sys.stdin)
64
+ rows = list(reader)
65
+ except Exception as e:
66
+ print(f"Error: {e}", file=sys.stderr)
67
+ sys.exit(1)
68
+
69
+ if not rows:
70
+ sys.exit(0)
71
+
72
+ # Separate header from data
73
+ header = rows[0]
74
+ data = rows[1:]
75
+
76
+ # Determine column index
77
+ if column is None:
78
+ col_idx = 0
79
+ else:
80
+ try:
81
+ col_idx = int(column) - 1 # 1-based to 0-based
82
+ except ValueError:
83
+ # Column is a name — find it in the header
84
+ try:
85
+ col_idx = header.index(column)
86
+ except ValueError:
87
+ print(f"Error: column '{column}' not found in header: {header}", file=sys.stderr)
88
+ sys.exit(1)
89
+
90
+ if col_idx < 0:
91
+ print(f"Error: column index must be 1 or greater", file=sys.stderr)
92
+ sys.exit(1)
93
+
94
+ # Sort
95
+ try:
96
+ if numeric:
97
+ data.sort(key=lambda row: _safe_num(row[col_idx]), reverse=reverse)
98
+ else:
99
+ data.sort(key=lambda row: row[col_idx] if col_idx < len(row) else '', reverse=reverse)
100
+ except IndexError:
101
+ print(f"Error: column index {col_idx + 1} exceeds row width", file=sys.stderr)
102
+ sys.exit(1)
103
+ except Exception as e:
104
+ print(f"Error during sort: {e}", file=sys.stderr)
105
+ sys.exit(1)
106
+
107
+ # Write output
108
+ writer = csv.writer(sys.stdout)
109
+ writer.writerow(header)
110
+ writer.writerows(data)
111
+
112
+
113
+ def _safe_num(val):
114
+ """Convert a string to float for numeric sorting, with fallback."""
115
+ try:
116
+ return float(val)
117
+ except (ValueError, TypeError):
118
+ return float('inf')
119
+
120
+
121
+ TOOL_META = {"name": "csv-sort", "func": "main", "desc": "Sort CSV files by column"}
122
+
123
+
124
+ if __name__ == '__main__':
125
+ main()