afv-library/skills/platform-data-and-tooling-api-context-get/examples/python_section_loading.py

110 lines
4.0 KiB
Python

#!/usr/bin/env python3
"""
Salesforce Data + Tooling API - Section-Specific Loading Examples (Python)
Demonstrates loading only the sections you need from the enterprise (SOQL/DML
sObject) and Tooling (developer record) JSON files, and how to traverse this
skill's surface-specific structure:
- enterprise `fields` carry query/DML `properties` (Create/Filter/Sort/Group/
Nillable/Update) plus relationship metadata (relationship_name / refers_to)
- `field_reference` is a SEPARATE catalog, not a subset of `fields`
- Tooling records expose supported_rest_api_http_methods / supported_soap_calls
CRITICAL: Do NOT Read/cat these JSON files whole — Account.json etc. carry a
huge wsdl_segment. Extract only the section you need.
"""
import json
from pathlib import Path
ENTERPRISE_DIR = Path('assets/enterprise_api')
TOOLING_DIR = Path('assets/tooling_api')
def _load(path):
with open(path, 'r', encoding='utf-8') as f:
return json.load(f)
def load_fields_section():
"""Example 1: Load ONLY the 'fields' section from an enterprise sObject."""
data = _load(ENTERPRISE_DIR / 'Account.json')
fields = data.get('fields', {})
# Skip wsdl_segment (verbose) and field_reference (load separately if needed)
print(f"Account has {len(fields)} fields in the 'fields' section")
return fields
def find_filterable_fields():
"""Example 2: Find filterable fields (usable in a SOQL WHERE clause).
The `properties` string controls capability: Filter -> WHERE, Sort ->
ORDER BY, Group -> GROUP BY, Create/Update -> DML. Compare case-insensitively.
"""
data = _load(ENTERPRISE_DIR / 'Opportunity.json')
filterable = [
name for name, meta in data.get('fields', {}).items()
if 'filter' in (meta.get('properties', '') or '').lower()
]
print(f"Opportunity has {len(filterable)} filterable fields; first 5: {filterable[:5]}")
return filterable
def traverse_relationship():
"""Example 3: Traverse a relationship (reference field -> parent object).
relationship_name is the SOQL traversal path; refers_to names the target.
"""
data = _load(ENTERPRISE_DIR / 'Contact.json')
account = data.get('fields', {}).get('AccountId', {})
print(f"AccountId -> relationship_name={account.get('relationship_name')} "
f"refers_to={account.get('refers_to')}")
print("SOQL: SELECT Id, Account.Name FROM Contact")
return account
def check_both_catalogs():
"""Example 4: Check BOTH catalogs — field_reference is NOT a subset of fields.
System/audit fields (Id, CreatedDate, ...) frequently live ONLY in
field_reference. If a field isn't in `fields`, check `field_reference`.
"""
data = _load(ENTERPRISE_DIR / 'Account.json')
fields = set(data.get('fields', {}))
ref = set(data.get('field_reference', {}))
only_in_ref = sorted(ref - fields)
print(f"Account: fields={len(fields)} field_reference={len(ref)}")
print(f"Only in field_reference (first 5): {only_in_ref[:5]}")
return only_in_ref
def tooling_supported_methods():
"""Example 5: Tooling record — check supported HTTP methods before querying.
Tooling objects query against /services/data/vXX.0/tooling/query, not the
regular Data API. Many are read-only; check the methods first.
"""
data = _load(TOOLING_DIR / 'ApexClass.json')
methods = data.get('supported_rest_api_http_methods', '')
field_names = list(data.get('fields', {}).keys())[:5]
print(f"ApexClass REST methods: {methods}")
print(f"First 5 ApexClass fields: {field_names}")
return methods
if __name__ == '__main__':
print("Example 1: enterprise fields section")
load_fields_section()
print("\nExample 2: filterable fields (WHERE-safe)")
find_filterable_fields()
print("\nExample 3: relationship traversal")
traverse_relationship()
print("\nExample 4: fields vs field_reference (dual catalog)")
check_both_catalogs()
print("\nExample 5: Tooling API supported methods")
tooling_supported_methods()