{"id":46364409,"url":"https://github.com/btoron/pyofsc","last_synced_at":"2026-03-05T02:00:58.477Z","repository":{"id":35266852,"uuid":"217085479","full_name":"btoron/pyOFSC","owner":"btoron","description":"Python Wrapper for Oracle Field Service Cloud API","archived":false,"fork":false,"pushed_at":"2026-03-03T19:54:21.000Z","size":1727,"stargazers_count":5,"open_issues_count":16,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2026-03-03T20:09:32.542Z","etag":null,"topics":["field-service","ofsc","oracle-field-service-cloud"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/btoron.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2019-10-23T15:01:44.000Z","updated_at":"2026-01-02T14:29:08.000Z","dependencies_parsed_at":"2023-02-18T08:30:45.657Z","dependency_job_id":"468fcec9-9b4b-4062-9292-98fa1a8cc5d0","html_url":"https://github.com/btoron/pyOFSC","commit_stats":{"total_commits":78,"total_committers":4,"mean_commits":19.5,"dds":"0.11538461538461542","last_synced_commit":"27821638d8a30437178d51be9e3b431f3fecc53d"},"previous_names":[],"tags_count":65,"template":false,"template_full_name":null,"purl":"pkg:github/btoron/pyOFSC","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/btoron%2FpyOFSC","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/btoron%2FpyOFSC/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/btoron%2FpyOFSC/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/btoron%2FpyOFSC/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/btoron","download_url":"https://codeload.github.com/btoron/pyOFSC/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/btoron%2FpyOFSC/sbom","scorecard":{"id":256839,"data":{"date":"2025-08-11","repo":{"name":"github.com/btoron/pyOFSC","commit":"caf8ed5b336aa5d9551413f2d648a0c994d0e99c"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":5.4,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/12 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Security-Policy","score":4,"reason":"security policy file detected","details":["Info: security policy file detected: SECURITY.md:1","Warn: no linked content found","Info: Found disclosure, vulnerability, and/or timelines in security policy: SECURITY.md:1","Info: Found text in security policy: SECURITY.md:1"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Maintained","score":10,"reason":"13 commit(s) and 4 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/poetrypublish.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/poetrypublish.yml:9: update your workflow using https://app.stepsecurity.io/secureworkflow/btoron/pyOFSC/poetrypublish.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/poetrypublish.yml:11: update your workflow using https://app.stepsecurity.io/secureworkflow/btoron/pyOFSC/poetrypublish.yml/master?enable=pin","Info:   0 out of   1 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE.txt:0","Info: FSF or OSI recognized license: MIT License: LICENSE.txt:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":4,"reason":"SAST tool is not run on all commits -- score normalized to 4","details":["Warn: 13 commits out of 28 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-17T09:54:13.730Z","repository_id":35266852,"created_at":"2025-08-17T09:54:13.730Z","updated_at":"2025-08-17T09:54:13.730Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30106120,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-05T01:39:18.192Z","status":"online","status_checked_at":"2026-03-05T02:00:06.710Z","response_time":93,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["field-service","ofsc","oracle-field-service-cloud"],"created_at":"2026-03-05T02:00:57.681Z","updated_at":"2026-03-05T02:00:58.451Z","avatar_url":"https://github.com/btoron.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"## pyOFSC\n\n**Oracle Fusion Field Service** (formerly Oracle Field Service Cloud, formerly ETAdirect) is a cloud-based field service management platform for scheduling, dispatching, and managing mobile workforces.\n\n**pyOFSC** is a Python wrapper for its REST API, providing both synchronous and asynchronous clients with Pydantic model-based validation. See the [official Oracle Fusion Field Service documentation](https://docs.oracle.com/en/cloud/saas/field-service/index.html) for API details.\n\n## Async Client\n\nStarting with version 2.19, pyOFSC includes an async client (`AsyncOFSC`) that provides asynchronous API access using `httpx` and Python's `async`/`await` patterns.\n\n**Implementation Status**: The async client is being implemented progressively. Currently available async methods are marked with `[Sync \u0026 Async]` tags in [docs/ENDPOINTS.md](docs/ENDPOINTS.md).\n\n### Usage Example\n```python\nfrom ofsc.async_client import AsyncOFSC\nasync with AsyncOFSC(clientID=\"...\", secret=\"...\", companyName=\"...\") as client:\n    workzones = await client.metadata.get_workzones()\n```\n\n### Key Features\n- **Async/Await Support**: Full async/await pattern support for non-blocking I/O\n- **Same Models**: Reuses all existing Pydantic models from the sync version\n- **Context Manager**: Must be used as an async context manager to properly manage HTTP client lifecycle\n- **Simplified API**: Async methods always return Pydantic models (no `response_type` parameter)\n- **Request/Response Logging**: Optional httpx event hooks for automatic API call tracing\n\n### Enabling Request/Response Logging\n\nPass `enable_logging=True` to automatically log all HTTP requests and responses via Python's standard logging:\n\n```python\nimport logging\nlogging.basicConfig(level=logging.DEBUG)\n\nasync with AsyncOFSC(clientID=\"...\", secret=\"...\", companyName=\"...\", enable_logging=True) as client:\n    workzones = await client.metadata.get_workzones()\n    # DEBUG: Request: GET https://company.fs.ocs.oraclecloud.com/rest/ofscMetadata/v1/workZones\n    # DEBUG: Response: GET https://company.fs.ocs.oraclecloud.com/rest/ofscMetadata/v1/workZones 200\n```\n\nLogs are emitted under the `ofsc.async_client` logger. HTTP errors (4xx/5xx) are also logged at WARNING level. Disabled by default with zero overhead.\n\n## Models\n\nAll API entities use Pydantic v2 models. See `ofsc/models/` for available models.\n\n## Testing\n\npyOFSC includes a comprehensive test suite with 500+ tests. Tests run in parallel by default using pytest-xdist for 10x faster execution.\n\n### Running Tests\n\n```bash\n# Run all tests (parallel for safe tests, sequential for serial tests)\nuv run pytest\n\n# Run tests with specific number of workers\nuv run pytest -n 4 -m \"not serial\"\n\n# Run all tests sequentially (disable parallel execution)\nuv run pytest -n 0\n\n# Run only serial tests (sequential execution)\nuv run pytest -m serial -n 0\n\n# Run only mocked tests (no API credentials needed)\nuv run pytest -m \"not uses_real_data\"\n\n# Run specific test file\nuv run pytest tests/async/test_async_workzones.py\n```\n\n**Note:** By default, tests marked with `@pytest.mark.serial` are excluded from parallel execution to prevent conflicts when modifying shared API state. To run all tests including serial ones, use: `uv run pytest -m \"\" -n auto \u0026\u0026 uv run pytest -m serial -n 0`\n\n### Test Requirements\n\n- **Mocked tests**: No special requirements, use saved API responses\n- **Live tests** (marked with `@pytest.mark.uses_real_data`): Require API credentials in `.env` file:\n  ```\n  OFSC_CLIENT_ID=your_client_id\n  OFSC_COMPANY=your_company\n  OFSC_CLIENT_SECRET=your_secret\n  ```\n\n### Test Markers\n\n- `@pytest.mark.uses_real_data` - Tests that require API credentials\n- `@pytest.mark.serial` - Tests that must run sequentially (automatically excluded from parallel execution)\n- `@pytest.mark.slow` - Slow-running tests\n- `@pytest.mark.integration` - Integration tests\n\n## Implemented Functions\n\n**195 async endpoints** (80% coverage) and **89 sync endpoints** (37% coverage) across Core, Metadata, Capacity, Statistics, and Auth modules.\n\nSee [docs/ENDPOINTS.md](docs/ENDPOINTS.md) for the full implementation status table.\n\n## Usage Examples\n\n**Sync:**\n```python\nfrom ofsc import OFSC\ninstance = OFSC(clientID=\"...\", secret=\"...\", companyName=\"...\")\nworkzones = instance.metadata.get_workzones()\n```\n\n**Async:**\n```python\nfrom ofsc.async_client import AsyncOFSC\nasync with AsyncOFSC(clientID=\"...\", secret=\"...\", companyName=\"...\") as client:\n    workzones = await client.metadata.get_workzones()\n```\n\nSee the [examples/](examples/) directory for comprehensive sync and async usage examples.\n\n## Test History\n\nOFS REST API Version | PyOFSC\n------------ | -------------\n20C| 1.7\n21A| 1.8, 1.8,1, 1.9\n21D| 1.15\n22B| 1.16, 1.17\n22D| 1.18\n24C| 2.0\n25B| 2.12\n26A| 2.24.0\n\n## Future Deprecation Notice - OFSC 3.0\n\n**Important**: Starting with Oracle Fusion Field Service 3.0, the synchronous client (`OFSC`) will be deprecated in favor of the async client (`AsyncOFSC`).\n\n### Migration Path\n- The async client (`AsyncOFSC`) is the recommended approach for all new development\n- OFSC 3.0 will provide a **compatibility wrapper** to allow existing synchronous code to continue working without modifications\n- The compatibility wrapper will internally use the async client with synchronous adapters\n- We recommend gradually migrating to the async client to take advantage of better performance and scalability\n\n### Timeline\n- **OFSC 2.x**: Both sync and async clients fully supported\n- **OFSC 3.0**: Sync client deprecated, compatibility wrapper provided\n- **OFSC 4.0**: Sync client may be removed (compatibility wrapper will remain for at least one major version)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbtoron%2Fpyofsc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbtoron%2Fpyofsc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbtoron%2Fpyofsc/lists"}