Skip to content

Releases: btoron/pyOFSC

v2.21.0 - Async Metadata API Phase 2

30 Dec 00:19
bcfe49d

Choose a tag to compare

pyOFSC v2.21.0 - Async Metadata API Phase 2

Release Date: December 30, 2025
Highlights: 9 new async API modules, 31 methods, comprehensive type safety improvements


🎯 Major Features

Async Metadata API - Phase 2 Implementation

This release completes Phase 2 of the async metadata API implementation, adding async support for 9 critical OFSC metadata modules.

1. Applications API

  • get_applications() - List all applications
  • get_application(label) - Get application details
  • get_application_api_accesses(label) - List API accesses
  • get_application_api_access(label, accessId) - Get specific API access

2. Capacity Areas API

  • get_capacity_areas() - List all capacity areas
  • get_capacity_area(label) - Get capacity area details

3. Capacity Categories API

  • get_capacity_categories(offset, limit) - List with pagination
  • get_capacity_category(label) - Get category details

4. Forms API

  • get_forms(offset, limit) - List forms with pagination
  • get_form(label) - Get form details

5. Map Layers API

  • get_map_layers(offset, limit) - List map layers with pagination
  • get_map_layer(label) - Get map layer details

6. Plugins API

  • import_plugin_file(file_path) - Import plugin from XML file
  • import_plugin(plugin_xml) - Import plugin from XML string

7. Routing Profiles API (Full CRUD)

  • get_routing_profiles(offset, limit) - List routing profiles
  • get_routing_plans(profile_label, offset, limit) - List plans
  • export_routing_plan(profile_label, plan_label) - Export plan
  • import_routing_plan(profile_label, plan_label, data) - Import plan
  • replace_routing_plan(profile_label, plan_label, data) - Replace plan
  • create_routing_plan(profile_label, plan_label, data) - Create plan
  • delete_routing_plan(profile_label, plan_label) - Delete plan

8. Shifts API

  • get_shifts(offset, limit) - List shifts with pagination
  • get_shift(label) - Get shift details

9. Work Skills API (Full CRUD)

  • get_work_skills(offset, limit) - List work skills
  • get_work_skill(label) - Get work skill details
  • create_or_replace_work_skill(workskill) - Create/update work skill
  • delete_work_skill(label) - Delete work skill
  • get_work_skill_conditions() - List all conditions
  • get_work_skill_groups(offset, limit) - List groups
  • get_work_skill_group(label) - Get group details
  • create_or_replace_work_skill_group(group) - Create/update group
  • delete_work_skill_group(label) - Delete group

🔧 Code Quality Improvements

Type Safety Enhancements

  • Replaced List[] with list[] - 70 occurrences updated for modern Python typing
  • Added pyright to dev dependencies - Static type checking support
  • Fixed all pyright errors - Reduced from 13 errors to 0
  • Added type: ignore annotations - 7 RootModel classes properly annotated

Model Improvements

  • Fixed duplicate Link class - Renamed to DailyExtractLink
  • Made Application fields Optional - Proper type safety
  • Fixed baseUrl property - Correct type annotation
  • Removed invalid __next__() methods - From response list classes
  • Fixed enum type mismatch - In Recurrence model
  • Added None checks - For optional member access and iterables
  • Fixed Property.translations - Changed to Optional[TranslationList]

Documentation

  • PEP 287 docstrings - All async metadata methods converted to reStructuredText format
  • New scripts/README.md - 504 lines documenting utility scripts
  • Updated ENDPOINTS.md - Current implementation status for all 243 endpoints

Code Organization

  • Reorganized models.py - Application and Routing Profile models in alphabetical regions
  • Deleted empty regions - 4 regions removed for cleaner code
  • Consistent naming - Fixed Workskill/WorkskillGroup inconsistencies

🧪 Testing

New Test Coverage

  • 9 new test files with 3,340 lines
  • 100+ test cases covering all new functionality
  • 50+ saved API responses for validation testing
  • All tests passing: 266/266 ✅

Test Structure

  • Live tests with @pytest.mark.uses_real_data
  • Model validation tests
  • Saved response validation tests
  • Error handling tests (404, authentication, etc.)
  • Comprehensive CRUD operation tests

Coverage Metrics

  • Overall: 84% (exceeds 80% target)
  • async_client/metadata.py: 95%
  • models.py: 87%
  • exceptions.py: 100%

🐛 Bug Fixes

Critical Fixes

  1. RoutingPlanData Validation - Made fields optional for varied API responses
  2. Optional Member Access - Added None checks before calling methods
  3. Import Naming - Fixed WorkskillConditionList typo
  4. Type Annotations - Standardized across all models

Minor Fixes

  • Updated capacity area validation test label
  • Updated Status enum usage in CapacityArea and Workzone
  • Corrected endpoint statuses in documentation
  • Removed deprecated routing profiles capture script

📦 New Dependencies

Development

  • pyright>=1.1.390,<2 - Static type checker for Python

📊 Statistics

Metric Count
Issues Resolved 9 (#92, #93, #94, #95, #99, #102, #105, #106, #108)
API Methods Added 31
Models Created/Updated 18
Test Files Created 9
Test Cases Added 100+
Saved Responses 50+
Documentation Lines 1,050+
Net Lines Added +5,253

🔄 Migration Guide

Breaking Changes

None - All changes are backward compatible.

New Features Usage

from ofsc import AsyncOFSC

async with AsyncOFSC(
    clientID="your_client_id",
    companyName="your_company",
    secret="your_secret"
) as client:
    # Applications API
    apps = await client.metadata.get_applications()
    app = await client.metadata.get_application("app_label")
    
    # Routing Profiles API
    profiles = await client.metadata.get_routing_profiles()
    plans = await client.metadata.get_routing_plans("profile_label")
    plan_data = await client.metadata.export_routing_plan(
        "profile_label", "plan_label"
    )
    
    # Work Skills API (CRUD)
    skills = await client.metadata.get_work_skills()
    skill = await client.metadata.get_work_skill("skill_label")
    await client.metadata.create_or_replace_work_skill(workskill)
    await client.metadata.delete_work_skill("skill_label")
    
    # All other new APIs follow the same pattern
    forms = await client.metadata.get_forms()
    shifts = await client.metadata.get_shifts()
    capacity_areas = await client.metadata.get_capacity_areas()

Type Checking Support

# Models now fully support modern Python typing
from ofsc.models import (
    Application,
    RoutingProfileList,
    Workskill,
    Form
)

# Use with mypy or pyright for static type checking
apps: list[Application] = []  # Modern syntax supported

📝 Documentation

New Documentation

  • scripts/README.md - Comprehensive guide for utility scripts
    • capture_api_responses.py - How to capture API responses
    • update_endpoints_doc.py - How to update endpoint documentation
    • Usage examples, best practices, troubleshooting

Updated Documentation

  • ENDPOINTS.md - Current implementation status (89 sync, 53 async endpoints)
  • All async metadata docstrings - Now in PEP 287 reStructuredText format

🚀 What's Next

Phase 3 (Upcoming)

  • Remaining metadata endpoints (see issue #109)
  • Additional CRUD operations
  • Batch operations support

Future Releases

  • Async Core API implementation
  • Async Capacity API implementation
  • OAuth token-based authentication for async client
  • Enhanced error handling and retries
  • Rate limiting support

🙏 Contributors

  • Borja Toron (@btoron) - Primary development
  • Claude Sonnet 4.5 - AI pair programming assistance

📋 Full Changelog

Features

  • feat: implement async routing profiles API methods and add tests (86db72c)
  • feat: implement async methods for capacity areas and add comprehensive tests (3448768)
  • feat: implement async methods for capacity categories and add comprehensive tests (3dc52d1)
  • feat: implement async methods for map layers and add comprehensive tests (aafcf98)
  • feat: implement async methods for forms and add comprehensive tests (503377d)
  • feat: implement async methods for shifts and add comprehensive tests (9671b40)
  • feat: implement async methods for work skills and conditions with comprehensive tests (f87e963)
  • feat: Add async applications and plugins API implementation (5db8cf1)
  • feat: Add comprehensive README for utility scripts (5ead113)
  • feat: add endpoints for work skills in API capture script (52bdbbc)
  • feat: add live and model tests for CRUD operations (a7fd98b)
  • feat: Update RoutingPlanData model for optional fields (f48d935)
  • feat: Refactor metadata models for applications and routing profiles (5383307)
  • feat: Add pyright to development dependencies (b9ad391)
  • feat: update status fields to use Status enum (f2a77d0)

Bug Fixes

  • fix: correct naming inconsistencies for Workskill and WorkskillGroup (7018dfa)
  • fix: Correct typo in import statement for WorkskillConditionList (6e64aaa)
  • fix: Update endpoint statuses in documentation (5557984)
  • test: update expected label for capacity area validation (ff18bed)

Refactoring

  • refactor: Replace List with built-in list type (202049d)
  • refactor: Simplify model classes and update type hints (de8086f)
  • refactor: Docstrings to use reStructuredText (35440fd)
  • feat: remove deprecated routing profiles capture script (e2f569e)

Version Updates

  • chore: Update version to 2.21.0 (01dfffe)

🔗 Links

Read more

Async Client

23 Dec 20:56
d28b50f

Choose a tag to compare

What's Changed

  • 86 add asyncofsc class with httpx async support by @btoron in #89

Full Changelog: v2.18.1...v2.19

v2.18.1

12 Dec 05:14
310e517

Choose a tag to compare

What's Changed

Full Changelog: v2.18...v2.18.1

v2.18

12 Dec 04:51
df5fe35

Choose a tag to compare

What's Changed

  • 83 add replace workzone method to metadata api by @btoron in #84

Full Changelog: v2.17...v2.18

v2.17

28 Oct 13:45
ffece3d

Choose a tag to compare

What's Changed

  • 78 add models and routes for route profiles and plan management by @btoron in #79
  • feat: Add get_resources method by @btoron in #82

Full Changelog: v2.15...v2.17

v2.15

02 Oct 00:56
7fa6cc9

Choose a tag to compare

What's Changed

Full Changelog: v2.14.1...v2.15

v2.14.1

25 Jun 20:52
caf8ed5

Choose a tag to compare

What's Changed

  • Update capacity and model handling: enhance fields type and version b… by @btoron in #72

Full Changelog: v2.14...v2.14.1

v2.14

25 Jun 17:17
44dfa54

Choose a tag to compare

Summary

This release adds comprehensive capacity management functionality to pyOFSC, including:

  • New OFSCapacity module for capacity and quota operations
  • Support for both getAvailableCapacity and getQuota endpoints
  • Flexible parameter handling with CsvList support
  • Generic internal converter function using type inspection

Major Changes

1. New Capacity Module (ofsc/capacity.py)

  • getAvailableCapacity(): Get available capacity with individual parameters
    • Supports list, CSV string, and CsvList inputs for areas, dates, categories
    • Consistent with getQuota signature pattern
  • getQuota(): Get quota information with flexible parameters
    • Boolean parameters automatically converted to lowercase strings
    • All string array parameters support multiple input formats
  • _convert_model_to_api_params(): Internal generic converter using inspection
    • Automatically detects CsvList and boolean fields
    • No hardcoded field names - works with any Pydantic model
    • DRY implementation shared by both public methods

2. Enhanced Models (ofsc/models.py)

  • CsvList: Utility model for comma-separated string lists
    • from_list() and to_list() conversion methods
    • Automatic conversion in field validators
  • CapacityRequest: Updated to use CsvList fields with validators
  • GetQuotaRequest: Request model with comprehensive parameters
  • GetQuotaResponse and QuotaAreaItem: Response models for quota data
  • All models support flexible input formats (list[str], str, CsvList)

3. Module Integration

  • Capacity module integrated as top-level API alongside core and metadata
  • Access via ofsc_instance.capacity.getAvailableCapacity() and ofsc_instance.capacity.getQuota()

4. Comprehensive Test Suite

  • 30+ mocked tests covering all functionality
  • 19+ integration tests for real server validation
  • Real server responses captured for consistent mocking
  • Tests for all input formats and edge cases
  • Performance tests included

API Examples

# Get available capacity
response = ofsc.capacity.getAvailableCapacity(
    dates=["2025-06-25", "2025-06-26"],
    areas=["FLUSA", "CAUSA"],
    categories=["EST", "RES"]
)

# Get quota information  
response = ofsc.capacity.getQuota(
    dates="2025-06-25",
    areas=["FLUSA", "CAUSA"],
    aggregateResults=True,
    categoryLevel=False
)

Breaking Changes

- getAvailableCapacity signature changed from accepting CapacityRequest object to individual parameters
- This aligns with the getQuota pattern for consistency

Testing

- All tests passing (30 mocked, 19 integration)
- Tested with real OFSC server using FLUSA/CAUSA areas
- Performance validated with week-long date ranges

v2.13

25 Jun 14:15
6e065a8

Choose a tag to compare

What's Changed

Full Changelog: v2.12.3...v2.13

v2.12.3

13 May 23:07
625f17f

Choose a tag to compare

What's Changed

  • feat: Add ApplicationsResourcestoAllow model and update Application r… by @btoron in #60

Full Changelog: v2.12.2...v2.12.3