tab-cli 0.2.0__tar.gz → 0.2.1__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 (127) hide show
  1. {tab_cli-0.2.0 → tab_cli-0.2.1}/PKG-INFO +1 -1
  2. {tab_cli-0.2.0 → tab_cli-0.2.1}/docs/cli-ref.md +2 -2
  3. tab_cli-0.2.1/docs/gen_assets.sh +3 -0
  4. {tab_cli-0.2.0 → tab_cli-0.2.1}/pyproject.toml +1 -1
  5. {tab_cli-0.2.0 → tab_cli-0.2.1}/src/tab_cli/cli.py +34 -14
  6. {tab_cli-0.2.0 → tab_cli-0.2.1}/src/tab_cli/config.py +7 -5
  7. {tab_cli-0.2.0 → tab_cli-0.2.1}/tests/test_config.py +58 -26
  8. tab_cli-0.2.0/docs/gen_assets.sh +0 -3
  9. {tab_cli-0.2.0 → tab_cli-0.2.1}/.gitignore +0 -0
  10. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/.gitignore +0 -0
  11. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/index/op_links/00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +0 -0
  12. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/index/op_links/282ad8cf3324b2679a7d460c0fc324adfa21dcfad2f197ac6991b98ec91f98495bb3ddb2cba36ce5dfa28a52063a373bb03f5d2e34f6e0c7b6b81b3046a4d7d0 +0 -0
  13. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/index/op_links/891d7ed26f62b0f8757b081e9d76840636877f1613ee17b7695fe2ee8640258c56e01291934e3797728bc2300a1b5f41e3f3ef81ab532c0e5ab475bb9b6f097a +0 -0
  14. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/index/op_links/8926397375b8328137652c18cd4371808b214cb26864d77dd33c8eea895e10e62c297064c3d4c703d58ee11dee81bbf9851525e3a0c33151f54c164b8a4343b0 +0 -0
  15. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/index/op_links/89d29d938e64b1295e138faedfa5df6f6729a67e5ba8e0c3fdd1c9266e0f59a4bc35b8a21e14225072317879af3323fa0457e01d9b08608770bc23957feec6c0 +0 -0
  16. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/index/op_links/95fc2854c0fa2528b03e2bcabc7612f56f0bcb3d6f54a06293e21d1887885a449907b5b320a1a94bac712bf56fdad0a4184b17047c1fc179dfa83acab3f70d21 +0 -0
  17. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/index/op_links/9a58ceae46de4649375b6b880b8500c85d34c8e9bc650dc4c993afb2fa8d45c4180331821c6226a0fb1475b04a0b9a849502647ef9c4dcac74769eb501c885fa +0 -0
  18. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/index/op_links/a19ae062208aa20b7310705af3d26ef53095a9dabfad080883cc7a32e98687063179db95cb2c71ef9064801c59fa46d261f172d83e83f96a39c274387b59dca4 +0 -0
  19. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/index/op_links/d1169a8d10067493e42752c2a7615ff27f55bd90c38b91feef918958e29a2239ee289a0cde8385441d1f0fe9af1fb634fa6d56438b9f33ec382e81fa59d70b54 +0 -0
  20. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/index/op_links/e171e5c6039c050c2368584a537d36df221b1f9f23d285c0399b95b14608d67006229823e6831bff7d8b0c2f9e86ebaec9c6811461119195f430ade055073fed +0 -0
  21. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/index/op_links/ee118dd19aac4e1cb354f83a37dadca70bc5f086cc8d36cd0059b222bf8c7250824401ff681518d0120f8db1f96f0025c464dcfc3b1ee28777e8c76325760134 +0 -0
  22. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/index/operations/00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +0 -0
  23. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/index/operations/282ad8cf3324b2679a7d460c0fc324adfa21dcfad2f197ac6991b98ec91f98495bb3ddb2cba36ce5dfa28a52063a373bb03f5d2e34f6e0c7b6b81b3046a4d7d0 +0 -0
  24. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/index/operations/891d7ed26f62b0f8757b081e9d76840636877f1613ee17b7695fe2ee8640258c56e01291934e3797728bc2300a1b5f41e3f3ef81ab532c0e5ab475bb9b6f097a +0 -0
  25. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/index/operations/8926397375b8328137652c18cd4371808b214cb26864d77dd33c8eea895e10e62c297064c3d4c703d58ee11dee81bbf9851525e3a0c33151f54c164b8a4343b0 +0 -0
  26. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/index/operations/89d29d938e64b1295e138faedfa5df6f6729a67e5ba8e0c3fdd1c9266e0f59a4bc35b8a21e14225072317879af3323fa0457e01d9b08608770bc23957feec6c0 +0 -0
  27. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/index/operations/95fc2854c0fa2528b03e2bcabc7612f56f0bcb3d6f54a06293e21d1887885a449907b5b320a1a94bac712bf56fdad0a4184b17047c1fc179dfa83acab3f70d21 +0 -0
  28. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/index/operations/9a58ceae46de4649375b6b880b8500c85d34c8e9bc650dc4c993afb2fa8d45c4180331821c6226a0fb1475b04a0b9a849502647ef9c4dcac74769eb501c885fa +0 -0
  29. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/index/operations/a19ae062208aa20b7310705af3d26ef53095a9dabfad080883cc7a32e98687063179db95cb2c71ef9064801c59fa46d261f172d83e83f96a39c274387b59dca4 +0 -0
  30. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/index/operations/d1169a8d10067493e42752c2a7615ff27f55bd90c38b91feef918958e29a2239ee289a0cde8385441d1f0fe9af1fb634fa6d56438b9f33ec382e81fa59d70b54 +0 -0
  31. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/index/operations/e171e5c6039c050c2368584a537d36df221b1f9f23d285c0399b95b14608d67006229823e6831bff7d8b0c2f9e86ebaec9c6811461119195f430ade055073fed +0 -0
  32. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/index/operations/ee118dd19aac4e1cb354f83a37dadca70bc5f086cc8d36cd0059b222bf8c7250824401ff681518d0120f8db1f96f0025c464dcfc3b1ee28777e8c76325760134 +0 -0
  33. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/index/segments/1029dd1c1f4430d8a667a0e48d0b817652c7ddca6f5ff56cac1755e5bb0c1cb7586935941c9b36f26cab05c0effe6154d073bd1dffbe37f22fed0a6e7d79201f +0 -0
  34. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/index/segments/3228b9bef9d8374b5532b40df2da8be3bfc86de713bdad7fe620977ffa7c56db83928678caa792bf0d328db607028e045a9e41423ef7501e5b550651c3815ffe +0 -0
  35. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/index/segments/424c9a53f5458b328d77ed6a943dc35662e949befa8725cfc7eead01a270417c8d07c1001b11623a088da8d2c9c34a41573314fa2394643147e4027e8a96a605 +0 -0
  36. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/index/segments/44107e81054aa5544b36eab8d811908a559b4d9027dc3fa1762c44e39551652199ef2a31f9bbcda79773c906151c12578cb18c43e0045de8b20c357272e1c62a +0 -0
  37. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/index/segments/52ea57bde33e8ef4718d833c2df3cf0a9e90fdcd5715c0caad50b4e37ea60aca2b8c71096de6920dc936c40b6291e896293f91c7cfd2aa96cf6c2aa49ef662c8 +0 -0
  38. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/index/segments/5ea52f6d4771afda4747b9f44954102c02ae2d0686f8aa9eca36c29796bbba0d14e851c0dca0a6af17bfbbbac174e3be645ae708d958390168e85c64786fc9ef +0 -0
  39. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/index/segments/86a1cfa113399acc7dd2dc90262a845558affb5e9373b6300dff68a485482c5e17ace9466bbc23b4301013ca1a27a577ca57ea838113f45bf321a64a242b1ad3 +0 -0
  40. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/index/segments/8ef99a12ae0624db198d9ecd83014fb8353c4731e0ba9a472f1fc339784308e38f1287d0765a7b0444f1a89c218c76a820dc4c9a3a39c1cedcd7423a4f5f88dc +0 -0
  41. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/index/segments/cb3e8da2bf2b7efae4a6e8fd0b8562dacd16ca0531b173a91480a9e60ee795ac5bec13fc6eb461e03edc9a26f5ff1d5ba53521a1c1a6c1ee1765b544b7d7bf73 +0 -0
  42. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/index/segments/d27ad326963b75736b636adad9fb812eb3f2871e0efb4bc7db37d4b701a4282911eaaee91bed3a759e940769b667be1ed66f2d7f2f41ac3906b87ab7eec19c3a +0 -0
  43. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/index/type +0 -0
  44. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/op_heads/heads/891d7ed26f62b0f8757b081e9d76840636877f1613ee17b7695fe2ee8640258c56e01291934e3797728bc2300a1b5f41e3f3ef81ab532c0e5ab475bb9b6f097a +0 -0
  45. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/op_heads/type +0 -0
  46. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/op_store/operations/282ad8cf3324b2679a7d460c0fc324adfa21dcfad2f197ac6991b98ec91f98495bb3ddb2cba36ce5dfa28a52063a373bb03f5d2e34f6e0c7b6b81b3046a4d7d0 +0 -0
  47. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/op_store/operations/891d7ed26f62b0f8757b081e9d76840636877f1613ee17b7695fe2ee8640258c56e01291934e3797728bc2300a1b5f41e3f3ef81ab532c0e5ab475bb9b6f097a +0 -0
  48. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/op_store/operations/8926397375b8328137652c18cd4371808b214cb26864d77dd33c8eea895e10e62c297064c3d4c703d58ee11dee81bbf9851525e3a0c33151f54c164b8a4343b0 +0 -0
  49. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/op_store/operations/89d29d938e64b1295e138faedfa5df6f6729a67e5ba8e0c3fdd1c9266e0f59a4bc35b8a21e14225072317879af3323fa0457e01d9b08608770bc23957feec6c0 +0 -0
  50. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/op_store/operations/95fc2854c0fa2528b03e2bcabc7612f56f0bcb3d6f54a06293e21d1887885a449907b5b320a1a94bac712bf56fdad0a4184b17047c1fc179dfa83acab3f70d21 +0 -0
  51. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/op_store/operations/9a58ceae46de4649375b6b880b8500c85d34c8e9bc650dc4c993afb2fa8d45c4180331821c6226a0fb1475b04a0b9a849502647ef9c4dcac74769eb501c885fa +0 -0
  52. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/op_store/operations/a19ae062208aa20b7310705af3d26ef53095a9dabfad080883cc7a32e98687063179db95cb2c71ef9064801c59fa46d261f172d83e83f96a39c274387b59dca4 +0 -0
  53. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/op_store/operations/d1169a8d10067493e42752c2a7615ff27f55bd90c38b91feef918958e29a2239ee289a0cde8385441d1f0fe9af1fb634fa6d56438b9f33ec382e81fa59d70b54 +0 -0
  54. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/op_store/operations/e171e5c6039c050c2368584a537d36df221b1f9f23d285c0399b95b14608d67006229823e6831bff7d8b0c2f9e86ebaec9c6811461119195f430ade055073fed +0 -0
  55. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/op_store/operations/ee118dd19aac4e1cb354f83a37dadca70bc5f086cc8d36cd0059b222bf8c7250824401ff681518d0120f8db1f96f0025c464dcfc3b1ee28777e8c76325760134 +0 -0
  56. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/op_store/type +0 -0
  57. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/op_store/views/123b0e36150cf8e99d644d2dfd1a7b0c8d2f676a78248d6902516d9ae58903665c79ec3f5f6729b98a1237dcf2abc1d41e690ae0ad30888c84786bcc9de5e314 +0 -0
  58. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/op_store/views/2ac0b7d8b1fdfac82b3ff3926e0018f72ef2b48f85b41f5fa541271370e1197d41e37c2c6d62af0c6974658c4a9e5e945b8efcbcc7748bdd99bd9483f7e13e22 +0 -0
  59. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/op_store/views/67b8396b301935ff624ff98952c57d8ee021e7d885e1220053b993e7bc822a4cf061298e9643ded745c55f3ed8e923a6731524129993d2664f48b60660761145 +0 -0
  60. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/op_store/views/9c6fca696f77383cc87d068fe3f5912466b157dccc6465973e653dd4d2c02e2eca9c0725c071857bf3f4f0e263259eafc18f1739615a501e672bb2afd415316b +0 -0
  61. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/op_store/views/cae2e3e5952cb5ba93f27e3898d90dac6c41fc9e20c66ef0791e71b91dc103d924996c921c88179705264a224fb5d2bb29091fc8f18f0ea7a088aaabb859ea2a +0 -0
  62. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/op_store/views/cd8efb6da14127c81c37b56ead18a39b30f2cd154891185a6e906efb491dbf63f290eed3c31d4725f490a93208ffbe5cdc031d5b6de38fcb77cbb11f0357118f +0 -0
  63. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/op_store/views/e434359d6306a4f6997733b9b5308299984f05219c92e1b2a31f1203126be0fada5fc09a2ba86c98d1318981cb53997c7f8674ef25da6ca7bf9fd849598cd355 +0 -0
  64. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/op_store/views/ea75e7ccb42f52b013dc1b45bb4e6d692b37c5e38bd39356ba2806be83ca5ca03ce20481db2788428126f93663e6723f99f4d46c5c705f5b12b70e2127ab15ba +0 -0
  65. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/op_store/views/fa5dec7ee06fbc6cbb2798c8e98bab482a6750776de41406fb06893c83f71f5015ec7ee2873642714b7bbc1c496f880e3acf44ffdabf2f87a39e0fbd68a4cc46 +0 -0
  66. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/op_store/views/ffde172c6285c71851b22780e34962d8f9234067af59ff2dc38b74e905dc540fe35b944e8c0b2d4230dfcf778424a335494cd0aeea1bb4be2a11c4b5428ad465 +0 -0
  67. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/store/extra/14e3f15273e204cadfe38dd2f38cebd1343a6bfbb91c6af0f5f9de6e9003d8ec8b0eb676975af9dca2d06ee5e6b3886c3c5d3755c6f149b6b09172cccc35adff +0 -0
  68. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/store/extra/42e0f32dd10ba6ae9f2297ca8ad0bd16337f14545b29f956ce380a7ab92bab771cbc9e04755752a6fa13231286f724379d6662b0fb257ef2cc2c52fe680eb95d +0 -0
  69. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/store/extra/466a441e56afdde383cef1d6127ca1d4c825157feb65a59f8f6ff5fa7a523bd683d0b7a6bb16c00afff53a890319a472d98da9af3dea5675168a4d424aa7af32 +0 -0
  70. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/store/extra/482ae5a29fbe856c7272f2071b8b0f0359ee2d89ff392b8a900643fbd0836eccd067b8bf41909e206c90d45d6e7d8b6686b93ecaee5fe1a9060d87b672101310 +0 -0
  71. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/store/extra/5403fa06049419ddcf620ce0dc20911583e1b1062b42630ee325aa5ac2f918dd266dfed93ebc808a2aecb37ac3a33e251fe1396fd24b8ed566bfbd61a81ff959 +0 -0
  72. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/store/extra/56119fa0480cb66159978b1a8c9b031f9e978b7a3172eb87407a701fea34fdd90db7771cd433a2cf7e8a84a7b49c924f973eccb0eb05685ec42f36f7ef61cc06 +0 -0
  73. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/store/extra/90b1f4de4ba65e0652f1de45e4c84b623f99bd9d9453667e19c7040857bd397e59e7a84406f2ab6204d25789d995c47c350d8abc47a4bbb102059f3111f20028 +0 -0
  74. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/store/extra/9215bd4ac28fdecba111c63bace46d0f1c253ad3af44e0e74bd43d30757bef2e655538c1172c8f25769bce0a3c669b713440773c1859f0a136d9ca42501f2470 +0 -0
  75. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/store/extra/a79320f784ef97b3d6297e55a48b17a517a38d95d5c61ba8d01c59d68dcd2ccf3a96479f4fc3c4cafdcd56dc7bd58b1cb987e079764c1646533ab32418900727 +0 -0
  76. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/store/extra/abe6b7a350e1604cb8f5a2cd10cef13a019bd797770e6dc37414d33d98dcf36d8ec80a2ae13bd7dd2d2076772c0ffadec0b53ba72f4669b461fff2da5d30f1ba +0 -0
  77. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/store/extra/b7689d54193a3798edd58d758966ad65ad57297c5276eab3e4ef07380779363efe9e462a149f4d42f55bbe004eb5ba88bf35df4c78ac975275530382390159d6 +0 -0
  78. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/store/extra/e75f5f3431d172d7e9434dfaef2be50812105b3ead73eeb10345c9b6892e9cbb5ee0602ebb0ceaf5ab87d22f45930dc30d136d0aac77310fb0261b3857ffde9b +0 -0
  79. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/store/extra/heads/56119fa0480cb66159978b1a8c9b031f9e978b7a3172eb87407a701fea34fdd90db7771cd433a2cf7e8a84a7b49c924f973eccb0eb05685ec42f36f7ef61cc06 +0 -0
  80. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/store/git_target +0 -0
  81. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/store/type +0 -0
  82. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/submodule_store/type +0 -0
  83. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/repo/workspace_store/index +0 -0
  84. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/working_copy/checkout +0 -0
  85. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/working_copy/tree_state +0 -0
  86. {tab_cli-0.2.0 → tab_cli-0.2.1}/.jj/working_copy/type +0 -0
  87. {tab_cli-0.2.0 → tab_cli-0.2.1}/AGENTS.md +0 -0
  88. {tab_cli-0.2.0 → tab_cli-0.2.1}/CHANGELOG.md +0 -0
  89. {tab_cli-0.2.0 → tab_cli-0.2.1}/FSSPEC_GLOB_NOTES.md +0 -0
  90. {tab_cli-0.2.0 → tab_cli-0.2.1}/LICENSE +0 -0
  91. {tab_cli-0.2.0 → tab_cli-0.2.1}/Makefile +0 -0
  92. {tab_cli-0.2.0 → tab_cli-0.2.1}/README.md +0 -0
  93. {tab_cli-0.2.0 → tab_cli-0.2.1}/docs/cloud.md +0 -0
  94. {tab_cli-0.2.0 → tab_cli-0.2.1}/docs/configuration.md +0 -0
  95. {tab_cli-0.2.0 → tab_cli-0.2.1}/docs/databases.md +0 -0
  96. {tab_cli-0.2.0 → tab_cli-0.2.1}/docs/index.md +0 -0
  97. {tab_cli-0.2.0 → tab_cli-0.2.1}/mkdocs.yml +0 -0
  98. {tab_cli-0.2.0 → tab_cli-0.2.1}/src/tab_cli/__init__.py +0 -0
  99. {tab_cli-0.2.0 → tab_cli-0.2.1}/src/tab_cli/formats/__init__.py +0 -0
  100. {tab_cli-0.2.0 → tab_cli-0.2.1}/src/tab_cli/formats/avro.py +0 -0
  101. {tab_cli-0.2.0 → tab_cli-0.2.1}/src/tab_cli/formats/base.py +0 -0
  102. {tab_cli-0.2.0 → tab_cli-0.2.1}/src/tab_cli/formats/csv.py +0 -0
  103. {tab_cli-0.2.0 → tab_cli-0.2.1}/src/tab_cli/formats/duckdb.py +0 -0
  104. {tab_cli-0.2.0 → tab_cli-0.2.1}/src/tab_cli/formats/jsonl.py +0 -0
  105. {tab_cli-0.2.0 → tab_cli-0.2.1}/src/tab_cli/formats/parquet.py +0 -0
  106. {tab_cli-0.2.0 → tab_cli-0.2.1}/src/tab_cli/formats/sqlite.py +0 -0
  107. {tab_cli-0.2.0 → tab_cli-0.2.1}/src/tab_cli/handlers/__init__.py +0 -0
  108. {tab_cli-0.2.0 → tab_cli-0.2.1}/src/tab_cli/handlers/base.py +0 -0
  109. {tab_cli-0.2.0 → tab_cli-0.2.1}/src/tab_cli/handlers/cli_table.py +0 -0
  110. {tab_cli-0.2.0 → tab_cli-0.2.1}/src/tab_cli/storage/__init__.py +0 -0
  111. {tab_cli-0.2.0 → tab_cli-0.2.1}/src/tab_cli/storage/aws.py +0 -0
  112. {tab_cli-0.2.0 → tab_cli-0.2.1}/src/tab_cli/storage/az.py +0 -0
  113. {tab_cli-0.2.0 → tab_cli-0.2.1}/src/tab_cli/storage/base.py +0 -0
  114. {tab_cli-0.2.0 → tab_cli-0.2.1}/src/tab_cli/storage/fsspec.py +0 -0
  115. {tab_cli-0.2.0 → tab_cli-0.2.1}/src/tab_cli/storage/gcloud.py +0 -0
  116. {tab_cli-0.2.0 → tab_cli-0.2.1}/src/tab_cli/storage/local.py +0 -0
  117. {tab_cli-0.2.0 → tab_cli-0.2.1}/src/tab_cli/style.py +0 -0
  118. {tab_cli-0.2.0 → tab_cli-0.2.1}/src/tab_cli/url_parser.py +0 -0
  119. {tab_cli-0.2.0 → tab_cli-0.2.1}/tests/__init__.py +0 -0
  120. {tab_cli-0.2.0 → tab_cli-0.2.1}/tests/assets/test.csv +0 -0
  121. {tab_cli-0.2.0 → tab_cli-0.2.1}/tests/conftest.py +0 -0
  122. {tab_cli-0.2.0 → tab_cli-0.2.1}/tests/test_cat.py +0 -0
  123. {tab_cli-0.2.0 → tab_cli-0.2.1}/tests/test_stdin.py +0 -0
  124. {tab_cli-0.2.0 → tab_cli-0.2.1}/tests/test_storage.py +0 -0
  125. {tab_cli-0.2.0 → tab_cli-0.2.1}/tests/test_summary.py +0 -0
  126. {tab_cli-0.2.0 → tab_cli-0.2.1}/tests/test_view.py +0 -0
  127. {tab_cli-0.2.0 → tab_cli-0.2.1}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tab-cli
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: A CLI tool for tabular data
5
5
  Author-email: Tongfei Chen <tongfei@pm.me>
6
6
  License-File: LICENSE
@@ -100,5 +100,5 @@ Options:
100
100
 
101
101
  | Option | Description |
102
102
  |-------------------------|------------------------------------------------------------------------------------------------------------------------------|
103
- | `--az-url-authority-is-account` | Interpret az:// URL authority as storage account name instead of container name. See [azure.md](Azure) for more information. |
104
- | `--log-level` | Log level from `{DEBUG, INFO, WARNING, ERROR, CRITICAL}`. If omitted, uses `log_level` from config. |
103
+ | `--az-url-authority-is-account` | Interpret az:// URL authority as storage account name instead of container name. See [Cloud](cloud.md) for more information. |
104
+ | `--log-level` | Log level from `{DEBUG, INFO, WARNING, ERROR, CRITICAL}`. If omitted, uses `log_level` from config. |
@@ -0,0 +1,3 @@
1
+ mkdir -p docs/assets
2
+ uv run tab --log-level error view tests/assets/test.csv --table-svg 2> docs/assets/test.svg
3
+ uv run tab --log-level error view --sql 'SELECT * FROM t WHERE Metric_A_Value > 80' tests/assets/test.csv --table-svg 2> docs/assets/test-where.svg
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "tab-cli"
3
- version = "0.2.0"
3
+ version = "0.2.1"
4
4
  description = "A CLI tool for tabular data"
5
5
  authors = [{name = "Tongfei Chen", email = "tongfei@pm.me"}]
6
6
  readme = "README.md"
@@ -80,6 +80,28 @@ app = typer.Typer(
80
80
  )
81
81
 
82
82
  DEFAULT_VIEW_TRUNCATION_PROBE_ROWS = 1
83
+ VALID_LOG_LEVELS = {"DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"}
84
+
85
+
86
+ def _normalize_log_level(log_level: str) -> str:
87
+ normalized = log_level.upper()
88
+ if normalized not in VALID_LOG_LEVELS:
89
+ valid_levels = ", ".join(sorted(VALID_LOG_LEVELS))
90
+ raise typer.BadParameter(f"Invalid log level '{log_level}'. Expected one of: {valid_levels}")
91
+ return normalized
92
+
93
+
94
+ def _configure_logger(level: str) -> None:
95
+ logger.remove()
96
+ logger.add(
97
+ RichHandler(
98
+ rich_tracebacks=True,
99
+ tracebacks_show_locals=True,
100
+ markup=True,
101
+ ),
102
+ format="{message}",
103
+ level=level,
104
+ )
83
105
 
84
106
 
85
107
  @app.callback()
@@ -100,23 +122,21 @@ def main_callback(
100
122
  ] = None,
101
123
  ) -> None:
102
124
  """Global options for tab_cli CLI."""
103
- load_config_file()
104
- effective_log_level = (
105
- log_level.upper() if log_level is not None else config.config.log_level.upper()
106
- )
107
125
  logger.remove()
108
- logger.add(
109
- RichHandler(
110
- rich_tracebacks=True,
111
- tracebacks_show_locals=True,
112
- markup=True,
113
- ),
114
- format="{message}",
115
- level=effective_log_level,
126
+ loaded_config = load_config_file()
127
+ effective_config = loaded_config
128
+
129
+ effective_config.log_level = (
130
+ _normalize_log_level(log_level)
131
+ if log_level is not None
132
+ else _normalize_log_level(effective_config.log_level)
116
133
  )
117
- # CLI flags override config file values
134
+
118
135
  if az_url_authority_is_account:
119
- config.config.az_url_authority_is_account = az_url_authority_is_account
136
+ effective_config.az_url_authority_is_account = az_url_authority_is_account
137
+
138
+ config.config = effective_config
139
+ _configure_logger(config.config.log_level)
120
140
 
121
141
 
122
142
  def _apply_sql(lf: pl.LazyFrame, sql: str | None) -> pl.LazyFrame:
@@ -37,15 +37,16 @@ def _matches_type(value: Any, expected_type: Any) -> bool:
37
37
  return type(value) is expected_type
38
38
 
39
39
 
40
- def load_config_file(path: Path = CONFIG_FILE) -> None:
41
- """Load settings from a JSON config file into the global config.
40
+ def load_config_file(path: Path = CONFIG_FILE) -> Config:
41
+ """Load settings from a JSON config file into a fresh Config object.
42
42
 
43
43
  Unknown keys are logged and ignored. Type mismatches raise ValueError.
44
- If the file does not exist, this is a no-op.
44
+ If the file does not exist, return built-in defaults.
45
45
  """
46
+ loaded_config = Config()
46
47
  if not path.is_file():
47
48
  logger.debug(f"No config file found at {path}; using built-in defaults")
48
- return
49
+ return loaded_config
49
50
 
50
51
  text = path.read_text(encoding="utf-8")
51
52
  data = json.loads(text)
@@ -65,5 +66,6 @@ def load_config_file(path: Path = CONFIG_FILE) -> None:
65
66
  raise ValueError(
66
67
  f"Config key '{key}' must be of type {expected_name}, got {type(value).__name__}"
67
68
  )
68
- setattr(config, key, value)
69
+ setattr(loaded_config, key, value)
69
70
  logger.debug(f"Loaded config from {path}")
71
+ return loaded_config
@@ -13,13 +13,13 @@ class TestConfigFile:
13
13
  config_module.config = Config()
14
14
 
15
15
  def test_load_missing_file(self, tmp_path):
16
- load_config_file(tmp_path / "nonexistent.json")
17
- assert config_module.config.az_url_authority_is_account is False
18
- assert config_module.config.default_num_view_rows == 20
19
- assert config_module.config.log_level == "INFO"
20
- assert config_module.config.max_cell_length is None
21
- assert config_module.config.num_remote_workers == 8
22
- assert config_module.config.sampling_size_for_schema_inference == 32
16
+ loaded = load_config_file(tmp_path / "nonexistent.json")
17
+ assert loaded.az_url_authority_is_account is False
18
+ assert loaded.default_num_view_rows == 20
19
+ assert loaded.log_level == "INFO"
20
+ assert loaded.max_cell_length is None
21
+ assert loaded.num_remote_workers == 8
22
+ assert loaded.sampling_size_for_schema_inference == 32
23
23
 
24
24
  def test_load_valid_config(self, tmp_path):
25
25
  cfg = tmp_path / "config.json"
@@ -35,13 +35,13 @@ class TestConfigFile:
35
35
  }
36
36
  )
37
37
  )
38
- load_config_file(cfg)
39
- assert config_module.config.az_url_authority_is_account is True
40
- assert config_module.config.default_num_view_rows == 10
41
- assert config_module.config.log_level == "DEBUG"
42
- assert config_module.config.max_cell_length == 12
43
- assert config_module.config.num_remote_workers == 2
44
- assert config_module.config.sampling_size_for_schema_inference == 64
38
+ loaded = load_config_file(cfg)
39
+ assert loaded.az_url_authority_is_account is True
40
+ assert loaded.default_num_view_rows == 10
41
+ assert loaded.log_level == "DEBUG"
42
+ assert loaded.max_cell_length == 12
43
+ assert loaded.num_remote_workers == 2
44
+ assert loaded.sampling_size_for_schema_inference == 64
45
45
 
46
46
  def test_load_partial_config(self, tmp_path):
47
47
  cfg = tmp_path / "config.json"
@@ -53,13 +53,13 @@ class TestConfigFile:
53
53
  }
54
54
  )
55
55
  )
56
- load_config_file(cfg)
57
- assert config_module.config.az_url_authority_is_account is False
58
- assert config_module.config.default_num_view_rows == 20
59
- assert config_module.config.log_level == "INFO"
60
- assert config_module.config.max_cell_length is None
61
- assert config_module.config.num_remote_workers == 8
62
- assert config_module.config.sampling_size_for_schema_inference == 128
56
+ loaded = load_config_file(cfg)
57
+ assert loaded.az_url_authority_is_account is False
58
+ assert loaded.default_num_view_rows == 20
59
+ assert loaded.log_level == "INFO"
60
+ assert loaded.max_cell_length is None
61
+ assert loaded.num_remote_workers == 8
62
+ assert loaded.sampling_size_for_schema_inference == 128
63
63
 
64
64
  def test_unknown_keys_ignored(self, tmp_path):
65
65
  cfg = tmp_path / "config.json"
@@ -68,9 +68,9 @@ class TestConfigFile:
68
68
  {"unknown_key": "value", "sampling_size_for_schema_inference": 16}
69
69
  )
70
70
  )
71
- load_config_file(cfg)
72
- assert config_module.config.sampling_size_for_schema_inference == 16
73
- assert not hasattr(config_module.config, "unknown_key")
71
+ loaded = load_config_file(cfg)
72
+ assert loaded.sampling_size_for_schema_inference == 16
73
+ assert not hasattr(loaded, "unknown_key")
74
74
 
75
75
  def test_invalid_json_raises(self, tmp_path):
76
76
  cfg = tmp_path / "config.json"
@@ -91,6 +91,38 @@ class TestConfigFile:
91
91
  except ValueError as exc:
92
92
  assert "num_remote_workers" in str(exc)
93
93
 
94
+ def test_invalid_log_level_in_config_is_rejected_by_cli(self, tmp_path):
95
+ cfg = tmp_path / "config.json"
96
+ cfg.write_text(json.dumps({"log_level": "NOPE"}))
97
+
98
+ with patch(
99
+ "tab_cli.cli.load_config_file", side_effect=lambda: load_config_file(cfg)
100
+ ):
101
+ result = runner.invoke(app, ["view", TEST_CSV])
102
+
103
+ assert result.exit_code != 0
104
+ assert "Invalid value" in result.output
105
+ assert "Invalid log level 'NOPE'" in result.output
106
+
107
+ def test_invalid_cli_log_level_has_friendly_error(self):
108
+ result = runner.invoke(app, ["--log-level", "NOPE", "view", TEST_CSV])
109
+
110
+ assert result.exit_code != 0
111
+ assert "Invalid value" in result.output
112
+ assert "Invalid log level 'NOPE'" in result.output
113
+
114
+ def test_missing_config_does_not_emit_debug_log_when_cli_log_level_is_error(self, tmp_path):
115
+ missing_cfg = tmp_path / "missing.json"
116
+
117
+ with patch(
118
+ "tab_cli.cli.load_config_file",
119
+ side_effect=lambda: load_config_file(missing_cfg),
120
+ ):
121
+ result = runner.invoke(app, ["--log-level", "ERROR", "view", TEST_CSV])
122
+
123
+ assert result.exit_code == 0
124
+ assert "No config file found" not in result.output
125
+
94
126
  def test_view_uses_default_max_cell_length_from_config(self, tmp_path):
95
127
  cfg = tmp_path / "config.json"
96
128
  cfg.write_text(json.dumps({"max_cell_length": 5}))
@@ -179,5 +211,5 @@ class TestConfigFile:
179
211
  def test_config_file_sets_num_remote_workers(self, tmp_path):
180
212
  cfg = tmp_path / "config.json"
181
213
  cfg.write_text(json.dumps({"num_remote_workers": 3}))
182
- load_config_file(cfg)
183
- assert config_module.config.num_remote_workers == 3
214
+ loaded = load_config_file(cfg)
215
+ assert loaded.num_remote_workers == 3
@@ -1,3 +0,0 @@
1
- mkdir -p docs/assets
2
- uv run tab view tests/assets/test.csv --table-svg 2> docs/assets/test.svg
3
- uv run tab view --sql 'SELECT * FROM t WHERE Metric_A_Value > 80' tests/assets/test.csv --table-svg 2> docs/assets/test-where.svg
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes