pltr-cli 0.10.0__tar.gz → 0.11.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/PKG-INFO +1 -1
  2. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/pyproject.toml +1 -1
  3. pltr_cli-0.11.0/src/pltr/__init__.py +1 -0
  4. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/commands/ontology.py +93 -0
  5. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/services/dataset.py +5 -8
  6. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/services/ontology.py +71 -0
  7. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/test_commands/test_ontology.py +105 -0
  8. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/test_services/test_ontology.py +79 -0
  9. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/uv.lock +1 -1
  10. pltr_cli-0.10.0/src/pltr/__init__.py +0 -1
  11. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/.github/workflows/ci.yml +0 -0
  12. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/.github/workflows/publish.yml +0 -0
  13. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/.github/workflows/test-publish.yml +0 -0
  14. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/.gitignore +0 -0
  15. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/.pre-commit-config.yaml +0 -0
  16. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/CHANGELOG.md +0 -0
  17. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/CLAUDE.md +0 -0
  18. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/LICENSE +0 -0
  19. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/README.md +0 -0
  20. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/RELEASE.md +0 -0
  21. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/children.csv +0 -0
  22. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/docs/README.md +0 -0
  23. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/docs/api/wrapper.md +0 -0
  24. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/docs/examples/csv-upload.md +0 -0
  25. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/docs/examples/gallery.md +0 -0
  26. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/docs/features/dataset-transactions.md +0 -0
  27. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/docs/user-guide/aliases.md +0 -0
  28. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/docs/user-guide/authentication.md +0 -0
  29. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/docs/user-guide/commands.md +0 -0
  30. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/docs/user-guide/quick-start.md +0 -0
  31. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/docs/user-guide/troubleshooting.md +0 -0
  32. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/docs/user-guide/workflows.md +0 -0
  33. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/folder_info.json +0 -0
  34. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/folders.json +0 -0
  35. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/mypy.ini +0 -0
  36. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/scripts/release.py +0 -0
  37. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/__main__.py +0 -0
  38. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/auth/__init__.py +0 -0
  39. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/auth/base.py +0 -0
  40. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/auth/manager.py +0 -0
  41. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/auth/oauth.py +0 -0
  42. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/auth/storage.py +0 -0
  43. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/auth/token.py +0 -0
  44. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/cli.py +0 -0
  45. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/commands/__init__.py +0 -0
  46. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/commands/admin.py +0 -0
  47. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/commands/alias.py +0 -0
  48. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/commands/completion.py +0 -0
  49. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/commands/configure.py +0 -0
  50. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/commands/connectivity.py +0 -0
  51. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/commands/dataset.py +0 -0
  52. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/commands/folder.py +0 -0
  53. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/commands/mediasets.py +0 -0
  54. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/commands/orchestration.py +0 -0
  55. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/commands/project.py +0 -0
  56. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/commands/resource.py +0 -0
  57. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/commands/resource_role.py +0 -0
  58. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/commands/shell.py +0 -0
  59. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/commands/space.py +0 -0
  60. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/commands/sql.py +0 -0
  61. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/commands/verify.py +0 -0
  62. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/config/__init__.py +0 -0
  63. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/config/aliases.py +0 -0
  64. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/config/profiles.py +0 -0
  65. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/config/settings.py +0 -0
  66. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/services/__init__.py +0 -0
  67. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/services/admin.py +0 -0
  68. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/services/base.py +0 -0
  69. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/services/connectivity.py +0 -0
  70. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/services/folder.py +0 -0
  71. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/services/mediasets.py +0 -0
  72. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/services/orchestration.py +0 -0
  73. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/services/project.py +0 -0
  74. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/services/resource.py +0 -0
  75. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/services/resource_role.py +0 -0
  76. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/services/space.py +0 -0
  77. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/services/sql.py +0 -0
  78. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/utils/__init__.py +0 -0
  79. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/utils/alias_resolver.py +0 -0
  80. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/utils/completion.py +0 -0
  81. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/utils/formatting.py +0 -0
  82. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/src/pltr/utils/progress.py +0 -0
  83. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/__init__.py +0 -0
  84. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/conftest.py +0 -0
  85. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/integration/README.md +0 -0
  86. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/integration/__init__.py +0 -0
  87. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/integration/conftest.py +0 -0
  88. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/integration/test_auth_flow.py +0 -0
  89. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/integration/test_cli_integration.py +0 -0
  90. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/integration/test_data_workflows.py +0 -0
  91. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/integration/test_data_workflows_simple.py +0 -0
  92. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/integration/test_simple_integration.py +0 -0
  93. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/test_auth/__init__.py +0 -0
  94. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/test_auth/test_base.py +0 -0
  95. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/test_auth/test_manager.py +0 -0
  96. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/test_auth/test_oauth.py +0 -0
  97. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/test_auth/test_storage.py +0 -0
  98. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/test_auth/test_token.py +0 -0
  99. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/test_commands/__init__.py +0 -0
  100. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/test_commands/test_admin.py +0 -0
  101. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/test_commands/test_alias.py +0 -0
  102. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/test_commands/test_completion.py +0 -0
  103. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/test_commands/test_connectivity.py +0 -0
  104. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/test_commands/test_dataset.py +0 -0
  105. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/test_commands/test_folder.py +0 -0
  106. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/test_commands/test_orchestration.py +0 -0
  107. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/test_commands/test_shell.py +0 -0
  108. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/test_commands/test_sql.py +0 -0
  109. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/test_commands/test_verify_simple.py +0 -0
  110. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/test_config/__init__.py +0 -0
  111. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/test_config/test_aliases.py +0 -0
  112. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/test_config/test_profiles.py +0 -0
  113. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/test_config/test_settings.py +0 -0
  114. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/test_services/__init__.py +0 -0
  115. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/test_services/test_admin.py +0 -0
  116. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/test_services/test_base.py +0 -0
  117. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/test_services/test_connectivity.py +0 -0
  118. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/test_services/test_dataset.py +0 -0
  119. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/test_services/test_dataset_transactions.py +0 -0
  120. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/test_services/test_folder.py +0 -0
  121. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/test_services/test_orchestration.py +0 -0
  122. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/test_services/test_project.py +0 -0
  123. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/test_services/test_resource.py +0 -0
  124. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/test_services/test_resource_role.py +0 -0
  125. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/test_services/test_space.py +0 -0
  126. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/test_services/test_sql.py +0 -0
  127. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/test_utils/__init__.py +0 -0
  128. {pltr_cli-0.10.0 → pltr_cli-0.11.0}/tests/test_utils/test_alias_resolver.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pltr-cli
3
- Version: 0.10.0
3
+ Version: 0.11.0
4
4
  Summary: Command-line interface for Palantir Foundry APIs
5
5
  Project-URL: Homepage, https://github.com/anjor/pltr-cli
6
6
  Project-URL: Repository, https://github.com/anjor/pltr-cli
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "pltr-cli"
3
- version = "0.10.0"
3
+ version = "0.11.0"
4
4
  description = "Command-line interface for Palantir Foundry APIs"
5
5
  authors = [
6
6
  { name = "anjor", email = "anjor@umd.edu" },
@@ -0,0 +1 @@
1
+ __version__ = "0.11.0"
@@ -366,6 +366,99 @@ def list_linked_objects(
366
366
  raise typer.Exit(1)
367
367
 
368
368
 
369
+ @app.command("object-count")
370
+ def count_objects(
371
+ ontology_rid: str = typer.Argument(..., help="Ontology Resource Identifier"),
372
+ object_type: str = typer.Argument(..., help="Object type API name"),
373
+ profile: Optional[str] = typer.Option(None, "--profile", "-p", help="Profile name"),
374
+ format: str = typer.Option(
375
+ "table", "--format", "-f", help="Output format (table, json, csv)"
376
+ ),
377
+ output: Optional[str] = typer.Option(
378
+ None, "--output", "-o", help="Output file path"
379
+ ),
380
+ branch: Optional[str] = typer.Option(None, "--branch", "-b", help="Branch name"),
381
+ ):
382
+ """Count objects of a specific type."""
383
+ try:
384
+ service = OntologyObjectService(profile=profile)
385
+
386
+ with SpinnerProgressTracker().track_spinner(
387
+ f"Counting {object_type} objects..."
388
+ ):
389
+ result = service.count_objects(ontology_rid, object_type, branch=branch)
390
+
391
+ formatter.format_dict(result, format=format, output=output)
392
+
393
+ if output:
394
+ formatter.print_success(f"Count result saved to {output}")
395
+
396
+ except (ProfileNotFoundError, MissingCredentialsError) as e:
397
+ formatter.print_error(f"Authentication error: {e}")
398
+ raise typer.Exit(1)
399
+ except Exception as e:
400
+ formatter.print_error(f"Failed to count objects: {e}")
401
+ raise typer.Exit(1)
402
+
403
+
404
+ @app.command("object-search")
405
+ def search_objects(
406
+ ontology_rid: str = typer.Argument(..., help="Ontology Resource Identifier"),
407
+ object_type: str = typer.Argument(..., help="Object type API name"),
408
+ query: str = typer.Option(..., "--query", "-q", help="Search query string"),
409
+ profile: Optional[str] = typer.Option(None, "--profile", "-p", help="Profile name"),
410
+ format: str = typer.Option(
411
+ "table", "--format", "-f", help="Output format (table, json, csv)"
412
+ ),
413
+ output: Optional[str] = typer.Option(
414
+ None, "--output", "-o", help="Output file path"
415
+ ),
416
+ page_size: Optional[int] = typer.Option(
417
+ None, "--page-size", help="Number of results per page"
418
+ ),
419
+ properties: Optional[str] = typer.Option(
420
+ None, "--properties", help="Comma-separated list of properties to include"
421
+ ),
422
+ branch: Optional[str] = typer.Option(None, "--branch", "-b", help="Branch name"),
423
+ ):
424
+ """Search objects by query."""
425
+ try:
426
+ service = OntologyObjectService(profile=profile)
427
+
428
+ prop_list = properties.split(",") if properties else None
429
+
430
+ with SpinnerProgressTracker().track_spinner(
431
+ f"Searching {object_type} objects..."
432
+ ):
433
+ objects = service.search_objects(
434
+ ontology_rid,
435
+ object_type,
436
+ query,
437
+ page_size=page_size,
438
+ properties=prop_list,
439
+ branch=branch,
440
+ )
441
+
442
+ if format == "table" and objects:
443
+ # Use first object's keys as columns
444
+ columns = list(objects[0].keys()) if objects else []
445
+ formatter.format_table(
446
+ objects, columns=columns, format=format, output=output
447
+ )
448
+ else:
449
+ formatter.format_list(objects, format=format, output=output)
450
+
451
+ if output:
452
+ formatter.print_success(f"Search results saved to {output}")
453
+
454
+ except (ProfileNotFoundError, MissingCredentialsError) as e:
455
+ formatter.print_error(f"Authentication error: {e}")
456
+ raise typer.Exit(1)
457
+ except Exception as e:
458
+ formatter.print_error(f"Failed to search objects: {e}")
459
+ raise typer.Exit(1)
460
+
461
+
369
462
  # Action commands
370
463
  @app.command("action-apply")
371
464
  def apply_action(
@@ -487,18 +487,15 @@ class DatasetService(BaseService):
487
487
  # Ensure output directory exists
488
488
  output_path.parent.mkdir(parents=True, exist_ok=True)
489
489
 
490
- file_content = self.service.Dataset.File.read(
490
+ # Use Dataset.File.content() which returns bytes directly
491
+ # Note: In SDK v1.27.0, the method is 'content' not 'read'
492
+ file_content = self.service.Dataset.File.content(
491
493
  dataset_rid=dataset_rid, file_path=file_path, branch_name=branch
492
494
  )
493
495
 
494
- # Write file content to disk
496
+ # Write file content to disk (file_content is bytes)
495
497
  with open(output_path, "wb") as f:
496
- if hasattr(file_content, "read"):
497
- # If it's a stream
498
- f.write(file_content.read())
499
- else:
500
- # If it's bytes
501
- f.write(file_content)
498
+ f.write(file_content)
502
499
 
503
500
  return {
504
501
  "dataset_rid": dataset_rid,
@@ -287,6 +287,77 @@ class OntologyObjectService(BaseService):
287
287
  except Exception as e:
288
288
  raise RuntimeError(f"Failed to list linked objects: {e}")
289
289
 
290
+ def count_objects(
291
+ self,
292
+ ontology_rid: str,
293
+ object_type: str,
294
+ branch: Optional[str] = None,
295
+ ) -> Dict[str, Any]:
296
+ """
297
+ Count objects of a specific type.
298
+
299
+ Args:
300
+ ontology_rid: Ontology Resource Identifier
301
+ object_type: Object type API name
302
+ branch: Branch name (optional)
303
+
304
+ Returns:
305
+ Dictionary containing count information
306
+ """
307
+ try:
308
+ count = self.service.OntologyObject.count(
309
+ ontology_rid,
310
+ object_type,
311
+ branch_name=branch,
312
+ )
313
+ return {
314
+ "ontology_rid": ontology_rid,
315
+ "object_type": object_type,
316
+ "count": count,
317
+ "branch": branch,
318
+ }
319
+ except Exception as e:
320
+ raise RuntimeError(f"Failed to count objects: {e}")
321
+
322
+ def search_objects(
323
+ self,
324
+ ontology_rid: str,
325
+ object_type: str,
326
+ query: str,
327
+ page_size: Optional[int] = None,
328
+ properties: Optional[List[str]] = None,
329
+ branch: Optional[str] = None,
330
+ ) -> List[Dict[str, Any]]:
331
+ """
332
+ Search objects by query.
333
+
334
+ Args:
335
+ ontology_rid: Ontology Resource Identifier
336
+ object_type: Object type API name
337
+ query: Search query string
338
+ page_size: Number of results per page
339
+ properties: List of properties to include
340
+ branch: Branch name (optional)
341
+
342
+ Returns:
343
+ List of matching object dictionaries
344
+ """
345
+ try:
346
+ result = self.service.OntologyObject.search(
347
+ ontology_rid,
348
+ object_type,
349
+ query=query,
350
+ page_size=page_size,
351
+ properties=properties,
352
+ branch_name=branch,
353
+ )
354
+ objects = []
355
+ for obj in result:
356
+ objects.append(self._format_object(obj))
357
+ return objects
358
+ except Exception as e:
359
+ raise RuntimeError(f"Failed to search objects: {e}")
360
+
290
361
  def _format_object(self, obj: Any) -> Dict[str, Any]:
291
362
  """Format object for consistent output."""
292
363
  # Objects may have various properties - extract them dynamically
@@ -220,6 +220,111 @@ def test_list_linked_objects_command(mock_services):
220
220
  mock_instance.list_linked_objects.assert_called_once()
221
221
 
222
222
 
223
+ def test_count_objects_command(mock_services):
224
+ """Test count objects command."""
225
+ mock_instance = Mock()
226
+ mock_instance.count_objects.return_value = {
227
+ "ontology_rid": "ri.ontology.main.ontology.test",
228
+ "object_type": "Employee",
229
+ "count": 42,
230
+ "branch": None,
231
+ }
232
+ mock_services["object"].return_value = mock_instance
233
+
234
+ result = runner.invoke(
235
+ app, ["object-count", "ri.ontology.main.ontology.test", "Employee"]
236
+ )
237
+
238
+ assert result.exit_code == 0
239
+ mock_instance.count_objects.assert_called_once_with(
240
+ "ri.ontology.main.ontology.test", "Employee", branch=None
241
+ )
242
+
243
+
244
+ def test_count_objects_with_branch(mock_services):
245
+ """Test count objects with branch specified."""
246
+ mock_instance = Mock()
247
+ mock_instance.count_objects.return_value = {
248
+ "ontology_rid": "ri.ontology.main.ontology.test",
249
+ "object_type": "Employee",
250
+ "count": 24,
251
+ "branch": "master",
252
+ }
253
+ mock_services["object"].return_value = mock_instance
254
+
255
+ result = runner.invoke(
256
+ app,
257
+ [
258
+ "object-count",
259
+ "ri.ontology.main.ontology.test",
260
+ "Employee",
261
+ "--branch",
262
+ "master",
263
+ ],
264
+ )
265
+
266
+ assert result.exit_code == 0
267
+ mock_instance.count_objects.assert_called_once_with(
268
+ "ri.ontology.main.ontology.test", "Employee", branch="master"
269
+ )
270
+
271
+
272
+ def test_search_objects_command(mock_services):
273
+ """Test search objects command."""
274
+ mock_instance = Mock()
275
+ mock_instance.search_objects.return_value = [
276
+ {"employee_id": "EMP001", "name": "John Doe"}
277
+ ]
278
+ mock_services["object"].return_value = mock_instance
279
+
280
+ result = runner.invoke(
281
+ app,
282
+ [
283
+ "object-search",
284
+ "ri.ontology.main.ontology.test",
285
+ "Employee",
286
+ "--query",
287
+ "John",
288
+ ],
289
+ )
290
+
291
+ assert result.exit_code == 0
292
+ mock_instance.search_objects.assert_called_once()
293
+
294
+
295
+ def test_search_objects_with_options(mock_services):
296
+ """Test search objects with all options."""
297
+ mock_instance = Mock()
298
+ mock_instance.search_objects.return_value = [
299
+ {"employee_id": "EMP001", "name": "John Doe"}
300
+ ]
301
+ mock_services["object"].return_value = mock_instance
302
+
303
+ result = runner.invoke(
304
+ app,
305
+ [
306
+ "object-search",
307
+ "ri.ontology.main.ontology.test",
308
+ "Employee",
309
+ "--query",
310
+ "Jane",
311
+ "--page-size",
312
+ "10",
313
+ "--properties",
314
+ "name,department",
315
+ "--branch",
316
+ "master",
317
+ ],
318
+ )
319
+
320
+ assert result.exit_code == 0
321
+ call_args = mock_instance.search_objects.call_args
322
+ assert call_args[0] == ("ri.ontology.main.ontology.test", "Employee", "Jane")
323
+ assert call_args[1]["page_size"] == 10
324
+ assert call_args[1]["properties"] == ["name", "department"]
325
+ assert call_args[1]["branch"] == "master"
326
+
327
+
223
328
  # Action command tests
224
329
  def test_apply_action_command(mock_services):
225
330
  """Test apply action command."""
@@ -335,6 +335,85 @@ def test_list_linked_objects(mock_ontology_object_service, sample_object):
335
335
  mock_ontology_object_class.list_linked_objects.assert_called_once()
336
336
 
337
337
 
338
+ def test_count_objects(mock_ontology_object_service):
339
+ """Test counting objects."""
340
+ service, mock_ontology_object_class = mock_ontology_object_service
341
+ mock_ontology_object_class.count.return_value = 42
342
+
343
+ result = service.count_objects("ri.ontology.main.ontology.test", "Employee")
344
+
345
+ assert result["count"] == 42
346
+ assert result["ontology_rid"] == "ri.ontology.main.ontology.test"
347
+ assert result["object_type"] == "Employee"
348
+ assert result["branch"] is None
349
+ mock_ontology_object_class.count.assert_called_once_with(
350
+ "ri.ontology.main.ontology.test", "Employee", branch_name=None
351
+ )
352
+
353
+
354
+ def test_count_objects_with_branch(mock_ontology_object_service):
355
+ """Test counting objects with branch specified."""
356
+ service, mock_ontology_object_class = mock_ontology_object_service
357
+ mock_ontology_object_class.count.return_value = 24
358
+
359
+ result = service.count_objects(
360
+ "ri.ontology.main.ontology.test", "Employee", branch="master"
361
+ )
362
+
363
+ assert result["count"] == 24
364
+ assert result["branch"] == "master"
365
+ mock_ontology_object_class.count.assert_called_once_with(
366
+ "ri.ontology.main.ontology.test", "Employee", branch_name="master"
367
+ )
368
+
369
+
370
+ def test_search_objects(mock_ontology_object_service, sample_object):
371
+ """Test searching objects."""
372
+ service, mock_ontology_object_class = mock_ontology_object_service
373
+ mock_ontology_object_class.search.return_value = [sample_object]
374
+
375
+ result = service.search_objects(
376
+ "ri.ontology.main.ontology.test", "Employee", "John"
377
+ )
378
+
379
+ assert len(result) == 1
380
+ assert result[0]["employee_id"] == "EMP001"
381
+ assert result[0]["name"] == "John Doe"
382
+ mock_ontology_object_class.search.assert_called_once_with(
383
+ "ri.ontology.main.ontology.test",
384
+ "Employee",
385
+ query="John",
386
+ page_size=None,
387
+ properties=None,
388
+ branch_name=None,
389
+ )
390
+
391
+
392
+ def test_search_objects_with_options(mock_ontology_object_service, sample_object):
393
+ """Test searching objects with all options."""
394
+ service, mock_ontology_object_class = mock_ontology_object_service
395
+ mock_ontology_object_class.search.return_value = [sample_object]
396
+
397
+ result = service.search_objects(
398
+ "ri.ontology.main.ontology.test",
399
+ "Employee",
400
+ "Jane",
401
+ page_size=10,
402
+ properties=["name", "department"],
403
+ branch="master",
404
+ )
405
+
406
+ assert len(result) == 1
407
+ mock_ontology_object_class.search.assert_called_once_with(
408
+ "ri.ontology.main.ontology.test",
409
+ "Employee",
410
+ query="Jane",
411
+ page_size=10,
412
+ properties=["name", "department"],
413
+ branch_name="master",
414
+ )
415
+
416
+
338
417
  # ActionService Tests
339
418
  def test_apply_action(mock_action_service, sample_action_result):
340
419
  """Test applying an action."""
@@ -710,7 +710,7 @@ wheels = [
710
710
 
711
711
  [[package]]
712
712
  name = "pltr-cli"
713
- version = "0.10.0"
713
+ version = "0.11.0"
714
714
  source = { editable = "." }
715
715
  dependencies = [
716
716
  { name = "click-repl" },
@@ -1 +0,0 @@
1
- __version__ = "0.10.0"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes