DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).
timestamp: str = field(default_factory=lambda: datetime.utcnow().isoformat() + 'Z')
Remote SPARQL Query
Execute SPARQL queries against remote endpoints and return result handles.
Query Rewriting Helper
Helper to inject LIMIT clauses into SELECT queries to bound server-side work.
# Test LIMIT injectionq1 ="SELECT ?s ?p ?o WHERE { ?s ?p ?o }"modified, injected = _inject_limit(q1, 100)assert injected ==Trueassert'LIMIT 100'in modifiedprint(f"✓ Basic injection: {modified}")# Test with existing LIMIT (should not modify)q2 ="SELECT ?s WHERE { ?s ?p ?o } LIMIT 50"modified, injected = _inject_limit(q2, 100)assert injected ==Falseassert modified == q2print(f"✓ Existing LIMIT preserved: {modified}")# Test with ORDER BY (inject before it)q3 ="SELECT ?s ?o WHERE { ?s ?p ?o } ORDER BY ?s"modified, injected = _inject_limit(q3, 100)assert injected ==Trueassert'LIMIT 100'in modifiedassert modified.index('LIMIT') < modified.index('ORDER')print(f"✓ Injection before ORDER BY: {modified}")# Test CONSTRUCT (should not inject)q4 ="CONSTRUCT { ?s ?p ?o } WHERE { ?s ?p ?o }"modified, injected = _inject_limit(q4, 100)assert injected ==Falseprint(f"✓ CONSTRUCT not modified: {modified}")
✓ Basic injection: SELECT ?s ?p ?o WHERE { ?s ?p ?o } LIMIT 100
✓ Existing LIMIT preserved: SELECT ?s WHERE { ?s ?p ?o } LIMIT 50
✓ Injection before ORDER BY: SELECT ?s ?o WHERE { ?s ?p ?o } LIMIT 100 ORDER BY ?s
✓ CONSTRUCT not modified: CONSTRUCT { ?s ?p ?o } WHERE { ?s ?p ?o }
Execute SPARQL query, store SPARQLResultHandle in namespace.
For SELECT: Stores SPARQLResultHandle with rows as list of dicts For CONSTRUCT/DESCRIBE: Stores SPARQLResultHandle with rdflib.Graph For ASK: Stores SPARQLResultHandle with boolean result
IMPORTANT - Work Bounds: - For SELECT: Automatically injects LIMIT clause to bound server-side work - For CONSTRUCT/DESCRIBE: max_results only truncates locally; full results still fetched from endpoint (SPARQL 1.1 has no standard LIMIT for graphs)
If ds_meta provided and store_in_work=True: - CONSTRUCT results stored in work/ graph - Query logged to prov graph
Args: query: SPARQL query string endpoint: SPARQL endpoint URL max_results: Maximum results to return (for SELECT/CONSTRUCT) name: Variable name to store result handle ns: Namespace dict (defaults to globals()) timeout: Query timeout in seconds ds_meta: Optional DatasetMeta for dataset integration store_in_work: If True and ds_meta provided, store CONSTRUCT results in work graph work_task_id: Task ID for work graph (auto-generated if None)
Useful for querying mounted ontologies or work graphs. Returns SPARQLResultHandle same as sparql_query().
IMPORTANT - Work Bounds: - max_results is output truncation only; full result set is materialized - For large local graphs, consider filtering in the SPARQL query itself
Args: query: SPARQL query string graph: rdflib.Graph object or name of graph in namespace max_results: Maximum results to return name: Variable name to store result handle ns: Namespace dict (defaults to globals())
Returns: Summary string describing the result
Test with local graph:
# Create test graphtest_graph = Graph()test_graph.add((URIRef('http://ex.org/alice'), URIRef('http://ex.org/age'), Literal('30')))test_graph.add((URIRef('http://ex.org/bob'), URIRef('http://ex.org/age'), Literal('25')))test_graph.add((URIRef('http://ex.org/alice'), URIRef('http://ex.org/city'), Literal('Boston')))test_ns = {'my_graph': test_graph}# Test SELECT query on local graphresult = sparql_local("SELECT ?s ?age WHERE { ?s <http://ex.org/age> ?age }",'my_graph', ns=test_ns, name='local_res')print(result)assert'local_res'in test_nsassert test_ns['local_res'].result_type =='select'assertlen(test_ns['local_res'].rows) ==2assert test_ns['local_res'].total_rows ==2print(f"✓ Local SELECT query works: {test_ns['local_res'].rows}")# Test CONSTRUCT on local graphresult = sparql_local("CONSTRUCT { ?s <http://ex.org/age> ?age } WHERE { ?s <http://ex.org/age> ?age }", test_graph, ns=test_ns, name='local_graph')print(result)assert test_ns['local_graph'].result_type =='construct'assertlen(test_ns['local_graph'].rows) ==2assert test_ns['local_graph'].triple_count ==2assert test_ns['local_graph'].total_triples ==2print(f"✓ Local CONSTRUCT query works")# Test truncationresult = sparql_local("CONSTRUCT { ?s ?p ?o } WHERE { ?s ?p ?o }", test_graph, max_results=2, ns=test_ns, name='truncated')print(result)assertlen(test_ns['truncated'].rows) ==2assert test_ns['truncated'].triple_count ==2assert test_ns['truncated'].total_triples ==3# Original had 3assert'(of 3 total)'in test_ns['truncated'].summary()print(f"✓ Truncation works correctly: {test_ns['truncated'].summary()}")
SELECT result with 2 rows, columns: ['s', 'age'], stored in 'local_res'
✓ Local SELECT query works: [{'s': rdflib.term.URIRef('http://ex.org/alice'), 'age': rdflib.term.Literal('30')}, {'s': rdflib.term.URIRef('http://ex.org/bob'), 'age': rdflib.term.Literal('25')}]
Graph with 2 triples stored in 'local_graph'
✓ Local CONSTRUCT query works
Graph with 2 triples stored in 'truncated' (of 3 total)
✓ Truncation works correctly: CONSTRUCT: 2 triples (of 3 total)
DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).
timestamp: str = field(default_factory=lambda: datetime.utcnow().isoformat() + 'Z')
View Operations
Bounded view functions for progressive disclosure over result sets.
These functions work with SPARQLResultHandle, ResultTable, or plain lists.
Args: result: SPARQLResultHandle, ResultTable, or list n: Number of rows to sample seed: Optional random seed for reproducibility
Returns: List of sampled rows
Test res_sample:
# Test with listtest_list = [{'x': i} for i inrange(20)]sample = res_sample(test_list, n=5, seed=42)assertlen(sample) ==5assertall(isinstance(item, dict) for item in sample)print(f"✓ res_sample works with list: {len(sample)} items")# Test with SPARQLResultHandlehandle = SPARQLResultHandle( rows=[{'s': f'http://ex.org/item{i}'} for i inrange(15)], result_type='select', query='SELECT ?s WHERE { ?s ?p ?o }', endpoint='local', columns=['s'], total_rows=15)sample = res_sample(handle, n=3, seed=42)assertlen(sample) ==3print(f"✓ res_sample works with SPARQLResultHandle")# Test with small result (no sampling needed)small_list = [1, 2, 3]sample = res_sample(small_list, n=10)assertlen(sample) ==3print(f"✓ res_sample handles small results correctly")
✓ res_sample works with list: 5 items
✓ res_sample works with SPARQLResultHandle
✓ res_sample handles small results correctly
DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).
timestamp: str = field(default_factory=lambda: datetime.utcnow().isoformat() + 'Z')
Setup Function
Initialize SPARQL tools in namespace for RLM sessions.
Binds: - sparql_query() with default endpoint - sparql_local() if ds_meta provided - res_head(), res_where(), res_group(), res_distinct(), res_sample()
Args: ns: Namespace dict where functions will be bound default_endpoint: Default SPARQL endpoint URL ds_meta: Optional DatasetMeta for dataset integration
Returns: Status message
Test setup function:
# Test basic setuptest_ns = {}result = setup_sparql_context(test_ns)print(result)assert'sparql_query'in test_nsassert'sparql_local'in test_nsassert'res_sample'in test_nsprint(f"✓ Setup function works")# Test with dataset integrationtry:from rlm.dataset import DatasetMetafrom rdflib import Dataset ds = Dataset() ds_meta = DatasetMeta(ds, name='test') test_ns2 = {} result = setup_sparql_context(test_ns2, ds_meta=ds_meta)print(result)assert'session:'in resultprint(f"✓ Setup with dataset integration works")exceptImportError:print("⊘ Dataset module not available, skipping integration test")
SPARQL context initialized with endpoint: https://query.wikidata.org/sparql
Bound functions: sparql_query, sparql_local, res_sample, res_head, res_where, res_group, res_distinct
✓ Setup function works
SPARQL context initialized with endpoint: https://query.wikidata.org/sparql
Dataset integration enabled (session: d6379b48)
Bound functions: sparql_query, sparql_local, res_sample, res_head, res_where, res_group, res_distinct
✓ Setup with dataset integration works
Usage Examples
End-to-end examples showing SPARQL handles in RLM context.
# Example 1: Basic SPARQL workflowns = {}setup_sparql_context(ns)# Execute query (LLM would do this)ns['sparql_query']('SELECT ?s ?p ?o WHERE { ?s ?p ?o } LIMIT 10', name='results')# Inspect resultsprint(ns['results'].summary())print(ns['res_head'](ns['results'], 5))print(ns['res_sample'](ns['results'], 3))
# Example 2: Dataset integrationfrom rlm.dataset import setup_dataset_contextns = {}setup_dataset_context(ns)setup_sparql_context(ns, ds_meta=ns['ds_meta'])# Query and store in work graphns['sparql_query']('CONSTRUCT { ?s ?p ?o } WHERE { ?s ?p ?o } LIMIT 5', name='discovered_triples', store_in_work=True, work_task_id='discovery_1')# Check provenanceprint(ns['dataset_stats']())
# Example 3: Local graph queriesfrom rlm.ontology import setup_ontology_contextns = {}setup_sparql_context(ns)setup_ontology_context('ontology/prov.ttl', ns, name='prov')# Query mounted ontologyns['sparql_local']('SELECT ?c WHERE { ?c a <http://www.w3.org/2002/07/owl#Class> }','prov', name='classes')print(f"Found {len(ns['classes'].rows)} classes")print(ns['res_head'](ns['classes'], 10))