tab-cli 0.1.5__tar.gz → 0.1.7__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 (118) hide show
  1. {tab_cli-0.1.5 → tab_cli-0.1.7}/AGENTS.md +1 -0
  2. {tab_cli-0.1.5 → tab_cli-0.1.7}/CHANGELOG.md +5 -0
  3. tab_cli-0.1.7/PKG-INFO +121 -0
  4. tab_cli-0.1.7/README.md +94 -0
  5. tab_cli-0.1.7/docs/configuration.md +34 -0
  6. {tab_cli-0.1.5 → tab_cli-0.1.7}/mkdocs.yml +1 -0
  7. {tab_cli-0.1.5 → tab_cli-0.1.7}/pyproject.toml +3 -3
  8. {tab_cli-0.1.5 → tab_cli-0.1.7}/src/tab_cli/cli.py +95 -27
  9. tab_cli-0.1.7/src/tab_cli/config.py +47 -0
  10. {tab_cli-0.1.5 → tab_cli-0.1.7}/src/tab_cli/formats/parquet.py +1 -1
  11. {tab_cli-0.1.5 → tab_cli-0.1.7}/tests/test_cli.py +164 -14
  12. tab_cli-0.1.5/PKG-INFO +0 -37
  13. tab_cli-0.1.5/README.md +0 -10
  14. tab_cli-0.1.5/src/tab_cli/config.py +0 -15
  15. {tab_cli-0.1.5 → tab_cli-0.1.7}/.gitignore +0 -0
  16. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/.gitignore +0 -0
  17. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/index/op_links/00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +0 -0
  18. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/index/op_links/282ad8cf3324b2679a7d460c0fc324adfa21dcfad2f197ac6991b98ec91f98495bb3ddb2cba36ce5dfa28a52063a373bb03f5d2e34f6e0c7b6b81b3046a4d7d0 +0 -0
  19. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/index/op_links/891d7ed26f62b0f8757b081e9d76840636877f1613ee17b7695fe2ee8640258c56e01291934e3797728bc2300a1b5f41e3f3ef81ab532c0e5ab475bb9b6f097a +0 -0
  20. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/index/op_links/8926397375b8328137652c18cd4371808b214cb26864d77dd33c8eea895e10e62c297064c3d4c703d58ee11dee81bbf9851525e3a0c33151f54c164b8a4343b0 +0 -0
  21. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/index/op_links/89d29d938e64b1295e138faedfa5df6f6729a67e5ba8e0c3fdd1c9266e0f59a4bc35b8a21e14225072317879af3323fa0457e01d9b08608770bc23957feec6c0 +0 -0
  22. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/index/op_links/95fc2854c0fa2528b03e2bcabc7612f56f0bcb3d6f54a06293e21d1887885a449907b5b320a1a94bac712bf56fdad0a4184b17047c1fc179dfa83acab3f70d21 +0 -0
  23. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/index/op_links/9a58ceae46de4649375b6b880b8500c85d34c8e9bc650dc4c993afb2fa8d45c4180331821c6226a0fb1475b04a0b9a849502647ef9c4dcac74769eb501c885fa +0 -0
  24. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/index/op_links/a19ae062208aa20b7310705af3d26ef53095a9dabfad080883cc7a32e98687063179db95cb2c71ef9064801c59fa46d261f172d83e83f96a39c274387b59dca4 +0 -0
  25. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/index/op_links/d1169a8d10067493e42752c2a7615ff27f55bd90c38b91feef918958e29a2239ee289a0cde8385441d1f0fe9af1fb634fa6d56438b9f33ec382e81fa59d70b54 +0 -0
  26. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/index/op_links/e171e5c6039c050c2368584a537d36df221b1f9f23d285c0399b95b14608d67006229823e6831bff7d8b0c2f9e86ebaec9c6811461119195f430ade055073fed +0 -0
  27. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/index/op_links/ee118dd19aac4e1cb354f83a37dadca70bc5f086cc8d36cd0059b222bf8c7250824401ff681518d0120f8db1f96f0025c464dcfc3b1ee28777e8c76325760134 +0 -0
  28. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/index/operations/00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +0 -0
  29. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/index/operations/282ad8cf3324b2679a7d460c0fc324adfa21dcfad2f197ac6991b98ec91f98495bb3ddb2cba36ce5dfa28a52063a373bb03f5d2e34f6e0c7b6b81b3046a4d7d0 +0 -0
  30. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/index/operations/891d7ed26f62b0f8757b081e9d76840636877f1613ee17b7695fe2ee8640258c56e01291934e3797728bc2300a1b5f41e3f3ef81ab532c0e5ab475bb9b6f097a +0 -0
  31. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/index/operations/8926397375b8328137652c18cd4371808b214cb26864d77dd33c8eea895e10e62c297064c3d4c703d58ee11dee81bbf9851525e3a0c33151f54c164b8a4343b0 +0 -0
  32. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/index/operations/89d29d938e64b1295e138faedfa5df6f6729a67e5ba8e0c3fdd1c9266e0f59a4bc35b8a21e14225072317879af3323fa0457e01d9b08608770bc23957feec6c0 +0 -0
  33. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/index/operations/95fc2854c0fa2528b03e2bcabc7612f56f0bcb3d6f54a06293e21d1887885a449907b5b320a1a94bac712bf56fdad0a4184b17047c1fc179dfa83acab3f70d21 +0 -0
  34. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/index/operations/9a58ceae46de4649375b6b880b8500c85d34c8e9bc650dc4c993afb2fa8d45c4180331821c6226a0fb1475b04a0b9a849502647ef9c4dcac74769eb501c885fa +0 -0
  35. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/index/operations/a19ae062208aa20b7310705af3d26ef53095a9dabfad080883cc7a32e98687063179db95cb2c71ef9064801c59fa46d261f172d83e83f96a39c274387b59dca4 +0 -0
  36. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/index/operations/d1169a8d10067493e42752c2a7615ff27f55bd90c38b91feef918958e29a2239ee289a0cde8385441d1f0fe9af1fb634fa6d56438b9f33ec382e81fa59d70b54 +0 -0
  37. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/index/operations/e171e5c6039c050c2368584a537d36df221b1f9f23d285c0399b95b14608d67006229823e6831bff7d8b0c2f9e86ebaec9c6811461119195f430ade055073fed +0 -0
  38. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/index/operations/ee118dd19aac4e1cb354f83a37dadca70bc5f086cc8d36cd0059b222bf8c7250824401ff681518d0120f8db1f96f0025c464dcfc3b1ee28777e8c76325760134 +0 -0
  39. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/index/segments/1029dd1c1f4430d8a667a0e48d0b817652c7ddca6f5ff56cac1755e5bb0c1cb7586935941c9b36f26cab05c0effe6154d073bd1dffbe37f22fed0a6e7d79201f +0 -0
  40. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/index/segments/3228b9bef9d8374b5532b40df2da8be3bfc86de713bdad7fe620977ffa7c56db83928678caa792bf0d328db607028e045a9e41423ef7501e5b550651c3815ffe +0 -0
  41. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/index/segments/424c9a53f5458b328d77ed6a943dc35662e949befa8725cfc7eead01a270417c8d07c1001b11623a088da8d2c9c34a41573314fa2394643147e4027e8a96a605 +0 -0
  42. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/index/segments/44107e81054aa5544b36eab8d811908a559b4d9027dc3fa1762c44e39551652199ef2a31f9bbcda79773c906151c12578cb18c43e0045de8b20c357272e1c62a +0 -0
  43. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/index/segments/52ea57bde33e8ef4718d833c2df3cf0a9e90fdcd5715c0caad50b4e37ea60aca2b8c71096de6920dc936c40b6291e896293f91c7cfd2aa96cf6c2aa49ef662c8 +0 -0
  44. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/index/segments/5ea52f6d4771afda4747b9f44954102c02ae2d0686f8aa9eca36c29796bbba0d14e851c0dca0a6af17bfbbbac174e3be645ae708d958390168e85c64786fc9ef +0 -0
  45. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/index/segments/86a1cfa113399acc7dd2dc90262a845558affb5e9373b6300dff68a485482c5e17ace9466bbc23b4301013ca1a27a577ca57ea838113f45bf321a64a242b1ad3 +0 -0
  46. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/index/segments/8ef99a12ae0624db198d9ecd83014fb8353c4731e0ba9a472f1fc339784308e38f1287d0765a7b0444f1a89c218c76a820dc4c9a3a39c1cedcd7423a4f5f88dc +0 -0
  47. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/index/segments/cb3e8da2bf2b7efae4a6e8fd0b8562dacd16ca0531b173a91480a9e60ee795ac5bec13fc6eb461e03edc9a26f5ff1d5ba53521a1c1a6c1ee1765b544b7d7bf73 +0 -0
  48. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/index/segments/d27ad326963b75736b636adad9fb812eb3f2871e0efb4bc7db37d4b701a4282911eaaee91bed3a759e940769b667be1ed66f2d7f2f41ac3906b87ab7eec19c3a +0 -0
  49. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/index/type +0 -0
  50. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/op_heads/heads/891d7ed26f62b0f8757b081e9d76840636877f1613ee17b7695fe2ee8640258c56e01291934e3797728bc2300a1b5f41e3f3ef81ab532c0e5ab475bb9b6f097a +0 -0
  51. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/op_heads/type +0 -0
  52. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/op_store/operations/282ad8cf3324b2679a7d460c0fc324adfa21dcfad2f197ac6991b98ec91f98495bb3ddb2cba36ce5dfa28a52063a373bb03f5d2e34f6e0c7b6b81b3046a4d7d0 +0 -0
  53. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/op_store/operations/891d7ed26f62b0f8757b081e9d76840636877f1613ee17b7695fe2ee8640258c56e01291934e3797728bc2300a1b5f41e3f3ef81ab532c0e5ab475bb9b6f097a +0 -0
  54. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/op_store/operations/8926397375b8328137652c18cd4371808b214cb26864d77dd33c8eea895e10e62c297064c3d4c703d58ee11dee81bbf9851525e3a0c33151f54c164b8a4343b0 +0 -0
  55. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/op_store/operations/89d29d938e64b1295e138faedfa5df6f6729a67e5ba8e0c3fdd1c9266e0f59a4bc35b8a21e14225072317879af3323fa0457e01d9b08608770bc23957feec6c0 +0 -0
  56. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/op_store/operations/95fc2854c0fa2528b03e2bcabc7612f56f0bcb3d6f54a06293e21d1887885a449907b5b320a1a94bac712bf56fdad0a4184b17047c1fc179dfa83acab3f70d21 +0 -0
  57. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/op_store/operations/9a58ceae46de4649375b6b880b8500c85d34c8e9bc650dc4c993afb2fa8d45c4180331821c6226a0fb1475b04a0b9a849502647ef9c4dcac74769eb501c885fa +0 -0
  58. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/op_store/operations/a19ae062208aa20b7310705af3d26ef53095a9dabfad080883cc7a32e98687063179db95cb2c71ef9064801c59fa46d261f172d83e83f96a39c274387b59dca4 +0 -0
  59. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/op_store/operations/d1169a8d10067493e42752c2a7615ff27f55bd90c38b91feef918958e29a2239ee289a0cde8385441d1f0fe9af1fb634fa6d56438b9f33ec382e81fa59d70b54 +0 -0
  60. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/op_store/operations/e171e5c6039c050c2368584a537d36df221b1f9f23d285c0399b95b14608d67006229823e6831bff7d8b0c2f9e86ebaec9c6811461119195f430ade055073fed +0 -0
  61. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/op_store/operations/ee118dd19aac4e1cb354f83a37dadca70bc5f086cc8d36cd0059b222bf8c7250824401ff681518d0120f8db1f96f0025c464dcfc3b1ee28777e8c76325760134 +0 -0
  62. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/op_store/type +0 -0
  63. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/op_store/views/123b0e36150cf8e99d644d2dfd1a7b0c8d2f676a78248d6902516d9ae58903665c79ec3f5f6729b98a1237dcf2abc1d41e690ae0ad30888c84786bcc9de5e314 +0 -0
  64. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/op_store/views/2ac0b7d8b1fdfac82b3ff3926e0018f72ef2b48f85b41f5fa541271370e1197d41e37c2c6d62af0c6974658c4a9e5e945b8efcbcc7748bdd99bd9483f7e13e22 +0 -0
  65. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/op_store/views/67b8396b301935ff624ff98952c57d8ee021e7d885e1220053b993e7bc822a4cf061298e9643ded745c55f3ed8e923a6731524129993d2664f48b60660761145 +0 -0
  66. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/op_store/views/9c6fca696f77383cc87d068fe3f5912466b157dccc6465973e653dd4d2c02e2eca9c0725c071857bf3f4f0e263259eafc18f1739615a501e672bb2afd415316b +0 -0
  67. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/op_store/views/cae2e3e5952cb5ba93f27e3898d90dac6c41fc9e20c66ef0791e71b91dc103d924996c921c88179705264a224fb5d2bb29091fc8f18f0ea7a088aaabb859ea2a +0 -0
  68. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/op_store/views/cd8efb6da14127c81c37b56ead18a39b30f2cd154891185a6e906efb491dbf63f290eed3c31d4725f490a93208ffbe5cdc031d5b6de38fcb77cbb11f0357118f +0 -0
  69. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/op_store/views/e434359d6306a4f6997733b9b5308299984f05219c92e1b2a31f1203126be0fada5fc09a2ba86c98d1318981cb53997c7f8674ef25da6ca7bf9fd849598cd355 +0 -0
  70. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/op_store/views/ea75e7ccb42f52b013dc1b45bb4e6d692b37c5e38bd39356ba2806be83ca5ca03ce20481db2788428126f93663e6723f99f4d46c5c705f5b12b70e2127ab15ba +0 -0
  71. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/op_store/views/fa5dec7ee06fbc6cbb2798c8e98bab482a6750776de41406fb06893c83f71f5015ec7ee2873642714b7bbc1c496f880e3acf44ffdabf2f87a39e0fbd68a4cc46 +0 -0
  72. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/op_store/views/ffde172c6285c71851b22780e34962d8f9234067af59ff2dc38b74e905dc540fe35b944e8c0b2d4230dfcf778424a335494cd0aeea1bb4be2a11c4b5428ad465 +0 -0
  73. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/store/extra/14e3f15273e204cadfe38dd2f38cebd1343a6bfbb91c6af0f5f9de6e9003d8ec8b0eb676975af9dca2d06ee5e6b3886c3c5d3755c6f149b6b09172cccc35adff +0 -0
  74. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/store/extra/42e0f32dd10ba6ae9f2297ca8ad0bd16337f14545b29f956ce380a7ab92bab771cbc9e04755752a6fa13231286f724379d6662b0fb257ef2cc2c52fe680eb95d +0 -0
  75. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/store/extra/466a441e56afdde383cef1d6127ca1d4c825157feb65a59f8f6ff5fa7a523bd683d0b7a6bb16c00afff53a890319a472d98da9af3dea5675168a4d424aa7af32 +0 -0
  76. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/store/extra/482ae5a29fbe856c7272f2071b8b0f0359ee2d89ff392b8a900643fbd0836eccd067b8bf41909e206c90d45d6e7d8b6686b93ecaee5fe1a9060d87b672101310 +0 -0
  77. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/store/extra/5403fa06049419ddcf620ce0dc20911583e1b1062b42630ee325aa5ac2f918dd266dfed93ebc808a2aecb37ac3a33e251fe1396fd24b8ed566bfbd61a81ff959 +0 -0
  78. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/store/extra/56119fa0480cb66159978b1a8c9b031f9e978b7a3172eb87407a701fea34fdd90db7771cd433a2cf7e8a84a7b49c924f973eccb0eb05685ec42f36f7ef61cc06 +0 -0
  79. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/store/extra/90b1f4de4ba65e0652f1de45e4c84b623f99bd9d9453667e19c7040857bd397e59e7a84406f2ab6204d25789d995c47c350d8abc47a4bbb102059f3111f20028 +0 -0
  80. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/store/extra/9215bd4ac28fdecba111c63bace46d0f1c253ad3af44e0e74bd43d30757bef2e655538c1172c8f25769bce0a3c669b713440773c1859f0a136d9ca42501f2470 +0 -0
  81. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/store/extra/a79320f784ef97b3d6297e55a48b17a517a38d95d5c61ba8d01c59d68dcd2ccf3a96479f4fc3c4cafdcd56dc7bd58b1cb987e079764c1646533ab32418900727 +0 -0
  82. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/store/extra/abe6b7a350e1604cb8f5a2cd10cef13a019bd797770e6dc37414d33d98dcf36d8ec80a2ae13bd7dd2d2076772c0ffadec0b53ba72f4669b461fff2da5d30f1ba +0 -0
  83. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/store/extra/b7689d54193a3798edd58d758966ad65ad57297c5276eab3e4ef07380779363efe9e462a149f4d42f55bbe004eb5ba88bf35df4c78ac975275530382390159d6 +0 -0
  84. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/store/extra/e75f5f3431d172d7e9434dfaef2be50812105b3ead73eeb10345c9b6892e9cbb5ee0602ebb0ceaf5ab87d22f45930dc30d136d0aac77310fb0261b3857ffde9b +0 -0
  85. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/store/extra/heads/56119fa0480cb66159978b1a8c9b031f9e978b7a3172eb87407a701fea34fdd90db7771cd433a2cf7e8a84a7b49c924f973eccb0eb05685ec42f36f7ef61cc06 +0 -0
  86. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/store/git_target +0 -0
  87. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/store/type +0 -0
  88. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/submodule_store/type +0 -0
  89. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/repo/workspace_store/index +0 -0
  90. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/working_copy/checkout +0 -0
  91. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/working_copy/tree_state +0 -0
  92. {tab_cli-0.1.5 → tab_cli-0.1.7}/.jj/working_copy/type +0 -0
  93. {tab_cli-0.1.5 → tab_cli-0.1.7}/LICENSE +0 -0
  94. {tab_cli-0.1.5 → tab_cli-0.1.7}/Makefile +0 -0
  95. {tab_cli-0.1.5 → tab_cli-0.1.7}/docs/cli-ref.md +0 -0
  96. {tab_cli-0.1.5 → tab_cli-0.1.7}/docs/cloud.md +0 -0
  97. {tab_cli-0.1.5 → tab_cli-0.1.7}/docs/gen_assets.sh +0 -0
  98. {tab_cli-0.1.5 → tab_cli-0.1.7}/docs/index.md +0 -0
  99. {tab_cli-0.1.5 → tab_cli-0.1.7}/src/tab_cli/__init__.py +0 -0
  100. {tab_cli-0.1.5 → tab_cli-0.1.7}/src/tab_cli/formats/__init__.py +0 -0
  101. {tab_cli-0.1.5 → tab_cli-0.1.7}/src/tab_cli/formats/avro.py +0 -0
  102. {tab_cli-0.1.5 → tab_cli-0.1.7}/src/tab_cli/formats/base.py +0 -0
  103. {tab_cli-0.1.5 → tab_cli-0.1.7}/src/tab_cli/formats/csv.py +0 -0
  104. {tab_cli-0.1.5 → tab_cli-0.1.7}/src/tab_cli/formats/jsonl.py +0 -0
  105. {tab_cli-0.1.5 → tab_cli-0.1.7}/src/tab_cli/handlers/__init__.py +0 -0
  106. {tab_cli-0.1.5 → tab_cli-0.1.7}/src/tab_cli/handlers/base.py +0 -0
  107. {tab_cli-0.1.5 → tab_cli-0.1.7}/src/tab_cli/handlers/cli_table.py +0 -0
  108. {tab_cli-0.1.5 → tab_cli-0.1.7}/src/tab_cli/storage/__init__.py +0 -0
  109. {tab_cli-0.1.5 → tab_cli-0.1.7}/src/tab_cli/storage/aws.py +0 -0
  110. {tab_cli-0.1.5 → tab_cli-0.1.7}/src/tab_cli/storage/az.py +0 -0
  111. {tab_cli-0.1.5 → tab_cli-0.1.7}/src/tab_cli/storage/base.py +0 -0
  112. {tab_cli-0.1.5 → tab_cli-0.1.7}/src/tab_cli/storage/fsspec.py +0 -0
  113. {tab_cli-0.1.5 → tab_cli-0.1.7}/src/tab_cli/storage/gcloud.py +0 -0
  114. {tab_cli-0.1.5 → tab_cli-0.1.7}/src/tab_cli/storage/local.py +0 -0
  115. {tab_cli-0.1.5 → tab_cli-0.1.7}/src/tab_cli/style.py +0 -0
  116. {tab_cli-0.1.5 → tab_cli-0.1.7}/src/tab_cli/url_parser.py +0 -0
  117. {tab_cli-0.1.5 → tab_cli-0.1.7}/tests/__init__.py +0 -0
  118. {tab_cli-0.1.5 → tab_cli-0.1.7}/tests/assets/test.csv +0 -0
@@ -143,6 +143,7 @@ Use it as the default operating guide when changing code in this repo.
143
143
  ## Documentation
144
144
 
145
145
  - Update `docs/` and CLI help text when changing user-facing behavior.
146
+ - Update `CHANGELOG.md` with a clear description of user-facing changes and bug fixes.
146
147
  - Keep examples aligned with the actual command names and flags.
147
148
  - If you change build, test, or auth flows, reflect that in this file too.
148
149
 
@@ -1,3 +1,8 @@
1
+ - 0.1.7:
2
+ - Optional dependency groups are now named `tab-cli[s3|gs|az]`, in accordance with the protocol name.
3
+ - 0.1.6:
4
+ - Fixed bug in pyarrow loading of Parquet files.
5
+ - Added global config file support: settings can be persisted in `~/.config/tab/config.json`. Config file values serve as defaults that CLI flags override.
1
6
  - 0.1.5:
2
7
  - Added stdin support: use `-` as the file path to read from stdin (e.g. `cat data.csv | tab view -i csv -`). Requires `-i`/`--input-format` since format cannot be inferred. Works with `view`, `schema`, `summary`, `convert`, and `cat`.
3
8
  - Added row-wise JMESPath queries via `--jmespath` / `--jp` on `view`, `convert`, and `cat`. Object results become columns; non-object results go into a `value` column. `--sql` and `--jp` are mutually exclusive.
tab_cli-0.1.7/PKG-INFO ADDED
@@ -0,0 +1,121 @@
1
+ Metadata-Version: 2.4
2
+ Name: tab-cli
3
+ Version: 0.1.7
4
+ Summary: A CLI tool for tabular data
5
+ Author-email: Tongfei Chen <tongfei@pm.me>
6
+ License-File: LICENSE
7
+ Requires-Python: >=3.10
8
+ Requires-Dist: blobfile>=3.0
9
+ Requires-Dist: fsspec>=2025.1.0
10
+ Requires-Dist: jmespath>=1.0
11
+ Requires-Dist: loguru>=0.7.3
12
+ Requires-Dist: polars-fastavro>=0.5.1
13
+ Requires-Dist: polars>=1.0
14
+ Requires-Dist: pyarrow>=15.0
15
+ Requires-Dist: rich>=13.0
16
+ Requires-Dist: typer>=0.21.1
17
+ Provides-Extra: az
18
+ Requires-Dist: adlfs>=2025.1.0; extra == 'az'
19
+ Requires-Dist: azure-identity>=1.10.0; extra == 'az'
20
+ Provides-Extra: gs
21
+ Requires-Dist: gcsfs>=2025.1.0; extra == 'gs'
22
+ Requires-Dist: google-auth>=2.27.0; extra == 'gs'
23
+ Provides-Extra: s3
24
+ Requires-Dist: boto3>=1.28.0; extra == 's3'
25
+ Requires-Dist: s3fs>=2025.1.0; extra == 's3'
26
+ Description-Content-Type: text/markdown
27
+
28
+ # tab
29
+
30
+ [![pypi](https://img.shields.io/pypi/v/tab-cli)](https://pypi.org/project/tab-cli/)
31
+
32
+ A CLI tool for viewing, querying, and converting tabular data files.
33
+ Reads CSV, TSV, JSON Lines, Parquet, and Avro -- locally or from S3, GCS, and Azure Blob Storage.
34
+
35
+ ```sh
36
+ pip install tab-cli
37
+ ```
38
+
39
+ **Documentation**: [tongfei.me/tab](https://tongfei.me/tab)
40
+
41
+ ---
42
+
43
+ ## Quick look
44
+
45
+ ### View any tabular file
46
+
47
+ ```bash
48
+ tab view data.csv
49
+ ```
50
+
51
+ <p align="center">
52
+ <img src="https://raw.githubusercontent.com/ctongfei/tab/refs/heads/gh-pages/assets/test.svg" alt="tab view" width="680">
53
+ </p>
54
+
55
+ ### Query with SQL
56
+
57
+ The table is always available as `t`:
58
+
59
+ ```bash
60
+ tab view --sql 'SELECT * FROM t WHERE Metric_A_Value > 80' data.csv
61
+ ```
62
+
63
+ <p align="center">
64
+ <img src="https://raw.githubusercontent.com/ctongfei/tab/refs/heads/gh-pages/assets/test-where.svg" alt="tab view --sql" width="680">
65
+ </p>
66
+
67
+ ### Reshape rows with JMESPath
68
+
69
+ ```bash
70
+ tab view --jp '{id: participant.id, city: profile.address.city}' data.parquet
71
+ ```
72
+
73
+ ### Convert between formats
74
+
75
+ ```bash
76
+ tab convert data.csv data.parquet
77
+ tab convert data.parquet data.jsonl -o jsonl
78
+ tab convert data.csv output_dir/ -o parquet -n 4 # partitioned
79
+ ```
80
+
81
+ ### Concatenate files
82
+
83
+ ```bash
84
+ tab cat part1.csv part2.csv part3.csv -o jsonl > combined.jsonl
85
+ ```
86
+
87
+ ### Inspect schema and summary
88
+
89
+ ```bash
90
+ tab schema data.parquet
91
+ tab summary data.parquet
92
+ ```
93
+
94
+ ### Read from stdin
95
+
96
+ ```bash
97
+ curl -s https://example.com/data.csv | tab view -i csv -
98
+ ```
99
+
100
+ ### Read from cloud storage
101
+
102
+ ```bash
103
+ tab view s3://bucket/path/data.parquet
104
+ tab view gs://bucket/path/data.csv
105
+ tab view az://container/path/data.jsonl
106
+ ```
107
+
108
+ Install cloud extras as needed:
109
+
110
+ ```sh
111
+ pip install 'tab-cli[s3]' # AWS S3
112
+ pip install 'tab-cli[gs]' # Google Cloud Storage
113
+ pip install 'tab-cli[az]' # Azure Blob Storage
114
+ ```
115
+
116
+ ## Supported formats
117
+ - csv
118
+ - tsv
119
+ - jsonl
120
+ - parquet
121
+ - avro
@@ -0,0 +1,94 @@
1
+ # tab
2
+
3
+ [![pypi](https://img.shields.io/pypi/v/tab-cli)](https://pypi.org/project/tab-cli/)
4
+
5
+ A CLI tool for viewing, querying, and converting tabular data files.
6
+ Reads CSV, TSV, JSON Lines, Parquet, and Avro -- locally or from S3, GCS, and Azure Blob Storage.
7
+
8
+ ```sh
9
+ pip install tab-cli
10
+ ```
11
+
12
+ **Documentation**: [tongfei.me/tab](https://tongfei.me/tab)
13
+
14
+ ---
15
+
16
+ ## Quick look
17
+
18
+ ### View any tabular file
19
+
20
+ ```bash
21
+ tab view data.csv
22
+ ```
23
+
24
+ <p align="center">
25
+ <img src="https://raw.githubusercontent.com/ctongfei/tab/refs/heads/gh-pages/assets/test.svg" alt="tab view" width="680">
26
+ </p>
27
+
28
+ ### Query with SQL
29
+
30
+ The table is always available as `t`:
31
+
32
+ ```bash
33
+ tab view --sql 'SELECT * FROM t WHERE Metric_A_Value > 80' data.csv
34
+ ```
35
+
36
+ <p align="center">
37
+ <img src="https://raw.githubusercontent.com/ctongfei/tab/refs/heads/gh-pages/assets/test-where.svg" alt="tab view --sql" width="680">
38
+ </p>
39
+
40
+ ### Reshape rows with JMESPath
41
+
42
+ ```bash
43
+ tab view --jp '{id: participant.id, city: profile.address.city}' data.parquet
44
+ ```
45
+
46
+ ### Convert between formats
47
+
48
+ ```bash
49
+ tab convert data.csv data.parquet
50
+ tab convert data.parquet data.jsonl -o jsonl
51
+ tab convert data.csv output_dir/ -o parquet -n 4 # partitioned
52
+ ```
53
+
54
+ ### Concatenate files
55
+
56
+ ```bash
57
+ tab cat part1.csv part2.csv part3.csv -o jsonl > combined.jsonl
58
+ ```
59
+
60
+ ### Inspect schema and summary
61
+
62
+ ```bash
63
+ tab schema data.parquet
64
+ tab summary data.parquet
65
+ ```
66
+
67
+ ### Read from stdin
68
+
69
+ ```bash
70
+ curl -s https://example.com/data.csv | tab view -i csv -
71
+ ```
72
+
73
+ ### Read from cloud storage
74
+
75
+ ```bash
76
+ tab view s3://bucket/path/data.parquet
77
+ tab view gs://bucket/path/data.csv
78
+ tab view az://container/path/data.jsonl
79
+ ```
80
+
81
+ Install cloud extras as needed:
82
+
83
+ ```sh
84
+ pip install 'tab-cli[s3]' # AWS S3
85
+ pip install 'tab-cli[gs]' # Google Cloud Storage
86
+ pip install 'tab-cli[az]' # Azure Blob Storage
87
+ ```
88
+
89
+ ## Supported formats
90
+ - csv
91
+ - tsv
92
+ - jsonl
93
+ - parquet
94
+ - avro
@@ -0,0 +1,34 @@
1
+ # Configuration
2
+
3
+ `tab` supports a global configuration file at `~/.config/tab/config.json`. Settings in this file serve as defaults and are overridden by CLI flags.
4
+
5
+ ## Setup
6
+
7
+ Create the config file:
8
+
9
+ ```bash
10
+ mkdir -p ~/.config/tab
11
+ cat > ~/.config/tab/config.json << 'EOF'
12
+ {
13
+ "az_url_authority_is_account": false,
14
+ "sampling_size_for_schema_inference": 32
15
+ }
16
+ EOF
17
+ ```
18
+
19
+ ## Available settings
20
+
21
+ | Key | Type | Default | Description |
22
+ |-----|------|---------|-------------|
23
+ | `az_url_authority_is_account` | `bool` | `false` | Interpret `az://` URL authority as storage account name instead of container name. |
24
+ | `sampling_size_for_schema_inference` | `int` | `32` | Number of rows sampled for schema inference (e.g. when using `--jp`). |
25
+
26
+ ## Precedence
27
+
28
+ Settings are applied in this order (last wins):
29
+
30
+ 1. Built-in defaults
31
+ 2. Config file (`~/.config/tab/config.json`)
32
+ 3. CLI flags (e.g. `--az-url-authority-is-account`)
33
+
34
+ If the config file does not exist, built-in defaults are used. Unknown keys in the file are ignored with a warning.
@@ -31,6 +31,7 @@ repo_url: 'https://github.com/ctongfei/tab'
31
31
 
32
32
  nav:
33
33
  - 'Introduction': 'index.md'
34
+ - 'Configuration': 'configuration.md'
34
35
  - 'Cloud support': 'cloud.md'
35
36
  - 'CLI reference': 'cli-ref.md'
36
37
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "tab-cli"
3
- version = "0.1.5"
3
+ version = "0.1.7"
4
4
  description = "A CLI tool for tabular data"
5
5
  authors = [{name = "Tongfei Chen", email = "tongfei@pm.me"}]
6
6
  readme = "README.md"
@@ -20,8 +20,8 @@ dependencies = [
20
20
 
21
21
  [project.optional-dependencies]
22
22
  s3 = ["s3fs>=2025.1.0", "boto3>=1.28.0"]
23
- gcs = ["gcsfs>=2025.1.0", "google-auth>=2.27.0"]
24
- azure = ["adlfs>=2025.1.0", "azure-identity>=1.10.0"]
23
+ gs = ["gcsfs>=2025.1.0", "google-auth>=2.27.0"]
24
+ az = ["adlfs>=2025.1.0", "azure-identity>=1.10.0"]
25
25
 
26
26
  [dependency-groups]
27
27
  dev = [
@@ -12,27 +12,67 @@ from rich.console import Console
12
12
  from rich.logging import RichHandler
13
13
 
14
14
  from tab_cli import config
15
- from tab_cli.config import Config
16
- from tab_cli.handlers import TableWriter, infer_reader, infer_writer, is_stdin, read_stdin
15
+ from tab_cli.config import Config, load_config_file
16
+ from tab_cli.handlers import (
17
+ TableWriter,
18
+ infer_reader,
19
+ infer_writer,
20
+ is_stdin,
21
+ read_stdin,
22
+ )
17
23
  from tab_cli.handlers.base import TableSchema, TableSummary
18
24
 
19
25
  # Reusable type aliases for common CLI options
20
- PathArg: TypeAlias = Annotated[str, typer.Argument(help="Path to the data file or directory")]
21
- PathsArg: TypeAlias = Annotated[list[str], typer.Argument(help="Paths to the data files or directories")]
22
- SrcArg: TypeAlias = Annotated[str, typer.Argument(help="Path to the source file or directory")]
23
- DstArg: TypeAlias = Annotated[str, typer.Argument(help="Path to the destination file or directory")]
24
- InputOpt: TypeAlias = Annotated[Optional[str], typer.Option("-i", "--input-format", help="Input format, auto-detected from extension if omitted")]
25
- OutputOpt: TypeAlias = Annotated[Optional[str], typer.Option("-o", "--output-format", help="Output format")]
26
- SqlOpt: TypeAlias = Annotated[Optional[str], typer.Option("--sql", help="SQL query to apply (table is available as 't')")]
26
+ PathArg: TypeAlias = Annotated[
27
+ str, typer.Argument(help="Path to the data file or directory")
28
+ ]
29
+ PathsArg: TypeAlias = Annotated[
30
+ list[str], typer.Argument(help="Paths to the data files or directories")
31
+ ]
32
+ SrcArg: TypeAlias = Annotated[
33
+ str, typer.Argument(help="Path to the source file or directory")
34
+ ]
35
+ DstArg: TypeAlias = Annotated[
36
+ str, typer.Argument(help="Path to the destination file or directory")
37
+ ]
38
+ InputOpt: TypeAlias = Annotated[
39
+ Optional[str],
40
+ typer.Option(
41
+ "-i",
42
+ "--input-format",
43
+ help="Input format, auto-detected from extension if omitted",
44
+ ),
45
+ ]
46
+ OutputOpt: TypeAlias = Annotated[
47
+ Optional[str], typer.Option("-o", "--output-format", help="Output format")
48
+ ]
49
+ SqlOpt: TypeAlias = Annotated[
50
+ Optional[str],
51
+ typer.Option("--sql", help="SQL query to apply (table is available as 't')"),
52
+ ]
27
53
  JmespathOpt: TypeAlias = Annotated[
28
54
  Optional[str],
29
- typer.Option("--jmespath", "--jp", help="JMESPath expression to apply to each row as JSON"),
55
+ typer.Option(
56
+ "--jmespath", "--jp", help="JMESPath expression to apply to each row as JSON"
57
+ ),
58
+ ]
59
+ LimitOpt: TypeAlias = Annotated[
60
+ Optional[int], typer.Option("--limit", help="Maximum number of rows to display")
61
+ ]
62
+ SkipOpt: TypeAlias = Annotated[
63
+ int, typer.Option("--skip", help="Number of rows to skip")
64
+ ]
65
+ MaxCellLenOpt: TypeAlias = Annotated[
66
+ Optional[int],
67
+ typer.Option("--max-cell-len", help="Truncate cell contents longer than this"),
68
+ ]
69
+ TableSvgOpt: TypeAlias = Annotated[
70
+ bool, typer.Option("--table-svg", help="Output table as SVG")
71
+ ]
72
+ NumPartitionsOpt: TypeAlias = Annotated[
73
+ Optional[int],
74
+ typer.Option("-n", "--num-partitions", help="Number of output partitions"),
30
75
  ]
31
- LimitOpt: TypeAlias = Annotated[Optional[int], typer.Option("--limit", help="Maximum number of rows to display")]
32
- SkipOpt: TypeAlias = Annotated[int, typer.Option("--skip", help="Number of rows to skip")]
33
- MaxCellLenOpt: TypeAlias = Annotated[Optional[int], typer.Option("--max-cell-len", help="Truncate cell contents longer than this")]
34
- TableSvgOpt: TypeAlias = Annotated[bool, typer.Option("--table-svg", help="Output table as SVG")]
35
- NumPartitionsOpt: TypeAlias = Annotated[Optional[int], typer.Option("-n", "--num-partitions", help="Number of output partitions")]
36
76
 
37
77
  app = typer.Typer(
38
78
  help="A CLI tool for viewing and manipulating tabular data.",
@@ -51,11 +91,12 @@ def main_callback(
51
91
  ] = False,
52
92
  log_level: Annotated[
53
93
  str,
54
- typer.Option("--log-level", help="Log level from {DEBUG, INFO, WARNING, ERROR, CRITICAL}"),
94
+ typer.Option(
95
+ "--log-level", help="Log level from {DEBUG, INFO, WARNING, ERROR, CRITICAL}"
96
+ ),
55
97
  ] = "INFO",
56
98
  ) -> None:
57
99
  """Global options for tab_cli CLI."""
58
- config.config.az_url_authority_is_account = az_url_authority_is_account
59
100
  logger.remove()
60
101
  logger.add(
61
102
  RichHandler(
@@ -66,6 +107,10 @@ def main_callback(
66
107
  format="{message}",
67
108
  level=log_level.upper(),
68
109
  )
110
+ load_config_file()
111
+ # CLI flags override config file values
112
+ if az_url_authority_is_account:
113
+ config.config.az_url_authority_is_account = az_url_authority_is_account
69
114
 
70
115
 
71
116
  def _apply_sql(lf: pl.LazyFrame, sql: str | None) -> pl.LazyFrame:
@@ -94,21 +139,29 @@ def _transform_jmespath_batch(
94
139
  if mode is None:
95
140
  mode = "object"
96
141
  elif mode != "object":
97
- raise ValueError("JMESPath query must return a consistent shape across rows")
142
+ raise ValueError(
143
+ "JMESPath query must return a consistent shape across rows"
144
+ )
98
145
 
99
146
  if expected_columns is not None:
100
147
  extra_columns = set(result) - set(expected_columns)
101
148
  if extra_columns:
102
149
  extras = ", ".join(sorted(extra_columns))
103
- raise ValueError(f"JMESPath query produced unexpected columns: {extras}")
104
- normalized_row = {column: result.get(column) for column in expected_columns}
150
+ raise ValueError(
151
+ f"JMESPath query produced unexpected columns: {extras}"
152
+ )
153
+ normalized_row = {
154
+ column: result.get(column) for column in expected_columns
155
+ }
105
156
  else:
106
157
  normalized_row = result
107
158
  else:
108
159
  if mode is None:
109
160
  mode = "value"
110
161
  elif mode != "value":
111
- raise ValueError("JMESPath query must return a consistent shape across rows")
162
+ raise ValueError(
163
+ "JMESPath query must return a consistent shape across rows"
164
+ )
112
165
  normalized_row = {"value": result}
113
166
 
114
167
  rows.append(normalized_row)
@@ -143,10 +196,14 @@ def _apply_jmespath(lf: pl.LazyFrame, expression: str) -> pl.LazyFrame:
143
196
  )
144
197
 
145
198
 
146
- def _apply_query(lf: pl.LazyFrame, sql: str | None, jmespath_expr: str | None) -> pl.LazyFrame:
199
+ def _apply_query(
200
+ lf: pl.LazyFrame, sql: str | None, jmespath_expr: str | None
201
+ ) -> pl.LazyFrame:
147
202
  """Apply exactly zero or one supported query transform to a LazyFrame."""
148
203
  if sql is not None and jmespath_expr is not None:
149
- raise ValueError("At most one query may be provided: use either --sql or --jmespath/--jp")
204
+ raise ValueError(
205
+ "At most one query may be provided: use either --sql or --jmespath/--jp"
206
+ )
150
207
  if sql is not None:
151
208
  return _apply_sql(lf, sql)
152
209
  if jmespath_expr is not None:
@@ -196,11 +253,18 @@ def view(
196
253
  reader = infer_reader(path, format=input)
197
254
  lf = reader.read(path)
198
255
  lf = _apply_query(lf, sql=sql, jmespath_expr=jmespath_expr)
199
- lf, truncated = _apply_limit(lf, limit=limit, skip=skip, default_limit=20 if limit is None else None)
200
- writer = infer_writer("table-svg" if table_svg else None, truncated=truncated, max_cell_len=max_cell_len)
256
+ lf, truncated = _apply_limit(
257
+ lf, limit=limit, skip=skip, default_limit=20 if limit is None else None
258
+ )
259
+ writer = infer_writer(
260
+ "table-svg" if table_svg else None,
261
+ truncated=truncated,
262
+ max_cell_len=max_cell_len,
263
+ )
201
264
  for chunk in writer.write(lf):
202
265
  sys.stdout.buffer.write(chunk)
203
266
 
267
+
204
268
  @app.command()
205
269
  def schema(
206
270
  path: PathArg,
@@ -258,7 +322,9 @@ def convert(
258
322
  elif input is not None:
259
323
  writer = infer_writer(format=input)
260
324
  else:
261
- raise ValueError("Output format (-o/--output-format) is required when reading from stdin (-)")
325
+ raise ValueError(
326
+ "Output format (-o/--output-format) is required when reading from stdin (-)"
327
+ )
262
328
  assert isinstance(writer, TableWriter)
263
329
  writer.write_to_path(lf, dst, partitions=num_partitions)
264
330
  else:
@@ -305,7 +371,9 @@ def cat(
305
371
  writer = infer_writer(format=input)
306
372
  assert isinstance(writer, TableWriter)
307
373
  else:
308
- raise ValueError("Output format (-o/--output-format) or input format (-i/--input-format) is required when reading from stdin (-)")
374
+ raise ValueError(
375
+ "Output format (-o/--output-format) or input format (-i/--input-format) is required when reading from stdin (-)"
376
+ )
309
377
  for chunk in writer.write(lf):
310
378
  sys.stdout.buffer.write(chunk)
311
379
 
@@ -0,0 +1,47 @@
1
+ """Global configuration for tab_cli-cli."""
2
+
3
+ import json
4
+ from dataclasses import dataclass, fields
5
+ from pathlib import Path
6
+
7
+ from loguru import logger
8
+
9
+ CONFIG_DIR = Path.home() / ".config" / "tab"
10
+ CONFIG_FILE = CONFIG_DIR / "config.json"
11
+
12
+
13
+ @dataclass
14
+ class Config:
15
+ """Global configuration settings."""
16
+
17
+ az_url_authority_is_account: bool = False
18
+ sampling_size_for_schema_inference: int = 32
19
+
20
+
21
+ # Global config instance
22
+ config: Config = Config()
23
+
24
+
25
+ def load_config_file(path: Path = CONFIG_FILE) -> None:
26
+ """Load settings from a JSON config file into the global config.
27
+
28
+ Unknown keys are logged and ignored. Type mismatches raise ValueError.
29
+ If the file does not exist, this is a no-op.
30
+ """
31
+ if not path.is_file():
32
+ return
33
+
34
+ text = path.read_text(encoding="utf-8")
35
+ data = json.loads(text)
36
+ if not isinstance(data, dict):
37
+ raise ValueError(
38
+ f"Config file must contain a JSON object, got {type(data).__name__}"
39
+ )
40
+
41
+ known = {f.name: f.type for f in fields(Config)}
42
+ for key, value in data.items():
43
+ if key not in known:
44
+ logger.warning("Unknown config key '{}' in {}", key, path)
45
+ continue
46
+ setattr(config, key, value)
47
+ logger.debug("Loaded config from {}", path)
@@ -30,7 +30,7 @@ def _scan_parquet_with_pyarrow_fallback(
30
30
  "Polars native Parquet reader failed ({}), retrying with PyArrow backend",
31
31
  e,
32
32
  )
33
- return pl.scan_parquet(url, storage_options=storage_options, use_pyarrow=True)
33
+ return pl.read_parquet(url, storage_options=storage_options, use_pyarrow=True).lazy()
34
34
 
35
35
 
36
36
  class ParquetFormat(FormatHandler):