Skip to main content

Shared Python SDK for SAP SuccessFactors tools - OData client, auth, config, and Flask base

Project description

sapsf-shared

Shared Python SDK for SAP SuccessFactors tools.

A single, well-tested library that extracts the common patterns repeated across every SAP SF tool in your workspace: OData HTTP client, authentication, config loading, logging, utilities, and Flask boilerplate.

Why this exists

Every SAP SF tool in your workspace reimplements:

  • OData v2 HTTP client with retries and pagination
  • Basic Auth / OAuth2 / Certificate auth handling
  • Keyring vs file-based credential storage
  • Config loader (YAML/JSON with env var substitution)
  • Coloured logging setup
  • Flask CSRF, error handlers, health endpoint

sapsf-shared consolidates all of this into one package. When you fix a bug in the auth layer, it's fixed everywhere.

Installation

cd sapsf/_shared
pip install -e ".[dev,flask]"

Quick Start

1. Connect to SAP SuccessFactors

from sapsf_shared import AuthConfig, SFClient

config = AuthConfig(
    base_url="https://api4.successfactors.com/odata/v2",
    username="admin@companyId",
    password="secret",
    company_id="companyId",
    auth_type="basic",
)

with SFClient(config) as client:
    # Fetch all departments
    depts = client.get("FODepartment")
    print(f"Found {len(depts)} departments")

    # Fetch with filter and pagination
    positions = client.get(
        "Position",
        filter_expr="cust_Country eq 'GBR'",
        select=["code", "externalName", "cust_JobFunction"],
        expand=["cust_JobFunction"],
    )

2. OAuth 2.0

config = AuthConfig(
    base_url="https://api4.successfactors.com/odata/v2",
    auth_type="oauth2",
    client_id="my_client_id",
    client_secret="my_secret",
    company_id="companyId",
)
with SFClient(config) as client:
    ok, msg = client.test_connection()
    print(ok, msg)

3. Secure credential storage

from sapsf_shared.auth import CredentialStore

store = CredentialStore(service="my_tool")
store.set("prd:password", "secret123")
pwd = store.get("prd:password")

Automatically uses OS keyring when available; falls back to a chmod-600 JSON file on headless systems.

4. Config from YAML

from sapsf_shared.config import load_config

cfg = load_config("config.yaml")
# Supports ${ENV_VAR} substitution inside the YAML file

5. Flask base app

from sapsf_shared.flask_base import create_app

app = create_app(__name__, log_dir="logs", enable_csrf=True)

@app.route("/")
def index():
    return {"status": "ok"}

if __name__ == "__main__":
    app.run(port=5050)

Comes with built-in:

  • /api/health endpoint
  • CSRF token generation + validation
  • JSON error handlers (400, 403, 404, 500)
  • CORS preflight support
  • Rotating file logging

API Reference

SFClient

Method Description
get(entity_set, **kwargs) Fetch all records with auto-pagination
get_entity_by_code(entity_set, external_code, **kwargs) Filter by externalCode
post(entity_set, payload) Create a record
patch(entity_set, payload) Update a record
delete(entity_set, key) Delete a record
test_connection() Quick connectivity probe
entity_exists(entity_set, external_code) Check existence

AuthConfig

Dataclass that normalises auth settings across all your tools. Fields: base_url, company_id, auth_type, username, password, client_id, client_secret, token_url, cert_path, key_path, timeout_sec.

SFEnvConfig

Loads configuration from environment variables with the standard SF_* prefix:

export SF_BASE_URL=https://api4.successfactors.com/odata/v2
export SF_USERNAME=admin
export SF_PASSWORD=secret
export SF_COMPANY_ID=companyId
cfg = SFEnvConfig.from_env()

CredentialStore

Keyring-backed secret storage with automatic fallback to a local .secrets.json file (chmod 600). Use store.clear_alias(alias) to delete all secrets for a tenant.

Utilities

Function Description
parse_sf_date(raw) Parse /Date(millis)/ and ISO formats
is_active_today(record) Check effective dating + status
flatten_record(record) Flatten nested OData for CSV export
build_odata_filter(dict) Build $filter strings from dicts

Development

pip install -e ".[dev,flask]"
pytest -v                  # 13 tests
mypy src/sapsf_shared      # Type checking
ruff check src tests       # Linting
ruff format src tests      # Formatting

Roadmap

  • Vectorised batch operations (upsert_many, delete_many)
  • Connection pooling tuning
  • Async support (httpx-based client)
  • SAP SF API v4 support

License

MIT

Adoption status

Tool Status
sf-config-compare Adopted - parse_sf_date via sapsf_shared.utils
sf-position-integrity-checker Next - client/pagination migration pending tenant testing
sf-object-sync Planned

Depend on it from any tool:

sapsf-shared @ git+https://github.com/SahirVhora/sapsf-shared

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

sapsf_shared-0.1.0.tar.gz (23.7 kB view details)

Uploaded Source

Built Distribution

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

sapsf_shared-0.1.0-py3-none-any.whl (19.5 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: sapsf_shared-0.1.0.tar.gz
  • Upload date:
  • Size: 23.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for sapsf_shared-0.1.0.tar.gz
Algorithm Hash digest
SHA256 0bd408426b8e3a65ea1f1531d8efac6144fd6bdfef008b4e798ab56910cf438b
MD5 05affee4b6427b4583d310f2e7e8efba
BLAKE2b-256 c411303dbe580dafe6f0c56170a1c303ecd7ad5b8bd8293c749792a020e0781a

See more details on using hashes here.

Provenance

The following attestation bundles were made for sapsf_shared-0.1.0.tar.gz:

Publisher: publish.yml on SahirVhora/sapsf-shared

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

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

File metadata

  • Download URL: sapsf_shared-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 19.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for sapsf_shared-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ad92eb6b05860927025d892ca845ac78213dee1e7fdfb91a84f28258d6ac3c0f
MD5 768590cbc1293726dd51defcd7e0a423
BLAKE2b-256 46e343086750a3c9a814a8d34b183c4b52d0e9992377b50712eca5ae8e69d781

See more details on using hashes here.

Provenance

The following attestation bundles were made for sapsf_shared-0.1.0-py3-none-any.whl:

Publisher: publish.yml on SahirVhora/sapsf-shared

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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