datajunction 0.0.183__tar.gz → 0.0.184__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 (183) hide show
  1. {datajunction-0.0.183 → datajunction-0.0.184}/Makefile +1 -1
  2. {datajunction-0.0.183 → datajunction-0.0.184}/PKG-INFO +2 -3
  3. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/__about__.py +1 -1
  4. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/_internal.py +2 -12
  5. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/cli.py +32 -4
  6. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/deployment.py +26 -2
  7. {datajunction-0.0.183 → datajunction-0.0.184}/pyproject.toml +1 -1
  8. {datajunction-0.0.183 → datajunction-0.0.184}/tests/test_cli.py +110 -0
  9. {datajunction-0.0.183 → datajunction-0.0.184}/.coveragerc +0 -0
  10. {datajunction-0.0.183 → datajunction-0.0.184}/.gitignore +0 -0
  11. {datajunction-0.0.183 → datajunction-0.0.184}/.pre-commit-config.yaml +0 -0
  12. {datajunction-0.0.183 → datajunction-0.0.184}/LICENSE.txt +0 -0
  13. {datajunction-0.0.183 → datajunction-0.0.184}/README.md +0 -0
  14. {datajunction-0.0.183 → datajunction-0.0.184}/claude_desktop_config.example.json +0 -0
  15. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/__init__.py +0 -0
  16. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/_base.py +0 -0
  17. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/admin.py +0 -0
  18. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/builder.py +0 -0
  19. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/client.py +0 -0
  20. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/compile.py +0 -0
  21. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/exceptions.py +0 -0
  22. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/mcp/__init__.py +0 -0
  23. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/mcp/cli.py +0 -0
  24. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/mcp/config.py +0 -0
  25. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/models.py +0 -0
  26. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/nodes.py +0 -0
  27. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/rendering.py +0 -0
  28. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/seed/init_system_nodes.py +0 -0
  29. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/seed/nodes/date.yaml +0 -0
  30. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/seed/nodes/deployment.yaml +0 -0
  31. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/seed/nodes/dimension_link.yaml +0 -0
  32. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/seed/nodes/distinct_node_authors.yaml +0 -0
  33. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/seed/nodes/distinct_node_editors.yaml +0 -0
  34. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/seed/nodes/dj.yaml +0 -0
  35. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/seed/nodes/is_active.yaml +0 -0
  36. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/seed/nodes/materialization.yaml +0 -0
  37. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/seed/nodes/median_deployment_duration_seconds.yaml +0 -0
  38. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/seed/nodes/median_dim_links_per_node.yaml +0 -0
  39. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/seed/nodes/median_dimension_indegree.yaml +0 -0
  40. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/seed/nodes/median_downstream_count.yaml +0 -0
  41. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/seed/nodes/median_revisions_per_node.yaml +0 -0
  42. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/seed/nodes/median_upstream_count.yaml +0 -0
  43. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/seed/nodes/namespace.yaml +0 -0
  44. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/seed/nodes/node_revision.yaml +0 -0
  45. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/seed/nodes/node_type.yaml +0 -0
  46. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/seed/nodes/nodes.yaml +0 -0
  47. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/seed/nodes/number_of_branches.yaml +0 -0
  48. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/seed/nodes/number_of_deployments.yaml +0 -0
  49. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/seed/nodes/number_of_materializations.yaml +0 -0
  50. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/seed/nodes/number_of_namespaces.yaml +0 -0
  51. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/seed/nodes/number_of_nodes.yaml +0 -0
  52. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/seed/nodes/number_of_orphan_nodes.yaml +0 -0
  53. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/seed/nodes/number_of_unused_dimensions.yaml +0 -0
  54. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/seed/nodes/repo.yaml +0 -0
  55. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/seed/nodes/user.yaml +0 -0
  56. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/skills/datajunction-api.md +0 -0
  57. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/skills/datajunction-query.md +0 -0
  58. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/skills/datajunction-repo.md +0 -0
  59. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/skills/datajunction-semantic-model.md +0 -0
  60. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/skills/datajunction.md +0 -0
  61. {datajunction-0.0.183 → datajunction-0.0.184}/datajunction/tags.py +0 -0
  62. {datajunction-0.0.183 → datajunction-0.0.184}/setup.cfg +0 -0
  63. {datajunction-0.0.183 → datajunction-0.0.184}/tests/__init__.py +0 -0
  64. {datajunction-0.0.183 → datajunction-0.0.184}/tests/conftest.py +0 -0
  65. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/deploy0/dj.yaml +0 -0
  66. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/deploy0/roads/companies.yaml +0 -0
  67. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/deploy0/roads/companies_dim.yaml +0 -0
  68. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/deploy0/roads/contractor.yaml +0 -0
  69. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/deploy0/roads/contractors.yaml +0 -0
  70. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/deploy0/roads/us_state.yaml +0 -0
  71. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/deploy0/roads/us_states.yaml +0 -0
  72. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project1/dj.yaml +0 -0
  73. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project1/roads/avg_length_of_employment.metric.yaml +0 -0
  74. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project1/roads/avg_repair_price.metric.yaml +0 -0
  75. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project1/roads/avg_time_to_dispatch.metric.yaml +0 -0
  76. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project1/roads/contractor.dimension.yaml +0 -0
  77. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project1/roads/contractors.source.yaml +0 -0
  78. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project1/roads/date.source.yaml +0 -0
  79. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project1/roads/date_dim.dimension.yaml +0 -0
  80. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project1/roads/dispatcher.dimension.yaml +0 -0
  81. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project1/roads/dispatchers.source.yaml +0 -0
  82. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project1/roads/hard_hat.dimension.yaml +0 -0
  83. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project1/roads/hard_hat_state.source.yaml +0 -0
  84. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project1/roads/hard_hats.source.yaml +0 -0
  85. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project1/roads/local_hard_hats.dimension.yaml +0 -0
  86. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project1/roads/municipality.source.yaml +0 -0
  87. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project1/roads/municipality_dim.dimension.yaml +0 -0
  88. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project1/roads/municipality_municipality_type.source.yaml +0 -0
  89. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project1/roads/municipality_type.source.yaml +0 -0
  90. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project1/roads/national_level_agg.transform.yaml +0 -0
  91. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project1/roads/num_repair_orders.metric.yaml +0 -0
  92. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project1/roads/regional_level_agg.transform.yaml +0 -0
  93. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project1/roads/regional_repair_efficiency.metric.yaml +0 -0
  94. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project1/roads/repair_order.dimension.yaml +0 -0
  95. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project1/roads/repair_order_details.source.yaml +0 -0
  96. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project1/roads/repair_order_transform.transform.yaml +0 -0
  97. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project1/roads/repair_orders.source.yaml +0 -0
  98. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project1/roads/repair_orders_cube.cube.yaml +0 -0
  99. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project1/roads/repair_type.source.yaml +0 -0
  100. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project1/roads/total_repair_cost.metric.yaml +0 -0
  101. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project1/roads/total_repair_order_discounts.metric.yaml +0 -0
  102. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project1/roads/us_region.source.yaml +0 -0
  103. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project1/roads/us_state.dimension.yaml +0 -0
  104. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project1/roads/us_states.source.yaml +0 -0
  105. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project10/dj.yaml +0 -0
  106. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project11/avg_length_of_employment.metric.yaml +0 -0
  107. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project11/avg_repair_price.metric.yaml +0 -0
  108. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project11/avg_time_to_dispatch.metric.yaml +0 -0
  109. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project11/contractor.dimension.yaml +0 -0
  110. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project11/contractors.source.yaml +0 -0
  111. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project11/date.source.yaml +0 -0
  112. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project11/date_dim.dimension.yaml +0 -0
  113. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project11/dispatcher.dimension.yaml +0 -0
  114. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project11/dispatchers.source.yaml +0 -0
  115. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project11/dj.yaml +0 -0
  116. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project11/hard_hat.dimension.yaml +0 -0
  117. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project11/hard_hat_state.source.yaml +0 -0
  118. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project11/hard_hats.source.yaml +0 -0
  119. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project11/local_hard_hats.dimension.yaml +0 -0
  120. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project11/municipality.source.yaml +0 -0
  121. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project11/municipality_dim.dimension.yaml +0 -0
  122. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project11/municipality_municipality_type.source.yaml +0 -0
  123. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project11/municipality_type.source.yaml +0 -0
  124. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project11/national_level_agg.transform.yaml +0 -0
  125. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project11/num_repair_orders.metric.yaml +0 -0
  126. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project11/regional_level_agg.transform.yaml +0 -0
  127. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project11/regional_repair_efficiency.metric.yaml +0 -0
  128. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project11/repair_order.dimension.yaml +0 -0
  129. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project11/repair_order_details.source.yaml +0 -0
  130. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project11/repair_order_transform.transform.yaml +0 -0
  131. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project11/repair_orders.source.yaml +0 -0
  132. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project11/repair_orders_cube.cube.yaml +0 -0
  133. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project11/repair_type.source.yaml +0 -0
  134. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project11/total_repair_cost.metric.yaml +0 -0
  135. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project11/total_repair_order_discounts.metric.yaml +0 -0
  136. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project11/us_region.source.yaml +0 -0
  137. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project11/us_state.dimension.yaml +0 -0
  138. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project11/us_states.source.yaml +0 -0
  139. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project12/dj.yaml +0 -0
  140. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project12/roads/companies.source.yaml +0 -0
  141. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project12/roads/companies_dim.dimension.yaml +0 -0
  142. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project12/roads/contractor.dimension.yaml +0 -0
  143. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project12/roads/contractors.source.yaml +0 -0
  144. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project12/roads/us_state.dimension.yaml +0 -0
  145. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project12/roads/us_states.source.yaml +0 -0
  146. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project2/dj.yaml +0 -0
  147. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project2/some_node.source.yaml +0 -0
  148. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project3/dj.yaml +0 -0
  149. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project3/some_node.yaml +0 -0
  150. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project4/dj.yaml +0 -0
  151. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project4/very/very/deeply/nested/namespace/some_node.source.yaml +0 -0
  152. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project5/dj.yaml +0 -0
  153. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project5/some_node.a.b.c.source.yaml +0 -0
  154. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project6/dj.yaml +0 -0
  155. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project6/roads/contractor.dimension.yaml +0 -0
  156. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project6/roads/contractors.source.yaml +0 -0
  157. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project7/dj.yaml +0 -0
  158. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project7/roads/contractor.dimension.yaml +0 -0
  159. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project7/roads/contractors.source.yaml +0 -0
  160. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project8/dj.yaml +0 -0
  161. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project9/dj.yaml +0 -0
  162. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project9/roads/companies.source.yaml +0 -0
  163. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project9/roads/companies_dim.dimension.yaml +0 -0
  164. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project9/roads/contractor.dimension.yaml +0 -0
  165. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project9/roads/contractors.source.yaml +0 -0
  166. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project9/roads/us_state.dimension.yaml +0 -0
  167. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples/project9/roads/us_states.source.yaml +0 -0
  168. {datajunction-0.0.183 → datajunction-0.0.184}/tests/examples.py +0 -0
  169. {datajunction-0.0.183 → datajunction-0.0.184}/tests/mcp/README.md +0 -0
  170. {datajunction-0.0.183 → datajunction-0.0.184}/tests/mcp/__init__.py +0 -0
  171. {datajunction-0.0.183 → datajunction-0.0.184}/tests/mcp/test_cli.py +0 -0
  172. {datajunction-0.0.183 → datajunction-0.0.184}/tests/test__internal.py +0 -0
  173. {datajunction-0.0.183 → datajunction-0.0.184}/tests/test_admin.py +0 -0
  174. {datajunction-0.0.183 → datajunction-0.0.184}/tests/test_base.py +0 -0
  175. {datajunction-0.0.183 → datajunction-0.0.184}/tests/test_builder.py +0 -0
  176. {datajunction-0.0.183 → datajunction-0.0.184}/tests/test_client.py +0 -0
  177. {datajunction-0.0.183 → datajunction-0.0.184}/tests/test_compile.py +0 -0
  178. {datajunction-0.0.183 → datajunction-0.0.184}/tests/test_deploy.py +0 -0
  179. {datajunction-0.0.183 → datajunction-0.0.184}/tests/test_generated_client.py +0 -0
  180. {datajunction-0.0.183 → datajunction-0.0.184}/tests/test_integration.py +0 -0
  181. {datajunction-0.0.183 → datajunction-0.0.184}/tests/test_models.py +0 -0
  182. {datajunction-0.0.183 → datajunction-0.0.184}/tests/test_skills.py +0 -0
  183. {datajunction-0.0.183 → datajunction-0.0.184}/tox.ini +0 -0
@@ -1,5 +1,5 @@
1
1
  setup:
2
- uv sync --extra mcp --group test --extra pandas
2
+ uv sync --extra mcp --group test
3
3
  check:
4
4
  uv run pre-commit run --all-files
5
5
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: datajunction
3
- Version: 0.0.183
3
+ Version: 0.0.184
4
4
  Summary: DataJunction client library for connecting to a DataJunction server
5
5
  Project-URL: repository, https://github.com/DataJunction/dj
6
6
  Author-email: DataJunction Authors <yian.shang@gmail.com>
@@ -14,6 +14,7 @@ Classifier: Programming Language :: Python :: 3.12
14
14
  Requires-Python: <4.0,>=3.10
15
15
  Requires-Dist: alive-progress>=3.1.2
16
16
  Requires-Dist: httpx>=0.27.0
17
+ Requires-Dist: pandas>=2.0.2
17
18
  Requires-Dist: pytest-xdist>=3.5.0
18
19
  Requires-Dist: pyyaml>=6.0.1
19
20
  Requires-Dist: requests<3.0.0,>=2.28.2
@@ -22,8 +23,6 @@ Provides-Extra: mcp
22
23
  Requires-Dist: mcp>=1.0.0; extra == 'mcp'
23
24
  Requires-Dist: pydantic-settings>=2.10.1; extra == 'mcp'
24
25
  Requires-Dist: pydantic>=2.0; extra == 'mcp'
25
- Provides-Extra: pandas
26
- Requires-Dist: pandas>=2.0.2; extra == 'pandas'
27
26
  Description-Content-Type: text/markdown
28
27
 
29
28
  # DataJunction Python Client
@@ -2,4 +2,4 @@
2
2
  Version for Hatch
3
3
  """
4
4
 
5
- __version__ = "0.0.183"
5
+ __version__ = "0.0.184"
@@ -4,21 +4,11 @@
4
4
  import logging
5
5
  import os
6
6
  import platform
7
- import warnings
8
7
  from dataclasses import asdict, dataclass
9
8
  from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, TypedDict, Union
10
9
  from urllib.parse import urljoin
11
10
 
12
- try:
13
- import pandas as pd
14
- except ImportError: # pragma: no cover
15
- warnings.warn(
16
- (
17
- "Optional dependency `pandas` not found, data retrieval"
18
- "disabled. You can install pandas by running `pip install pandas`."
19
- ),
20
- ImportWarning,
21
- )
11
+ import pandas as pd
22
12
  import requests
23
13
  from requests.adapters import CaseInsensitiveDict, HTTPAdapter
24
14
 
@@ -271,7 +261,7 @@ class DJClient:
271
261
  @staticmethod
272
262
  def process_results(results) -> "pd.DataFrame":
273
263
  """
274
- Return a pandas dataframe of the results if pandas is installed
264
+ Return a pandas dataframe of the results
275
265
  """
276
266
  if "results" in results and results["results"]:
277
267
  columns = results["results"][0]["columns"]
@@ -601,10 +601,15 @@ class DJCLI:
601
601
  )
602
602
  return
603
603
 
604
- # Handle error responses
605
- if isinstance(result, dict) and "message" in result:
606
- console.print(f"[bold red]ERROR:[/bold red] {result['message']}")
607
- return
604
+ # Handle error responses and raw dict responses.
605
+ # data() / node_data() should return a DataFrame via process_results,
606
+ # but if the raw query response dict is returned instead, try to
607
+ # process it here rather than crashing on result.columns.
608
+ if isinstance(result, dict):
609
+ if "message" in result:
610
+ console.print(f"[bold red]ERROR:[/bold red] {result['message']}")
611
+ return
612
+ result = self.builder_client.process_results(result)
608
613
 
609
614
  # result should be a DataFrame (already limited by API)
610
615
  if format == "json":
@@ -958,6 +963,27 @@ class DJCLI:
958
963
  default="GITHUB_TOKEN",
959
964
  help="Name of the env var holding the GitHub token (default: GITHUB_TOKEN)",
960
965
  )
966
+ codeowners_parser.add_argument(
967
+ "--default-owner",
968
+ type=str,
969
+ default=None,
970
+ help=(
971
+ "Owner for a leading `* <owner>` rule. Unmatched files and any "
972
+ "--exclude'd directories fall through to it (e.g. '@org/team')."
973
+ ),
974
+ )
975
+ codeowners_parser.add_argument(
976
+ "--exclude",
977
+ action="append",
978
+ default=None,
979
+ dest="exclude_dirs",
980
+ metavar="DIR",
981
+ help=(
982
+ "Directory (relative to <directory>) whose nodes get no per-file "
983
+ "owners — they fall through to --default-owner. Repeatable. Use for "
984
+ "machine-generated trees like 'nodes/generated'."
985
+ ),
986
+ )
961
987
 
962
988
  # `dj pull <namespace> <directory>`
963
989
  pull_parser = subparsers.add_parser(
@@ -1489,6 +1515,8 @@ class DJCLI:
1489
1515
  output=args.output,
1490
1516
  github_api_url=args.github_api_url,
1491
1517
  github_token_env=args.github_token_env,
1518
+ default_owner=args.default_owner,
1519
+ exclude_dirs=args.exclude_dirs,
1492
1520
  )
1493
1521
  console = Console()
1494
1522
  console.print(
@@ -304,6 +304,8 @@ class DeploymentService:
304
304
  output: str | Path = ".github/CODEOWNERS",
305
305
  github_api_url: str | None = None,
306
306
  github_token_env: str = "GITHUB_TOKEN",
307
+ default_owner: str | None = None,
308
+ exclude_dirs: list[str] | None = None,
307
309
  ) -> int:
308
310
  """
309
311
  Generate a CODEOWNERS file from the owners fields in DJ node YAML files.
@@ -317,9 +319,24 @@ class DeploymentService:
317
319
  email addresses in owners fields are resolved to GitHub usernames via the
318
320
  search API. Unresolvable emails are emitted as-is with a warning comment.
319
321
 
320
- Returns the number of entries written.
322
+ ``default_owner``, when set, emits a leading ``* <default_owner>`` rule so
323
+ unmatched files (and any excluded directories) fall through to it. Because
324
+ CODEOWNERS is last-match-wins, the per-file rules below it still take
325
+ precedence for the files they name.
326
+
327
+ ``exclude_dirs`` lists directories (relative to base_dir) whose nodes are
328
+ NOT given per-file owners — they fall through to ``default_owner`` instead.
329
+ This is for machine-generated trees (e.g. ``nodes/generated``) that have no
330
+ individual human owner and should be team-owned as a block.
331
+
332
+ Returns the number of per-file entries written (excludes the default rule).
321
333
  """
322
334
  base = Path(base_dir).resolve()
335
+ excluded_dirs = [(base / d).resolve() for d in (exclude_dirs or [])]
336
+
337
+ def _is_excluded(path: Path) -> bool:
338
+ return any(d == path or d in path.parents for d in excluded_dirs)
339
+
323
340
  _token = os.getenv(github_token_env)
324
341
  # Only resolve if both API URL and token are available
325
342
  lookup: tuple[str, str] | None = (
@@ -353,6 +370,8 @@ class DeploymentService:
353
370
  for path in sorted(base.rglob("*.yaml")):
354
371
  if path.name == "dj.yaml":
355
372
  continue
373
+ if _is_excluded(path):
374
+ continue
356
375
  try:
357
376
  node = DeploymentService.read_yaml_file(path)
358
377
  except Exception: # skip unreadable / non-dict files
@@ -376,7 +395,12 @@ class DeploymentService:
376
395
  )
377
396
  for w in warnings:
378
397
  lines.append(f"# {w}")
379
- lines += ["", *entries, ""]
398
+ lines.append("")
399
+ # Default rule first so per-file rules below win (last-match-wins).
400
+ if default_owner:
401
+ lines.append(f"* {default_owner}")
402
+ lines.append("")
403
+ lines += [*entries, ""]
380
404
  content = "\n".join(lines)
381
405
 
382
406
  output_path = Path(output)
@@ -16,6 +16,7 @@ dependencies = [
16
16
  "rich>=13.7.0",
17
17
  "pytest-xdist>=3.5.0",
18
18
  "httpx>=0.27.0",
19
+ "pandas>=2.0.2",
19
20
  ]
20
21
  requires-python = ">=3.10,<4.0"
21
22
  readme = "README.md"
@@ -29,7 +30,6 @@ classifiers = [
29
30
  ]
30
31
 
31
32
  [project.optional-dependencies]
32
- pandas = ["pandas>=2.0.2"]
33
33
  # Optional dependencies for the dj-mcp stdio→HTTP proxy CLI. plotext was
34
34
  # previously needed for client-side rendering of `visualize_metrics`; that
35
35
  # logic now lives server-side in datajunction-server, so the client only
@@ -744,6 +744,32 @@ def test_data_with_error_response(builder_client: DJBuilder, capsys):
744
744
  assert "Test error message from data API" in captured.out
745
745
 
746
746
 
747
+ def test_data_with_raw_dict_response(builder_client: DJBuilder, capsys):
748
+ """
749
+ Test `dj data` handles a raw query response dict (no "message" key) by
750
+ passing it through process_results (covers line 612).
751
+ """
752
+ import pandas as pd
753
+
754
+ raw_response = {"results": [{"columns": [], "rows": []}], "errors": []}
755
+ mock_df = pd.DataFrame()
756
+ with patch.object(builder_client, "data", return_value=raw_response):
757
+ with mock.patch(
758
+ "datajunction._internal.DJClient.process_results",
759
+ return_value=mock_df,
760
+ ) as mock_process:
761
+ test_args = ["dj", "data", "--metrics", "some.metric"]
762
+ with patch.dict(
763
+ os.environ,
764
+ {"DJ_USER": "datajunction", "DJ_PWD": "datajunction"},
765
+ clear=False,
766
+ ):
767
+ with patch.object(sys, "argv", test_args):
768
+ main(builder_client=builder_client)
769
+
770
+ mock_process.assert_called_once_with(raw_response)
771
+
772
+
747
773
  def test_data_with_limit(builder_client: DJBuilder): # pylint: disable=redefined-outer-name
748
774
  """
749
775
  Test `dj data` with explicit --limit flag (covers effective_limit usage)
@@ -2346,6 +2372,57 @@ class TestGenerateCodeowners:
2346
2372
  assert "/revenue.metric.yaml alice@example.com" in content
2347
2373
  assert "no_owner" not in content
2348
2374
 
2375
+ def test_default_owner_emitted_first(self, tmp_path):
2376
+ """default_owner adds a leading `* <owner>` rule before per-file rules."""
2377
+ from datajunction.deployment import DeploymentService
2378
+
2379
+ self._write_node(tmp_path, "revenue.metric.yaml", owners=["alice@example.com"])
2380
+ output = tmp_path / "CODEOWNERS"
2381
+
2382
+ count = DeploymentService.build_codeowners(
2383
+ tmp_path,
2384
+ output=output,
2385
+ default_owner="@org/team",
2386
+ )
2387
+
2388
+ content = output.read_text()
2389
+ lines = [ln for ln in content.splitlines() if ln and not ln.startswith("#")]
2390
+ # The `*` rule comes before the per-file rule so per-file wins (last-match).
2391
+ assert lines[0] == "* @org/team"
2392
+ assert "/revenue.metric.yaml alice@example.com" in content
2393
+ assert content.index("* @org/team") < content.index("/revenue.metric.yaml")
2394
+ # count is per-file entries only, not the default rule
2395
+ assert count == 1
2396
+
2397
+ def test_exclude_dir_falls_through_to_default(self, tmp_path):
2398
+ """Nodes under an excluded dir get no per-file rule (team-owned via default)."""
2399
+ from datajunction.deployment import DeploymentService
2400
+
2401
+ generated = tmp_path / "nodes" / "generated"
2402
+ generated.mkdir(parents=True)
2403
+ authored = tmp_path / "nodes"
2404
+ self._write_node(generated, "account_d.yaml", owners=["bot@example.com"])
2405
+ self._write_node(
2406
+ authored,
2407
+ "shoot_volume.metric.yaml",
2408
+ owners=["alice@example.com"],
2409
+ )
2410
+
2411
+ output = tmp_path / "CODEOWNERS"
2412
+ count = DeploymentService.build_codeowners(
2413
+ tmp_path,
2414
+ output=output,
2415
+ default_owner="@org/team",
2416
+ exclude_dirs=["nodes/generated"],
2417
+ )
2418
+
2419
+ content = output.read_text()
2420
+ # Generated node is excluded -> no per-file rule, covered by the default.
2421
+ assert "account_d.yaml" not in content
2422
+ # Hand-authored node keeps its real owner.
2423
+ assert "/nodes/shoot_volume.metric.yaml alice@example.com" in content
2424
+ assert count == 1
2425
+
2349
2426
  def test_dj_yaml_is_skipped(self, tmp_path):
2350
2427
  """dj.yaml project config must never appear in CODEOWNERS."""
2351
2428
  from datajunction.deployment import DeploymentService
@@ -2520,8 +2597,41 @@ class TestGenerateCodeowners:
2520
2597
  output=str(output),
2521
2598
  github_api_url=None,
2522
2599
  github_token_env="GITHUB_TOKEN",
2600
+ default_owner=None,
2601
+ exclude_dirs=None,
2523
2602
  )
2524
2603
 
2604
+ def test_cli_generate_codeowners_default_owner_and_exclude(self, tmp_path):
2605
+ """--default-owner and repeated --exclude are forwarded to build_codeowners."""
2606
+ from datajunction.cli import DJCLI
2607
+
2608
+ cli = DJCLI(builder_client=mock.MagicMock())
2609
+
2610
+ with patch(
2611
+ "datajunction.deployment.DeploymentService.build_codeowners",
2612
+ return_value=0,
2613
+ ) as mock_build:
2614
+ with patch.object(
2615
+ sys,
2616
+ "argv",
2617
+ [
2618
+ "dj",
2619
+ "generate-codeowners",
2620
+ str(tmp_path),
2621
+ "--default-owner",
2622
+ "@org/team",
2623
+ "--exclude",
2624
+ "nodes/generated",
2625
+ "--exclude",
2626
+ "nodes/legacy",
2627
+ ],
2628
+ ):
2629
+ cli.run()
2630
+
2631
+ _, kwargs = mock_build.call_args
2632
+ assert kwargs["default_owner"] == "@org/team"
2633
+ assert kwargs["exclude_dirs"] == ["nodes/generated", "nodes/legacy"]
2634
+
2525
2635
  def test_cli_generate_codeowners_github_flags(self, tmp_path):
2526
2636
  """--github-api-url and --github-token-env are forwarded to build_codeowners."""
2527
2637
  from datajunction.cli import DJCLI
File without changes
File without changes
File without changes