@voxgig/sdkgen 1.5.0 → 2.0.0

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 (270) hide show
  1. package/dist/cmp/AgentGuideContent.js +5 -0
  2. package/dist/cmp/AgentGuideContent.js.map +1 -1
  3. package/dist/cmp/Feature.js +13 -0
  4. package/dist/cmp/Feature.js.map +1 -1
  5. package/dist/helpers/canonType.d.ts +3 -1
  6. package/dist/helpers/canonType.js +44 -1
  7. package/dist/helpers/canonType.js.map +1 -1
  8. package/dist/helpers/packageMeta.js +7 -0
  9. package/dist/helpers/packageMeta.js.map +1 -1
  10. package/dist/sdkgen.d.ts +3 -3
  11. package/dist/sdkgen.js +4 -1
  12. package/dist/sdkgen.js.map +1 -1
  13. package/dist/tsconfig.tsbuildinfo +1 -1
  14. package/package.json +7 -6
  15. package/project/.sdk/model/feature/paging.aontu +7 -0
  16. package/project/.sdk/model/target/py-data.aontu +64 -0
  17. package/project/.sdk/src/cmp/c/fragment/Main.fragment.c +89 -1
  18. package/project/.sdk/src/cmp/clojure/Main_clojure.ts +1 -0
  19. package/project/.sdk/src/cmp/csharp/fragment/Main.fragment.cs +97 -0
  20. package/project/.sdk/src/cmp/dart/fragment/Main.fragment.dart +78 -0
  21. package/project/.sdk/src/cmp/elixir/fragment/Main.fragment.ex +84 -0
  22. package/project/.sdk/src/cmp/go/fragment/Main.fragment.go +87 -0
  23. package/project/.sdk/src/cmp/js/fragment/Main.fragment.js +75 -0
  24. package/project/.sdk/src/cmp/lua/fragment/Main.fragment.lua +85 -0
  25. package/project/.sdk/src/cmp/ocaml/Main_ocaml.ts +4 -0
  26. package/project/.sdk/src/cmp/perl/fragment/Main.fragment.pm +80 -0
  27. package/project/.sdk/src/cmp/php/fragment/Main.fragment.php +86 -0
  28. package/project/.sdk/src/cmp/py/Entity_py.ts +9 -2
  29. package/project/.sdk/src/cmp/py/MainEntity_py.ts +1 -1
  30. package/project/.sdk/src/cmp/py/Main_py.ts +34 -6
  31. package/project/.sdk/src/cmp/py/Package_py.ts +6 -9
  32. package/project/.sdk/src/cmp/py/TestDirect_py.ts +2 -2
  33. package/project/.sdk/src/cmp/py/TestEntity_py.ts +3 -3
  34. package/project/.sdk/src/cmp/py/fragment/Entity.fragment.py +2 -2
  35. package/project/.sdk/src/cmp/py/fragment/EntityCreateOp.fragment.py +2 -2
  36. package/project/.sdk/src/cmp/py/fragment/EntityLoadOp.fragment.py +2 -2
  37. package/project/.sdk/src/cmp/py/fragment/EntityRemoveOp.fragment.py +2 -2
  38. package/project/.sdk/src/cmp/py/fragment/EntityUpdateOp.fragment.py +2 -2
  39. package/project/.sdk/src/cmp/py/fragment/Main.fragment.py +75 -8
  40. package/project/.sdk/src/cmp/py-data/Main_py-data.ts +987 -0
  41. package/project/.sdk/src/cmp/rb/fragment/Main.fragment.rb +71 -0
  42. package/project/.sdk/src/cmp/rust/fragment/Main.fragment.rs +95 -0
  43. package/project/.sdk/src/cmp/swift/fragment/Main.fragment.swift +86 -0
  44. package/project/.sdk/src/cmp/ts/fragment/Main.fragment.ts +75 -0
  45. package/project/.sdk/src/cmp/zig/fragment/Main.fragment.zig +95 -0
  46. package/project/.sdk/tm/c/core/sdk.h +7 -0
  47. package/project/.sdk/tm/c/feature/paging.c +141 -2
  48. package/project/.sdk/tm/c/utility/graphql.c +178 -0
  49. package/project/.sdk/tm/c/utility/make_options.c +1 -1
  50. package/project/.sdk/tm/c/utility/make_response.c +6 -0
  51. package/project/.sdk/tm/c/utility/make_spec.c +23 -3
  52. package/project/.sdk/tm/clojure/src/sdk/client.clj +64 -1
  53. package/project/.sdk/tm/clojure/src/sdk/core.clj +126 -3
  54. package/project/.sdk/tm/clojure/src/sdk/features.clj +80 -14
  55. package/project/.sdk/tm/cpp/core/types.hpp +83 -0
  56. package/project/.sdk/tm/cpp/feature/paging.hpp +103 -1
  57. package/project/.sdk/tm/cpp/utility/pipeline.hpp +152 -3
  58. package/project/.sdk/tm/csharp/core/Utility.cs +4 -0
  59. package/project/.sdk/tm/csharp/feature/PagingFeature.cs +118 -1
  60. package/project/.sdk/tm/csharp/utility/Graphql.cs +190 -0
  61. package/project/.sdk/tm/csharp/utility/MakeOptions.cs +1 -1
  62. package/project/.sdk/tm/csharp/utility/MakeResponse.cs +7 -0
  63. package/project/.sdk/tm/csharp/utility/MakeSpec.cs +21 -2
  64. package/project/.sdk/tm/csharp/utility/Register.cs +2 -0
  65. package/project/.sdk/tm/dart/lib/Point.dart +7 -0
  66. package/project/.sdk/tm/dart/lib/feature/paging/PagingFeature.dart +99 -4
  67. package/project/.sdk/tm/dart/lib/utility/GraphqlUtility.dart +162 -0
  68. package/project/.sdk/tm/dart/lib/utility/MakeOptionsUtility.dart +1 -1
  69. package/project/.sdk/tm/dart/lib/utility/MakeResponseUtility.dart +5 -0
  70. package/project/.sdk/tm/dart/lib/utility/MakeSpecUtility.dart +18 -2
  71. package/project/.sdk/tm/dart/lib/utility/PrepareMethodUtility.dart +6 -1
  72. package/project/.sdk/tm/dart/lib/utility/Utility.dart +9 -0
  73. package/project/.sdk/tm/elixir/lib/projectname/feature/paging.ex +136 -13
  74. package/project/.sdk/tm/elixir/lib/projectname/utility.ex +187 -3
  75. package/project/.sdk/tm/go/core/utility_type.go +2 -0
  76. package/project/.sdk/tm/go/feature/paging_feature.go +87 -1
  77. package/project/.sdk/tm/go/utility/graphql.go +168 -0
  78. package/project/.sdk/tm/go/utility/make_options.go +1 -1
  79. package/project/.sdk/tm/go/utility/make_response.go +6 -0
  80. package/project/.sdk/tm/go/utility/make_spec.go +19 -2
  81. package/project/.sdk/tm/go/utility/register.go +2 -0
  82. package/project/.sdk/tm/haskell/src/SdkFeatures.hs +146 -7
  83. package/project/.sdk/tm/haskell/src/SdkRuntime.hs +153 -3
  84. package/project/.sdk/tm/java/core/SdkClient.java +93 -0
  85. package/project/.sdk/tm/java/core/Utility.java +4 -0
  86. package/project/.sdk/tm/java/feature/PagingFeature.java +100 -1
  87. package/project/.sdk/tm/java/utility/Graphql.java +191 -0
  88. package/project/.sdk/tm/java/utility/MakeOptions.java +1 -1
  89. package/project/.sdk/tm/java/utility/MakeResponse.java +6 -0
  90. package/project/.sdk/tm/java/utility/MakeSpec.java +17 -2
  91. package/project/.sdk/tm/java/utility/Register.java +2 -0
  92. package/project/.sdk/tm/js/src/Point.js +5 -0
  93. package/project/.sdk/tm/js/src/feature/paging/PagingFeature.js +82 -3
  94. package/project/.sdk/tm/js/src/feature/test/TestFeature.js +14 -2
  95. package/project/.sdk/tm/js/src/utility/GraphqlUtility.js +148 -0
  96. package/project/.sdk/tm/js/src/utility/MakeOptionsUtility.js +1 -1
  97. package/project/.sdk/tm/js/src/utility/MakeResponseUtility.js +7 -0
  98. package/project/.sdk/tm/js/src/utility/MakeSpecUtility.js +19 -2
  99. package/project/.sdk/tm/js/src/utility/Utility.js +4 -0
  100. package/project/.sdk/tm/kotlin/core/SdkClient.kt +84 -0
  101. package/project/.sdk/tm/kotlin/core/Utility.kt +2 -0
  102. package/project/.sdk/tm/kotlin/feature/PagingFeature.kt +92 -1
  103. package/project/.sdk/tm/kotlin/utility/Graphql.kt +145 -0
  104. package/project/.sdk/tm/kotlin/utility/MakeOptions.kt +1 -1
  105. package/project/.sdk/tm/kotlin/utility/MakeReqRes.kt +6 -0
  106. package/project/.sdk/tm/kotlin/utility/MakeSpecUrl.kt +17 -2
  107. package/project/.sdk/tm/kotlin/utility/Register.kt +2 -0
  108. package/project/.sdk/tm/lean/src/SdkUtility.lean +134 -1
  109. package/project/.sdk/tm/lua/feature/paging_feature.lua +97 -2
  110. package/project/.sdk/tm/lua/utility/graphql.lua +163 -0
  111. package/project/.sdk/tm/lua/utility/make_options.lua +1 -1
  112. package/project/.sdk/tm/lua/utility/make_response.lua +6 -0
  113. package/project/.sdk/tm/lua/utility/make_spec.lua +18 -2
  114. package/project/.sdk/tm/lua/utility/register.lua +3 -0
  115. package/project/.sdk/tm/ocaml/sdk_features.ml +164 -20
  116. package/project/.sdk/tm/ocaml/sdk_runtime.ml +143 -4
  117. package/project/.sdk/tm/ocaml/sdk_types.ml +2 -0
  118. package/project/.sdk/tm/perl/feature/paging_feature.pm +91 -3
  119. package/project/.sdk/tm/perl/utility/graphql.pm +150 -0
  120. package/project/.sdk/tm/perl/utility/make_options.pm +1 -1
  121. package/project/.sdk/tm/perl/utility/make_response.pm +6 -0
  122. package/project/.sdk/tm/perl/utility/make_spec.pm +20 -2
  123. package/project/.sdk/tm/perl/utility/register.pm +1 -0
  124. package/project/.sdk/tm/php/core/UtilityType.php +2 -0
  125. package/project/.sdk/tm/php/feature/PagingFeature.php +106 -4
  126. package/project/.sdk/tm/php/utility/Graphql.php +176 -0
  127. package/project/.sdk/tm/php/utility/MakeOptions.php +1 -1
  128. package/project/.sdk/tm/php/utility/MakeResponse.php +7 -0
  129. package/project/.sdk/tm/php/utility/MakeSpec.php +20 -2
  130. package/project/.sdk/tm/php/utility/Register.php +3 -0
  131. package/project/.sdk/tm/py/pkg/core/__init__.py +0 -0
  132. package/project/.sdk/tm/py/{core → pkg/core}/context.py +8 -8
  133. package/project/.sdk/tm/py/{core → pkg/core}/operation.py +1 -1
  134. package/project/.sdk/tm/py/{core → pkg/core}/response.py +1 -1
  135. package/project/.sdk/tm/py/{core → pkg/core}/result.py +1 -1
  136. package/project/.sdk/tm/py/{core → pkg/core}/utility_type.py +2 -0
  137. package/project/.sdk/tm/py/pkg/entity/__init__.py +0 -0
  138. package/project/.sdk/tm/py/pkg/feature/__init__.py +0 -0
  139. package/project/.sdk/tm/py/{feature → pkg/feature}/audit_feature.py +1 -1
  140. package/project/.sdk/tm/py/{feature → pkg/feature}/cache_feature.py +1 -1
  141. package/project/.sdk/tm/py/{feature → pkg/feature}/clienttrack_feature.py +1 -1
  142. package/project/.sdk/tm/py/{feature → pkg/feature}/debug_feature.py +1 -1
  143. package/project/.sdk/tm/py/{feature → pkg/feature}/idempotency_feature.py +1 -1
  144. package/project/.sdk/tm/py/{feature → pkg/feature}/log_feature.py +1 -1
  145. package/project/.sdk/tm/py/{feature → pkg/feature}/metrics_feature.py +1 -1
  146. package/project/.sdk/tm/py/{feature → pkg/feature}/netsim_feature.py +1 -1
  147. package/project/.sdk/tm/py/{feature → pkg/feature}/paging_feature.py +87 -6
  148. package/project/.sdk/tm/py/{feature → pkg/feature}/proxy_feature.py +1 -1
  149. package/project/.sdk/tm/py/{feature → pkg/feature}/ratelimit_feature.py +1 -1
  150. package/project/.sdk/tm/py/{feature → pkg/feature}/rbac_feature.py +1 -1
  151. package/project/.sdk/tm/py/{feature → pkg/feature}/retry_feature.py +1 -1
  152. package/project/.sdk/tm/py/{feature → pkg/feature}/streaming_feature.py +1 -1
  153. package/project/.sdk/tm/py/{feature → pkg/feature}/telemetry_feature.py +1 -1
  154. package/project/.sdk/tm/py/{feature → pkg/feature}/test_feature.py +2 -2
  155. package/project/.sdk/tm/py/{feature → pkg/feature}/timeout_feature.py +1 -1
  156. package/project/.sdk/tm/py/pkg/utility/__init__.py +0 -0
  157. package/project/.sdk/tm/py/{utility → pkg/utility}/feature_init.py +1 -1
  158. package/project/.sdk/tm/py/{utility → pkg/utility}/fetcher.py +1 -1
  159. package/project/.sdk/tm/py/pkg/utility/graphql.py +145 -0
  160. package/project/.sdk/tm/py/{utility → pkg/utility}/make_context.py +1 -1
  161. package/project/.sdk/tm/py/{utility → pkg/utility}/make_error.py +5 -5
  162. package/project/.sdk/tm/py/{utility → pkg/utility}/make_fetch_def.py +2 -2
  163. package/project/.sdk/tm/py/{utility → pkg/utility}/make_options.py +2 -2
  164. package/project/.sdk/tm/py/{utility → pkg/utility}/make_point.py +2 -2
  165. package/project/.sdk/tm/py/{utility → pkg/utility}/make_request.py +2 -2
  166. package/project/.sdk/tm/py/{utility → pkg/utility}/make_response.py +6 -0
  167. package/project/.sdk/tm/py/{utility → pkg/utility}/make_spec.py +19 -4
  168. package/project/.sdk/tm/py/{utility → pkg/utility}/make_url.py +1 -1
  169. package/project/.sdk/tm/py/{utility → pkg/utility}/param.py +2 -2
  170. package/project/.sdk/tm/py/{utility → pkg/utility}/prepare_auth.py +1 -1
  171. package/project/.sdk/tm/py/{utility → pkg/utility}/prepare_headers.py +1 -1
  172. package/project/.sdk/tm/py/{utility → pkg/utility}/prepare_method.py +1 -1
  173. package/project/.sdk/tm/py/{utility → pkg/utility}/prepare_params.py +1 -1
  174. package/project/.sdk/tm/py/{utility → pkg/utility}/prepare_path.py +1 -1
  175. package/project/.sdk/tm/py/{utility → pkg/utility}/prepare_query.py +1 -1
  176. package/project/.sdk/tm/py/pkg/utility/register.py +71 -0
  177. package/project/.sdk/tm/py/{utility → pkg/utility}/transform_request.py +2 -2
  178. package/project/.sdk/tm/py/{utility → pkg/utility}/transform_response.py +2 -2
  179. package/project/.sdk/tm/py/test/feature_harness.py +6 -6
  180. package/project/.sdk/tm/py/test/runner.py +1 -1
  181. package/project/.sdk/tm/py/test/struct_runner.py +1 -1
  182. package/project/.sdk/tm/py/test/test_pipeline.py +5 -5
  183. package/project/.sdk/tm/py/test/test_primary_utility.py +8 -8
  184. package/project/.sdk/tm/py/test/test_struct_utility.py +3 -3
  185. package/project/.sdk/tm/py-data/LICENSE +22 -0
  186. package/project/.sdk/tm/py-data/Makefile +57 -0
  187. package/project/.sdk/tm/py-data/pkg/auth.py +131 -0
  188. package/project/.sdk/tm/py-data/pkg/fetch.py +178 -0
  189. package/project/.sdk/tm/py-data/pkg/frames.py +236 -0
  190. package/project/.sdk/tm/py-data/src/feature/README.md +8 -0
  191. package/project/.sdk/tm/py-data/src/feature/debug/.gitkeep +0 -0
  192. package/project/.sdk/tm/py-data/src/feature/idempotency/.gitkeep +0 -0
  193. package/project/.sdk/tm/py-data/src/feature/log/.gitkeep +0 -0
  194. package/project/.sdk/tm/py-data/src/feature/metrics/.gitkeep +0 -0
  195. package/project/.sdk/tm/py-data/src/feature/netsim/.gitkeep +0 -0
  196. package/project/.sdk/tm/py-data/src/feature/paging/.gitkeep +0 -0
  197. package/project/.sdk/tm/py-data/src/feature/proxy/.gitkeep +0 -0
  198. package/project/.sdk/tm/py-data/src/feature/ratelimit/.gitkeep +0 -0
  199. package/project/.sdk/tm/py-data/src/feature/rbac/.gitkeep +0 -0
  200. package/project/.sdk/tm/py-data/src/feature/retry/.gitkeep +0 -0
  201. package/project/.sdk/tm/py-data/src/feature/streaming/.gitkeep +0 -0
  202. package/project/.sdk/tm/py-data/src/feature/telemetry/.gitkeep +0 -0
  203. package/project/.sdk/tm/py-data/src/feature/test/.gitkeep +0 -0
  204. package/project/.sdk/tm/py-data/src/feature/timeout/.gitkeep +0 -0
  205. package/project/.sdk/tm/py-data/test/__init__.py +0 -0
  206. package/project/.sdk/tm/py-data/test/test_auth.py +95 -0
  207. package/project/.sdk/tm/py-data/test/test_fetch.py +152 -0
  208. package/project/.sdk/tm/py-data/test/test_frames.py +250 -0
  209. package/project/.sdk/tm/rb/core/utility_type.rb +1 -0
  210. package/project/.sdk/tm/rb/feature/paging_feature.rb +89 -3
  211. package/project/.sdk/tm/rb/utility/graphql.rb +131 -0
  212. package/project/.sdk/tm/rb/utility/make_options.rb +1 -1
  213. package/project/.sdk/tm/rb/utility/make_response.rb +6 -0
  214. package/project/.sdk/tm/rb/utility/make_spec.rb +18 -2
  215. package/project/.sdk/tm/rb/utility/register.rb +3 -0
  216. package/project/.sdk/tm/rust/feature/paging.rs +124 -2
  217. package/project/.sdk/tm/rust/utility/graphql.rs +193 -0
  218. package/project/.sdk/tm/rust/utility/make_options.rs +1 -1
  219. package/project/.sdk/tm/rust/utility/make_response.rs +6 -0
  220. package/project/.sdk/tm/rust/utility/make_spec.rs +32 -4
  221. package/project/.sdk/tm/rust/utility/mod.rs +1 -0
  222. package/project/.sdk/tm/scala/core/SdkClient.scala +90 -0
  223. package/project/.sdk/tm/scala/core/Utility.scala +4 -0
  224. package/project/.sdk/tm/scala/feature/PagingFeature.scala +104 -3
  225. package/project/.sdk/tm/scala/utility/Graphql.scala +160 -0
  226. package/project/.sdk/tm/scala/utility/Make.scala +7 -1
  227. package/project/.sdk/tm/scala/utility/MakeSpec.scala +22 -2
  228. package/project/.sdk/tm/scala/utility/Register.scala +2 -0
  229. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/core/Utility.swift +4 -0
  230. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/PagingFeature.swift +86 -1
  231. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/Graphql.swift +142 -0
  232. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/Make.swift +24 -2
  233. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/MakeOptions.swift +1 -1
  234. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/Register.swift +2 -0
  235. package/project/.sdk/tm/ts/src/Point.ts +7 -0
  236. package/project/.sdk/tm/ts/src/feature/paging/PagingFeature.ts +82 -3
  237. package/project/.sdk/tm/ts/src/feature/test/TestFeature.ts +14 -2
  238. package/project/.sdk/tm/ts/src/utility/GraphqlUtility.ts +152 -0
  239. package/project/.sdk/tm/ts/src/utility/MakeOptionsUtility.ts +1 -1
  240. package/project/.sdk/tm/ts/src/utility/MakeResponseUtility.ts +7 -0
  241. package/project/.sdk/tm/ts/src/utility/MakeSpecUtility.ts +19 -2
  242. package/project/.sdk/tm/ts/src/utility/Utility.ts +4 -0
  243. package/project/.sdk/tm/zig/core/utility.zig +198 -3
  244. package/project/.sdk/tm/zig/feature/paging.zig +128 -1
  245. package/src/cmp/AgentGuideContent.ts +5 -0
  246. package/src/cmp/Feature.ts +13 -0
  247. package/src/helpers/canonType.ts +46 -0
  248. package/src/helpers/packageMeta.ts +7 -0
  249. package/src/sdkgen.ts +6 -1
  250. package/project/.sdk/tm/py/utility/register.py +0 -68
  251. /package/project/.sdk/tm/py/{core → pkg/core}/control.py +0 -0
  252. /package/project/.sdk/tm/py/{core → pkg/core}/error.py +0 -0
  253. /package/project/.sdk/tm/py/{core → pkg/core}/helpers.py +0 -0
  254. /package/project/.sdk/tm/py/{core → pkg/core}/spec.py +0 -0
  255. /package/project/.sdk/tm/py/{feature → pkg/feature}/base_feature.py +0 -0
  256. /package/project/.sdk/tm/py/{utility → pkg/utility}/clean.py +0 -0
  257. /package/project/.sdk/tm/py/{utility → pkg/utility}/done.py +0 -0
  258. /package/project/.sdk/tm/py/{utility → pkg/utility}/feature_add.py +0 -0
  259. /package/project/.sdk/tm/py/{utility → pkg/utility}/feature_hook.py +0 -0
  260. /package/project/.sdk/tm/py/{utility → pkg/utility}/make_result.py +0 -0
  261. /package/project/.sdk/tm/py/{utility → pkg/utility}/prepare_body.py +0 -0
  262. /package/project/.sdk/tm/py/{utility → pkg/utility}/result_basic.py +0 -0
  263. /package/project/.sdk/tm/py/{utility → pkg/utility}/result_body.py +0 -0
  264. /package/project/.sdk/tm/py/{utility → pkg/utility}/result_headers.py +0 -0
  265. /package/project/.sdk/tm/py/{utility → pkg/utility}/voxgig_struct/__init__.py +0 -0
  266. /package/project/.sdk/tm/py/{utility → pkg/utility}/voxgig_struct/voxgig_struct.py +0 -0
  267. /package/project/.sdk/tm/{py/core/__init__.py → py-data/src/feature/audit/.gitkeep} +0 -0
  268. /package/project/.sdk/tm/{py/entity/__init__.py → py-data/src/feature/base/.gitkeep} +0 -0
  269. /package/project/.sdk/tm/{py/feature/__init__.py → py-data/src/feature/cache/.gitkeep} +0 -0
  270. /package/project/.sdk/tm/{py/utility/__init__.py → py-data/src/feature/clienttrack/.gitkeep} +0 -0
@@ -1,7 +1,7 @@
1
1
  # ProjectName SDK utility: prepare_headers
2
2
 
3
3
  from __future__ import annotations
4
- from utility.voxgig_struct import voxgig_struct as vs
4
+ from projectname_sdk.utility.voxgig_struct import voxgig_struct as vs
5
5
 
6
6
 
7
7
  def prepare_headers_util(ctx):
@@ -1,6 +1,6 @@
1
1
  # ProjectName SDK utility: prepare_method
2
2
 
3
- from utility.voxgig_struct import voxgig_struct as vs
3
+ from projectname_sdk.utility.voxgig_struct import voxgig_struct as vs
4
4
 
5
5
  METHOD_MAP = {
6
6
  "create": "POST",
@@ -1,7 +1,7 @@
1
1
  # ProjectName SDK utility: prepare_params
2
2
 
3
3
  from __future__ import annotations
4
- from utility.voxgig_struct import voxgig_struct as vs
4
+ from projectname_sdk.utility.voxgig_struct import voxgig_struct as vs
5
5
 
6
6
 
7
7
  def prepare_params_util(ctx):
@@ -1,7 +1,7 @@
1
1
  # ProjectName SDK utility: prepare_path
2
2
 
3
3
  from __future__ import annotations
4
- from utility.voxgig_struct import voxgig_struct as vs
4
+ from projectname_sdk.utility.voxgig_struct import voxgig_struct as vs
5
5
 
6
6
 
7
7
  def prepare_path_util(ctx):
@@ -1,7 +1,7 @@
1
1
  # ProjectName SDK utility: prepare_query
2
2
 
3
3
  from __future__ import annotations
4
- from utility.voxgig_struct import voxgig_struct as vs
4
+ from projectname_sdk.utility.voxgig_struct import voxgig_struct as vs
5
5
 
6
6
 
7
7
  def _contains_param(params, s):
@@ -0,0 +1,71 @@
1
+ # ProjectName SDK utility registration
2
+
3
+ from projectname_sdk.core.utility_type import ProjectNameUtility
4
+
5
+ from projectname_sdk.utility.clean import clean_util
6
+ from projectname_sdk.utility.done import done_util
7
+ from projectname_sdk.utility.make_error import make_error_util
8
+ from projectname_sdk.utility.feature_add import feature_add_util
9
+ from projectname_sdk.utility.feature_hook import feature_hook_util
10
+ from projectname_sdk.utility.feature_init import feature_init_util
11
+ from projectname_sdk.utility.fetcher import fetcher_util
12
+ from projectname_sdk.utility.make_fetch_def import make_fetch_def_util
13
+ from projectname_sdk.utility.make_context import make_context_util
14
+ from projectname_sdk.utility.make_options import make_options_util
15
+ from projectname_sdk.utility.make_request import make_request_util
16
+ from projectname_sdk.utility.make_response import make_response_util
17
+ from projectname_sdk.utility.make_result import make_result_util
18
+ from projectname_sdk.utility.make_point import make_point_util
19
+ from projectname_sdk.utility.make_spec import make_spec_util
20
+ from projectname_sdk.utility.make_url import make_url_util
21
+ from projectname_sdk.utility.param import param_util
22
+ from projectname_sdk.utility.prepare_auth import prepare_auth_util
23
+ from projectname_sdk.utility.prepare_body import prepare_body_util
24
+ from projectname_sdk.utility.prepare_headers import prepare_headers_util
25
+ from projectname_sdk.utility.prepare_method import prepare_method_util
26
+ from projectname_sdk.utility.prepare_params import prepare_params_util
27
+ from projectname_sdk.utility.prepare_path import prepare_path_util
28
+ from projectname_sdk.utility.prepare_query import prepare_query_util
29
+ from projectname_sdk.utility.graphql import graphql_body_util, graphql_errors_util
30
+ from projectname_sdk.utility.result_basic import result_basic_util
31
+ from projectname_sdk.utility.result_body import result_body_util
32
+ from projectname_sdk.utility.result_headers import result_headers_util
33
+ from projectname_sdk.utility.transform_request import transform_request_util
34
+ from projectname_sdk.utility.transform_response import transform_response_util
35
+
36
+
37
+ def register_all(u):
38
+ u.clean = clean_util
39
+ u.done = done_util
40
+ u.make_error = make_error_util
41
+ u.feature_add = feature_add_util
42
+ u.feature_hook = feature_hook_util
43
+ u.feature_init = feature_init_util
44
+ u.fetcher = fetcher_util
45
+ u.make_fetch_def = make_fetch_def_util
46
+ u.make_context = make_context_util
47
+ u.make_options = make_options_util
48
+ u.make_request = make_request_util
49
+ u.make_response = make_response_util
50
+ u.make_result = make_result_util
51
+ u.make_point = make_point_util
52
+ u.make_spec = make_spec_util
53
+ u.make_url = make_url_util
54
+ u.param = param_util
55
+ u.prepare_auth = prepare_auth_util
56
+ u.prepare_body = prepare_body_util
57
+ u.prepare_headers = prepare_headers_util
58
+ u.prepare_method = prepare_method_util
59
+ u.prepare_params = prepare_params_util
60
+ u.prepare_path = prepare_path_util
61
+ u.prepare_query = prepare_query_util
62
+ u.graphql_body = graphql_body_util
63
+ u.graphql_errors = graphql_errors_util
64
+ u.result_basic = result_basic_util
65
+ u.result_body = result_body_util
66
+ u.result_headers = result_headers_util
67
+ u.transform_request = transform_request_util
68
+ u.transform_response = transform_response_util
69
+
70
+
71
+ ProjectNameUtility._registrar = register_all
@@ -1,8 +1,8 @@
1
1
  # ProjectName SDK utility: transform_request
2
2
 
3
3
  from __future__ import annotations
4
- from utility.voxgig_struct import voxgig_struct as vs
5
- from core.helpers import to_map
4
+ from projectname_sdk.utility.voxgig_struct import voxgig_struct as vs
5
+ from projectname_sdk.core.helpers import to_map
6
6
 
7
7
 
8
8
  def transform_request_util(ctx):
@@ -1,8 +1,8 @@
1
1
  # ProjectName SDK utility: transform_response
2
2
 
3
3
  from __future__ import annotations
4
- from utility.voxgig_struct import voxgig_struct as vs
5
- from core.helpers import to_map
4
+ from projectname_sdk.utility.voxgig_struct import voxgig_struct as vs
5
+ from projectname_sdk.core.helpers import to_map
6
6
 
7
7
 
8
8
  def transform_response_util(ctx):
@@ -14,12 +14,12 @@ from __future__ import annotations
14
14
 
15
15
  from urllib.parse import quote
16
16
 
17
- from config import make_config
18
- from features import _make_feature
19
- from core.control import ProjectNameControl
20
- from core.error import ProjectNameError
21
- from core.result import ProjectNameResult
22
- from core.spec import ProjectNameSpec
17
+ from projectname_sdk.config import make_config
18
+ from projectname_sdk.features import _make_feature
19
+ from projectname_sdk.core.control import ProjectNameControl
20
+ from projectname_sdk.core.error import ProjectNameError
21
+ from projectname_sdk.core.result import ProjectNameResult
22
+ from projectname_sdk.core.spec import ProjectNameSpec
23
23
 
24
24
 
25
25
  # True when this SDK was generated with the named feature.
@@ -4,7 +4,7 @@ from __future__ import annotations
4
4
  import os
5
5
  import json
6
6
 
7
- from utility.voxgig_struct import voxgig_struct as vs
7
+ from projectname_sdk.utility.voxgig_struct import voxgig_struct as vs
8
8
 
9
9
 
10
10
  class ProjectNameTestRunner:
@@ -6,7 +6,7 @@ import json
6
6
  import re
7
7
  from typing import Any, Dict, List, Callable, TypedDict, Optional, Union
8
8
 
9
- from utility.voxgig_struct import voxgig_struct as vs
9
+ from projectname_sdk.utility.voxgig_struct import voxgig_struct as vs
10
10
 
11
11
 
12
12
  NULLMARK = '__NULL__' # Value is JSON null
@@ -16,11 +16,11 @@
16
16
  import pytest
17
17
 
18
18
  from projectname_sdk import ProjectNameSDK
19
- from core.error import ProjectNameError
20
- from core.result import ProjectNameResult
21
- from core.response import ProjectNameResponse
22
- from core.spec import ProjectNameSpec
23
- from feature.base_feature import ProjectNameBaseFeature
19
+ from projectname_sdk.core.error import ProjectNameError
20
+ from projectname_sdk.core.result import ProjectNameResult
21
+ from projectname_sdk.core.response import ProjectNameResponse
22
+ from projectname_sdk.core.spec import ProjectNameSpec
23
+ from projectname_sdk.feature.base_feature import ProjectNameBaseFeature
24
24
 
25
25
 
26
26
  def _client():
@@ -6,15 +6,15 @@ import re
6
6
 
7
7
  import pytest
8
8
 
9
- from utility.voxgig_struct import voxgig_struct as vs
9
+ from projectname_sdk.utility.voxgig_struct import voxgig_struct as vs
10
10
  from projectname_sdk import ProjectNameSDK
11
- from core.spec import ProjectNameSpec
12
- from core.result import ProjectNameResult
13
- from core.response import ProjectNameResponse
14
- from core.operation import ProjectNameOperation
15
- from core.error import ProjectNameError
16
- from core import helpers
17
- from feature.base_feature import ProjectNameBaseFeature
11
+ from projectname_sdk.core.spec import ProjectNameSpec
12
+ from projectname_sdk.core.result import ProjectNameResult
13
+ from projectname_sdk.core.response import ProjectNameResponse
14
+ from projectname_sdk.core.operation import ProjectNameOperation
15
+ from projectname_sdk.core.error import ProjectNameError
16
+ from projectname_sdk.core import helpers
17
+ from projectname_sdk.feature.base_feature import ProjectNameBaseFeature
18
18
 
19
19
  _TEST_DIR = os.path.dirname(os.path.abspath(__file__))
20
20
 
@@ -13,8 +13,8 @@ from test.struct_runner import (
13
13
  StructTestClient,
14
14
  )
15
15
 
16
- from utility.voxgig_struct import voxgig_struct as vs
17
- from utility.voxgig_struct.voxgig_struct import (
16
+ from projectname_sdk.utility.voxgig_struct import voxgig_struct as vs
17
+ from projectname_sdk.utility.voxgig_struct.voxgig_struct import (
18
18
  T_noval, T_scalar, T_function, T_symbol, T_any, T_node, T_instance, T_null,
19
19
  )
20
20
 
@@ -308,7 +308,7 @@ class TestStructUtility(unittest.TestCase):
308
308
 
309
309
 
310
310
  def test_minor_joinurl(self):
311
- from utility.voxgig_struct.voxgig_struct import join as struct_join
311
+ from projectname_sdk.utility.voxgig_struct.voxgig_struct import join as struct_join
312
312
  runsetflags(minorSpec["join"], {"null": False},
313
313
  lambda vin: struct_join(vin.get("val"), vin.get("sep"), vin.get("url")))
314
314
 
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) $$const.year$$ Voxgig
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
@@ -0,0 +1,57 @@
1
+ .PHONY: test build clean publish dev notebook
2
+
3
+ # Install the sibling ProjectName SDK from the same repo (../py) plus this
4
+ # package, both editable, so a working copy tests against the SDK it was
5
+ # generated alongside rather than whatever is on PyPI.
6
+ dev:
7
+ python3 -m pip install -e ../py
8
+ python3 -m pip install -e .
9
+
10
+ test:
11
+ python3 -m pytest test/
12
+
13
+ # Execute the generated quickstart notebook end to end. A quickstart that
14
+ # does not run is a broken product, so this is part of `make test` in CI.
15
+ notebook:
16
+ python3 -m jupyter nbconvert --to notebook --execute \
17
+ --stdout notebooks/quickstart.ipynb > /dev/null && echo "quickstart.ipynb OK"
18
+
19
+ build:
20
+ @echo "No build step for Python"
21
+
22
+ clean:
23
+ find . -name __pycache__ -exec rm -rf {} + 2>/dev/null; true
24
+ rm -rf dist .pytest_cache
25
+
26
+ # --- Release: publish to PyPI ---------------------------------------------
27
+ # Publish this package to PyPI, then tag py-data/vX.Y.Z. Run headless under the
28
+ # boru key vault, which injects the PyPI + GitHub tokens as environment
29
+ # variables (never written to disk or argv):
30
+ # boru vault exec --for=pypi=<alias> --for=github=<alias> -- make publish
31
+ # boru `--dry-run` injects a filler token we detect to rehearse: builds the dist
32
+ # but performs no upload, tag, or push. set -e + tag-last: a failed upload never
33
+ # leaves a tag behind. Needs python `build` + `twine` (pip install build twine).
34
+ VERSION := $(shell sed -nE 's/^version *= *"([^"]+)".*/\1/p' pyproject.toml | head -1)
35
+ TAG := py-data/v$(VERSION)
36
+ BORU_DRY_RUN_FILLER := BORU-DRY-RUN-FILLER-NOT-A-REAL-SECRET
37
+ publish: test
38
+ @if git rev-parse -q --verify "refs/tags/$(TAG)" >/dev/null; then \
39
+ echo "tag $(TAG) already exists — bump pyproject.toml version first"; exit 1; fi
40
+ @set -e; \
41
+ token="$${GITHUB_TOKEN:-$$GH_TOKEN}"; \
42
+ rm -rf dist; \
43
+ python3 -m build; \
44
+ if [ "$$token" = "$(BORU_DRY_RUN_FILLER)" ] || [ "$$TWINE_PASSWORD" = "$(BORU_DRY_RUN_FILLER)" ]; then \
45
+ echo "[dry-run] boru filler token detected: built the dist; would upload to PyPI and tag $(TAG); nothing pushed."; \
46
+ exit 0; \
47
+ fi; \
48
+ python3 -m twine upload dist/*; \
49
+ git tag -a "$(TAG)" -m "py-data v$(VERSION)"; \
50
+ url=$$(git remote get-url origin | sed -E 's#^git@github.com:#https://github.com/#'); \
51
+ if [ -n "$$token" ] && printf '%s' "$$url" | grep -q '^https://github.com/'; then \
52
+ hdr="AUTHORIZATION: basic $$(printf 'x-access-token:%s' "$$token" | base64 | tr -d '\n')"; \
53
+ git -c http.extraheader="$$hdr" push "$$url" "$(TAG)"; \
54
+ else \
55
+ git push origin "$(TAG)"; \
56
+ fi; \
57
+ echo "Published to PyPI + tag $(TAG)."
@@ -0,0 +1,131 @@
1
+ # ProjectName Data — credential discovery.
2
+ #
3
+ # `data()` must work in a fresh Colab cell with no arguments. Analysts do not
4
+ # want to construct a client; they want a DataFrame. So the token and base
5
+ # URL are looked up through a short, predictable chain and the failure
6
+ # message TEACHES rather than merely reports.
7
+ #
8
+ # Kept generic (the SDK's env-var prefix is passed in) because this file is
9
+ # copied verbatim per SDK — only `ProjectName` is substituted at generation
10
+ # time, so nothing here may hardcode a per-API name.
11
+
12
+ from __future__ import annotations
13
+
14
+ import os
15
+ from typing import Any
16
+
17
+
18
+ NOT_FOUND = object()
19
+
20
+
21
+ def from_colab(key: str) -> Any:
22
+ """Read a Colab secret, or NOT_FOUND.
23
+
24
+ Guarded three ways because every one of them bites in practice:
25
+ the import fails outside Colab; `userdata` raises SecretNotFoundError for
26
+ a key that was never set; and it raises NotebookAccessError when the
27
+ secret exists but the notebook has not been granted access to it (the
28
+ toggle in Colab's key panel). None of those are errors HERE — they just
29
+ mean "try the next source".
30
+ """
31
+ try:
32
+ from google.colab import userdata # type: ignore
33
+ except Exception:
34
+ return NOT_FOUND
35
+ try:
36
+ val = userdata.get(key)
37
+ except Exception:
38
+ return NOT_FOUND
39
+ return val if val else NOT_FOUND
40
+
41
+
42
+ def from_env(key: str) -> Any:
43
+ val = os.environ.get(key)
44
+ return val if val else NOT_FOUND
45
+
46
+
47
+ def resolve(
48
+ prefix: str,
49
+ token: str | None = None,
50
+ base_url: str | None = None,
51
+ *,
52
+ token_key: str | None = None,
53
+ base_key: str | None = None,
54
+ ) -> tuple:
55
+ """(token, base_url, source) from args, then Colab secrets, then env.
56
+
57
+ `prefix` is the SDK's upper-snake name, e.g. ACME -> ACME_APIKEY /
58
+ ACME_BASE. Returns the raw values; validation is the caller's job so it
59
+ can decide whether a missing base_url is fatal (multi-tenant APIs) or
60
+ fine (the model's default applies).
61
+ """
62
+ tkey = token_key or f"{prefix}_APIKEY"
63
+ bkey = base_key or f"{prefix}_BASE"
64
+
65
+ source = "argument"
66
+ tok: Any = token if token else NOT_FOUND
67
+
68
+ if tok is NOT_FOUND:
69
+ tok = from_colab(tkey)
70
+ source = "colab"
71
+ if tok is NOT_FOUND:
72
+ tok = from_env(tkey)
73
+ source = "env"
74
+
75
+ base: Any = base_url if base_url else NOT_FOUND
76
+ if base is NOT_FOUND:
77
+ base = from_colab(bkey)
78
+ if base is NOT_FOUND:
79
+ base = from_env(bkey)
80
+
81
+ return (
82
+ None if tok is NOT_FOUND else tok,
83
+ None if base is NOT_FOUND else base,
84
+ None if tok is NOT_FOUND else source,
85
+ )
86
+
87
+
88
+ def missing_token_message(prefix: str, token_key: str | None = None) -> str:
89
+ """The error an analyst sees when no credential was found.
90
+
91
+ Shows the exact lines to run for THIS SDK in both environments. A generic
92
+ "credentials not found" costs the reader a trip to the README; this costs
93
+ them a copy-paste.
94
+ """
95
+ tkey = token_key or f"{prefix}_APIKEY"
96
+ return (
97
+ f"No API credential found for ProjectName.\n"
98
+ f"\n"
99
+ f"In Google Colab — open the key panel (left sidebar), add a secret\n"
100
+ f"named {tkey}, and enable notebook access for it. Or set it in code:\n"
101
+ f"\n"
102
+ f" from google.colab import userdata\n"
103
+ f" userdata.set('{tkey}', 'your-api-key')\n"
104
+ f"\n"
105
+ f"Elsewhere (Jupyter, a script, a terminal):\n"
106
+ f"\n"
107
+ f" import os\n"
108
+ f" os.environ['{tkey}'] = 'your-api-key'\n"
109
+ f"\n"
110
+ f"Or pass it directly:\n"
111
+ f"\n"
112
+ f" data(token='your-api-key')\n"
113
+ )
114
+
115
+
116
+ def missing_base_message(prefix: str, base_key: str | None = None) -> str:
117
+ """The error for a multi-tenant API with no base URL.
118
+
119
+ Only raised when the model's server URL carries an unresolved
120
+ placeholder, i.e. the API genuinely has no single host and every customer
121
+ has their own instance. Guessing one would produce confusing 404s.
122
+ """
123
+ bkey = base_key or f"{prefix}_BASE"
124
+ return (
125
+ f"ProjectName is multi-tenant: it has no single API host, so the base\n"
126
+ f"URL for YOUR instance is required.\n"
127
+ f"\n"
128
+ f" data(base_url='https://your-instance.example.com')\n"
129
+ f"\n"
130
+ f"or set {bkey} as a Colab secret / environment variable.\n"
131
+ )
@@ -0,0 +1,178 @@
1
+ # ProjectName Data — eager paging drain.
2
+ #
3
+ # Analysts want the whole table now. Lazy iterators are application
4
+ # ergonomics: correct for a service processing a stream, wrong for someone
5
+ # who typed `df = ad.things()` and wants to run a groupby on the next line.
6
+ #
7
+ # This module owns NO pagination knowledge. The sibling SDK's `paging`
8
+ # feature already normalises every server dialect it understands — a
9
+ # `Link: rel="next"` header, X-Page / X-Next-Page / X-Total-Count, or body
10
+ # `next` / `cursor` / `nextCursor` / `hasMore` — onto `result.paging`, and
11
+ # records the last one on the client. All we do is drive it to exhaustion by
12
+ # feeding the cursor/page back in through the per-call `ctrl.paging` hook,
13
+ # which exists for exactly this purpose.
14
+
15
+ from __future__ import annotations
16
+
17
+ import sys
18
+ from typing import Any, Callable
19
+
20
+
21
+ # Safety backstop. A server that always reports "more" (or a cursor that
22
+ # never advances) would otherwise loop forever inside a notebook cell with
23
+ # no output. Hitting this is always reported, never silent.
24
+ MAX_PAGES_DEFAULT = 1000
25
+
26
+
27
+ def in_notebook() -> bool:
28
+ """True when running under IPython/Jupyter/Colab with a display."""
29
+ try:
30
+ from IPython import get_ipython # type: ignore
31
+ except Exception:
32
+ return False
33
+ ip = get_ipython()
34
+ if ip is None:
35
+ return False
36
+ return hasattr(ip, "kernel")
37
+
38
+
39
+ def _progress(count: int, pages: int, quiet: bool) -> None:
40
+ if quiet:
41
+ return
42
+ # Deliberately not tqdm: an extra hard dependency for a progress bar is a
43
+ # bad trade in an environment that reinstalls every dependency on every
44
+ # session start. A rewritten stderr line costs nothing and works in both
45
+ # notebooks and plain terminals.
46
+ sys.stderr.write(f"\r fetched {count} rows ({pages} pages)…")
47
+ sys.stderr.flush()
48
+
49
+
50
+ def _progress_done(count: int, pages: int, quiet: bool) -> None:
51
+ if quiet:
52
+ return
53
+ sys.stderr.write(f"\r fetched {count} rows ({pages} pages) \n")
54
+ sys.stderr.flush()
55
+
56
+
57
+ def drain(
58
+ call: Callable[[dict], Any],
59
+ client: Any,
60
+ *,
61
+ limit: int | None = None,
62
+ max_pages: int = MAX_PAGES_DEFAULT,
63
+ quiet: bool = False,
64
+ progress_after: int = 1,
65
+ ) -> list:
66
+ """Call `call(ctrl)` until the server stops offering more.
67
+
68
+ call — invoked with a ctrl dict; returns one page of records
69
+ client — the SDK client, read for `_paging` (set by the paging feature)
70
+ limit — stop once this many rows are collected (None = all)
71
+ max_pages — backstop; a warning is emitted if it is reached
72
+ quiet — suppress progress output
73
+ progress_after — only show progress once this many pages have been fetched,
74
+ so the common single-page case prints nothing at all
75
+
76
+ Returns the accumulated records.
77
+
78
+ When the SDK's paging feature is INACTIVE there is no `_paging` state, so
79
+ this makes exactly one call and returns it — the correct degradation, not
80
+ an error. An SDK without paging configured genuinely has one page.
81
+ """
82
+ rows: list = []
83
+ ctrl: dict = {}
84
+ pages = 0
85
+ seen_cursors: set = set()
86
+ hit_max = False
87
+
88
+ while True:
89
+ page = call(ctrl)
90
+ pages += 1
91
+
92
+ if page is None:
93
+ batch = []
94
+ elif isinstance(page, (list, tuple)):
95
+ batch = list(page)
96
+ else:
97
+ batch = [page]
98
+
99
+ rows.extend(batch)
100
+
101
+ if pages >= progress_after + 1:
102
+ _progress(len(rows), pages, quiet)
103
+
104
+ if limit is not None and len(rows) >= limit:
105
+ rows = rows[:limit]
106
+ break
107
+
108
+ paging = _last_paging(client)
109
+ if not paging or not paging.get("hasMore"):
110
+ break
111
+
112
+ # An empty page that still claims more would spin forever.
113
+ if len(batch) == 0:
114
+ break
115
+
116
+ nxt = _next_ctrl(paging)
117
+ if nxt is None:
118
+ break
119
+
120
+ # A cursor that repeats means the server is not advancing. Stopping
121
+ # beats looping: the analyst gets the rows fetched so far, plus a
122
+ # warning, instead of a hung cell.
123
+ token = repr(sorted(nxt.get("paging", {}).items()))
124
+ if token in seen_cursors:
125
+ _warn("pagination stopped advancing (repeated cursor) — "
126
+ f"returning the {len(rows)} rows fetched so far")
127
+ break
128
+ seen_cursors.add(token)
129
+
130
+ if pages >= max_pages:
131
+ hit_max = True
132
+ break
133
+
134
+ ctrl = nxt
135
+
136
+ if pages >= progress_after + 1:
137
+ _progress_done(len(rows), pages, quiet)
138
+
139
+ if hit_max:
140
+ _warn(f"stopped at max_pages={max_pages} with {len(rows)} rows; the "
141
+ "server still reported more. Pass max_pages= to raise the cap, "
142
+ "or limit= to take a defined slice.")
143
+
144
+ return rows
145
+
146
+
147
+ def _last_paging(client: Any) -> dict | None:
148
+ """The paging state the SDK's paging feature recorded on the client."""
149
+ state = getattr(client, "_paging", None)
150
+ if not isinstance(state, dict):
151
+ return None
152
+ last = state.get("last")
153
+ return last if isinstance(last, dict) else None
154
+
155
+
156
+ def _next_ctrl(paging: dict) -> dict | None:
157
+ """Build the ctrl for the next page from the recorded paging state.
158
+
159
+ Cursor wins over page number: when a server offers both, the cursor is
160
+ the one with consistency guarantees.
161
+ """
162
+ cursor = paging.get("cursor")
163
+ if cursor is not None:
164
+ return {"paging": {"cursor": cursor}}
165
+
166
+ next_page = paging.get("nextPage")
167
+ if next_page is not None:
168
+ return {"paging": {"page": next_page}}
169
+
170
+ # A `Link: rel="next"` URL with no cursor/page extracted is not something
171
+ # we can turn into a ctrl — the SDK builds its own request URLs. Rather
172
+ # than guess at query parsing, stop and keep what we have.
173
+ return None
174
+
175
+
176
+ def _warn(msg: str) -> None:
177
+ import warnings
178
+ warnings.warn(f"ProjectName data: {msg}", stacklevel=3)