Skip to main content

Terminal explorer for OData CSDL metadata

Project description

CSDL Explorer

A terminal explorer for OData CSDL metadata. Parse any $metadata XML and discover entities, properties, relationships, and field attributes — then query live OData services directly from the terminal.

Features:

  • Interactive Rich REPL with colored tables and visual trees
  • Full Textual TUI with tree navigation, tabbed views, and split panes
  • Live OData queries with visual query builder (filter, select, expand, orderby)
  • SAP SuccessFactors auth support (Bearer, Basic, OAuth2 SAML)
  • Picklist exploration with impact analysis
  • Headless mode for scripting and AI assistants
  • Search across entity names, property names, labels, and picklist values
  • Entity comparison, custom field discovery, navigation graphs
  • Switchable color themes

The Problem

OData services expose their schema through $metadata but those XML documents can be enormous (10MB+, 700+ entities). This tool parses the CSDL and gives you fast, searchable access to every entity, property, navigation relationship, and annotation.

Particularly useful with SAP SuccessFactors, where documentation says "Worker Category" but the actual field is customString17.

Installation

pip install csdl-explore

For the full Textual TUI (tree navigation, split panes, query builder):

pip install csdl-explore[tui]

Or from source:

git clone https://github.com/guinetik/csdl-explore
cd csdl-explore
pip install -e .        # Basic install
pip install -e ".[tui]" # With Textual TUI

Quick Start

# Point at any OData $metadata XML file
csdl-explore metadata.xml

# Search for fields
csdl-explore metadata.xml search contract

# Show entity details
csdl-explore metadata.xml entity EmpJob

# Launch full TUI with tree navigation
csdl-explore metadata.xml --tui

# Query a live OData service
csdl-explore metadata.xml query EmpJob --select "userId,company" --top 5

Usage

# Start interactive explorer (default)
csdl-explore metadata.xml

# Or with --file flag
csdl-explore --file metadata.xml entity EmpJob

# With connection settings
csdl-explore metadata.xml --base-url https://api.example.com --auth-type bearer --bearer-token TOKEN

Interactive Mode

$ csdl-explore metadata.xml

╭─────────────────────────────────────────╮
│             CSDL Explorer               │
│         Loaded 735 entities             │
╰─────────────────────────────────────────╯

csdl> search contract
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Search Results (4)                             ┃
┣━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━┫
┃ Type   ┃ Entity    ┃ Match           ┃ Details ┃
┣━━━━━━━━╋━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━╋━━━━━━━━━┫
┃ PROP   ┃ EmpJob    ┃ .contractType   ┃ String  ┃
┃ NAV    ┃ EmpJob    ┃ .contractTypeNav┃         ┃
┗━━━━━━━━┻━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━┻━━━━━━━━━┛

csdl> tree EmpJob
EmpJob
├── Keys
│   ├── seqNumber Edm.Int64
│   ├── startDate Edm.DateTime
│   └── userId Edm.String
├── Properties (45)
│   ├── businessUnit Edm.String
│   ├── company Edm.String
│   └── ... and 42 more
├── Lookups (12)
│   ├── businessUnit -> FOBusinessUnit
│   └── ... and 9 more
├── Custom Fields (24)
│   ├── customString7 Edm.String
│   └── ... and 23 more
└── Navigation (8)
    ├── employmentNav -> EmpEmployment
    └── ... and 7 more

Commands

Metadata Exploration

Command Aliases Description
entities List all entity types (multi-column on wide terminals)
entity <name> e Show all properties of an entity
tree <name> t Show entity as visual tree with relationships
model [entities] Show data model overview
search <term> s Search entities and properties
custom <entity> c Show custom fields (customStringXX)
nav <entity> Show navigation properties
diff <e1> <e2> Compare two entities
path <entity> paths Suggest JSON paths
emp List Emp* entities (SAP SuccessFactors)
per List Per* entities (SAP SuccessFactors)

Picklists

Command Aliases Description
picklists List all picklists used across entities (JSON)
picklist <name> pk Fetch picklist values from live API (JSON)
batch-picklists <entity> Fetch all picklist values for an entity's fields

OData Queries

Command Description
query <entity> Execute an OData query against a live service

Query flags:

Flag Description
--select "<props>" Comma-separated properties to return
--filter "<expr>" OData $filter expression
--orderby "<prop>" Property to sort by
--orderby-dir "asc|desc" Sort direction (default: asc)
--top <n> Result limit (default: 20)
--expand "<navs>" Navigation properties to expand
--asof-date "<date>" Point-in-time query
--from-date "<date>" Date range start
--to-date "<date>" Date range end

Example:

csdl-explore metadata.xml query EmpJob \
  --select "userId,company,businessUnit" \
  --filter "company eq 'ACME'" \
  --top 10

Options

Option Description
--file <file> Path to metadata XML file
--tui Launch full Textual TUI
--base-url <url> OData service base URL
--auth-type <type> Auth type: none, bearer, basic, oauth2
--bearer-token <token> Bearer token for API access
--username <user> Username for basic auth
--password <pass> Password for basic auth
--format <fmt> Output format: table (default), json, json-compact, csv
--wide Show full column widths (no truncation)
--filter <pattern> Filter properties by name glob pattern (e.g. "custom*")
--json-only JSON output only, no banner (for agents/scripts)

Connection settings can also be loaded from a .env file placed alongside the metadata XML, or from environment variables (SAP_BASE_URL, SAP_AUTH_TYPE, SAP_BEARER_TOKEN, etc.).

Exit Codes

Code Meaning
0 Success
1 General error
2 Invalid input (bad args, missing params)
3 Network error (auth failure, HTTP error)
4 Not found (entity/picklist doesn't exist)

Full Textual TUI

For the best experience on large monitors, use the Textual TUI:

pip install csdl-explore[tui]
csdl-explore metadata.xml --tui

Features:

  • Tree navigation - Browse entities by category (Emp*, Per*, alphabetical)
  • Split pane view - Entity tree on left, tabbed details on right
  • Global search - Search across all metadata from the sidebar
  • Fuzzy filter - Type in any table to filter rows (fzf-style)
  • Entity tabs - Details, Properties table, and Query sub-tabs per entity
  • Picklist tabs - Overview, entity usage, impact analysis, and live value fetching
  • Query builder - Visual form for OData queries with auth configuration
  • Results viewer - Syntax-highlighted JSON/XML results with file export
  • Navigation graph - Visualize entity relationships
  • Switchable themes - Vercel dark, Classic, and more

Keyboard shortcuts:

Key Action
/ Focus search
Escape Clear search
t Toggle tree sidebar
Ctrl+T Cycle theme
Ctrl+W Close current tab
q Quit
? Show help

Headless Mode (for AI/Scripts)

All commands work without interactive mode, making it easy for AI assistants and scripts to discover fields:

csdl-explore metadata.xml search benefit
csdl-explore metadata.xml entity EmpJob
csdl-explore metadata.xml diff EmpCompensation EmpPayCompRecurring
csdl-explore metadata.xml tree EmpJob
csdl-explore metadata.xml picklists
csdl-explore metadata.xml query EmpJob --select "userId" --top 5

Python API

from csdl_explore import CSDLExplorer
from pathlib import Path

# Load from file
explorer = CSDLExplorer.from_file(Path("metadata.xml"))

# Search
results = explorer.search("worker")
for r in results:
    print(f"{r.entity}.{r.property}: {r.prop_type}")

# Get entity details
entity = explorer.get_entity("EmpJob")
for prop in entity.properties.values():
    print(f"{prop.name}: {prop.type} (label={prop.label})")

# Get custom fields
for prop in explorer.get_custom_fields("EmpJob"):
    print(f"{prop.name}: {prop.label} picklist={prop.picklist}")

# Compare entities
comp = explorer.compare_entities("EmpCompensation", "EmpPayCompRecurring")
print(f"Only in first: {comp.only_in_entity1[:5]}")

# Picklist usage across all entities
usage = explorer.get_picklist_usage()
for picklist, entities in usage.items():
    print(f"{picklist}: used by {entities}")

Supported OData Services

Any OData service that exposes CSDL $metadata should work. Tested with:

  • SAP SuccessFactors (full annotation support: labels, picklists, CRUD flags)
  • SAP S/4HANA OData
  • Standard OData v2/v3 services

The parser auto-detects annotation namespaces, so vendor-specific attributes (like sap:label, sap:filterable) are extracted automatically.

Project Structure

csdl-explore/
├── pyproject.toml
├── README.md
└── src/
    └── csdl_explore/
        ├── __init__.py         # Package exports
        ├── cli.py              # CLI entry point & command dispatch
        ├── parser.py           # CSDL metadata parser
        ├── explorer.py         # High-level exploration API
        ├── formatters.py       # Pure data transforms (no UI imports)
        ├── themes.py           # Textual themes + Rich color palettes
        ├── repl.py             # Rich-based interactive REPL
        ├── sap_client.py       # Async OData HTTP client & auth
        ├── app.py              # Textual TUI application
        └── widgets/
            ├── entity_pane.py      # Entity tab container
            ├── details_tab.py      # Entity details sub-tab
            ├── properties_tab.py   # Filterable properties table
            ├── query_tab.py        # OData query sub-tab
            ├── query_builder.py    # Visual query form
            ├── connection_panel.py # Auth configuration panel
            ├── results_viewer.py   # Query results + export
            ├── picklist_pane.py    # Picklist tab container
            ├── entity_tree.py      # Sidebar tree widget
            ├── global_search.py    # Unified metadata search
            ├── filter_bar.py       # fzf-style filter bar
            ├── filterable_table.py # Reusable filterable DataTable
            ├── auth_modal.py       # Credential input modal
            ├── record_view_modal.py# Row detail viewer
            ├── nav_graph.py        # Navigation graph visualization
            └── welcome_tab.py      # Welcome screen

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

csdl_explore-0.1.0.tar.gz (117.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

csdl_explore-0.1.0-py3-none-any.whl (81.0 kB view details)

Uploaded Python 3

File details

Details for the file csdl_explore-0.1.0.tar.gz.

File metadata

  • Download URL: csdl_explore-0.1.0.tar.gz
  • Upload date:
  • Size: 117.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.3

File hashes

Hashes for csdl_explore-0.1.0.tar.gz
Algorithm Hash digest
SHA256 c9f8308e3e5cbb169f8222e1977a95aa3e67daf9da56d1f8defd0508d2bf1ebe
MD5 367931aa0e79a0e0b588278d442c09a7
BLAKE2b-256 c100b42a22a61f4616a506ac7618025e1a1769394d358104fb4f15c232b0bb64

See more details on using hashes here.

File details

Details for the file csdl_explore-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: csdl_explore-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 81.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.3

File hashes

Hashes for csdl_explore-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0c6cfcd5178a1531bf5cd42494ccab455acaa6d16bf01a3266b0ae794011a6cf
MD5 4f52f93ef6fa020a1ccbb68e4f569223
BLAKE2b-256 d1e0db0dc3faff67a70cb5d61fc382e015190e0b2e9cc873a2067e1ba8966140

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page