geek-cafe-saas-sdk 0.6.0__tar.gz → 0.7.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of geek-cafe-saas-sdk might be problematic. Click here for more details.
- geek_cafe_saas_sdk-0.7.0/LINEAGE_IMPLEMENTATION_SUMMARY.md +335 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/PKG-INFO +11 -11
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/README.md +10 -10
- geek_cafe_saas_sdk-0.7.0/examples/file_lineage_example.py +240 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/pyproject.toml +1 -1
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/__init__.py +2 -2
- geek_cafe_saas_sdk-0.7.0/src/geek_cafe_saas_sdk/domains/files/handlers/README.md +446 -0
- geek_cafe_saas_sdk-0.7.0/src/geek_cafe_saas_sdk/domains/files/handlers/__init__.py +6 -0
- geek_cafe_saas_sdk-0.7.0/src/geek_cafe_saas_sdk/domains/files/handlers/files/create/app.py +121 -0
- geek_cafe_saas_sdk-0.7.0/src/geek_cafe_saas_sdk/domains/files/handlers/files/download/app.py +80 -0
- geek_cafe_saas_sdk-0.7.0/src/geek_cafe_saas_sdk/domains/files/handlers/files/get/app.py +62 -0
- geek_cafe_saas_sdk-0.7.0/src/geek_cafe_saas_sdk/domains/files/handlers/files/list/app.py +72 -0
- geek_cafe_saas_sdk-0.7.0/src/geek_cafe_saas_sdk/domains/files/handlers/lineage/create_derived/app.py +99 -0
- geek_cafe_saas_sdk-0.7.0/src/geek_cafe_saas_sdk/domains/files/handlers/lineage/create_main/app.py +104 -0
- geek_cafe_saas_sdk-0.7.0/src/geek_cafe_saas_sdk/domains/files/handlers/lineage/download_bundle/app.py +99 -0
- geek_cafe_saas_sdk-0.7.0/src/geek_cafe_saas_sdk/domains/files/handlers/lineage/get_lineage/app.py +68 -0
- geek_cafe_saas_sdk-0.7.0/src/geek_cafe_saas_sdk/domains/files/handlers/lineage/prepare_bundle/app.py +76 -0
- geek_cafe_saas_sdk-0.7.0/src/geek_cafe_saas_sdk/domains/files/models/__init__.py +17 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/files/models/file.py +118 -12
- geek_cafe_saas_sdk-0.7.0/src/geek_cafe_saas_sdk/domains/files/services/__init__.py +21 -0
- geek_cafe_saas_sdk-0.7.0/src/geek_cafe_saas_sdk/domains/files/services/file_lineage_service.py +487 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/files/services/file_system_service.py +27 -1
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/utilities/cognito_utility.py +16 -26
- geek_cafe_saas_sdk-0.6.0/src/geek_cafe_saas_sdk/domains/voting/__init__.py +0 -0
- geek_cafe_saas_sdk-0.6.0/src/geek_cafe_saas_sdk/domains/voting/handlers/__init__.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/.env.mock +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/.gitignore +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/.windsurf/rules/cascade.yaml +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/ARCHITECTURE.md +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/CHANGELOG.md +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/CHANGELOG_0.4.1.md +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/LICENSE +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/README_FILE_SYSTEM_SDK_USAGE.md +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/coverage.json +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/examples/decorator_pattern_handlers.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/examples/factory_authorization_example.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/examples/hierarchical_routing_handler_example.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/examples/lambda_handler_examples.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/examples/lambda_handlers/api_key_example.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/examples/website_analytics_example.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/lambda_handlers/auth/confirm_forgot_password/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/lambda_handlers/auth/forgot_password/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/lambda_handlers/users/change_password/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/lambda_handlers/users/reset_password/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/publish_to_pypi.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/publish_to_pypi.sh +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/pysetup.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/pysetup.sh +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/requirements.dev.txt +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/requirements.txt +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/run_unit_tests.sh +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/core/__init__.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/core/audit_mixin.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/core/error_codes.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/core/service_errors.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/core/service_result.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/decorators/__init__.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/decorators/auth.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/decorators/core.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/__init__.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/analytics/__init__.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/analytics/handlers/__init__.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/analytics/models/__init__.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/analytics/models/website_analytics.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/analytics/models/website_analytics_summary.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/analytics/services/__init__.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/analytics/services/website_analytics_service.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/analytics/services/website_analytics_summary_service.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/analytics/services/website_analytics_tally_service.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/auth/__init__.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/auth/handlers/__init__.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/auth/handlers/users/create/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/auth/handlers/users/delete/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/auth/handlers/users/get/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/auth/handlers/users/list/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/auth/handlers/users/update/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/auth/models/__init__.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/auth/models/permission.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/auth/models/resource_permission.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/auth/models/role.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/auth/models/user.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/auth/services/__init__.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/auth/services/authorization_service.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/auth/services/permission_registry.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/auth/services/resource_permission_service.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/auth/services/user_service.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/communities/__init__.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/communities/handlers/__init__.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/communities/handlers/communities/create/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/communities/handlers/communities/delete/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/communities/handlers/communities/get/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/communities/handlers/communities/list/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/communities/handlers/communities/update/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/communities/models/__init__.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/communities/models/community.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/communities/models/community_member.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/communities/services/__init__.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/communities/services/community_member_service.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/communities/services/community_service.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/events/__init__.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/events/handlers/__init__.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/events/handlers/attendees/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/events/handlers/cancel/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/events/handlers/check_in/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/events/handlers/create/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/events/handlers/delete/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/events/handlers/get/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/events/handlers/invite/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/events/handlers/list/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/events/handlers/publish/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/events/handlers/rsvp/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/events/handlers/update/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/events/models/__init__.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/events/models/event.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/events/models/event_attendee.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/events/services/__init__.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/events/services/event_attendee_service.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/events/services/event_service.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/files/__init__.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/files/models/directory.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/files/models/file_share.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/files/models/file_version.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/files/services/directory_service.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/files/services/file_share_service.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/files/services/file_version_service.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/files/services/s3_file_service.py +0 -0
- {geek_cafe_saas_sdk-0.6.0/src/geek_cafe_saas_sdk/domains/files/models → geek_cafe_saas_sdk-0.7.0/src/geek_cafe_saas_sdk/domains/messaging}/__init__.py +0 -0
- {geek_cafe_saas_sdk-0.6.0/src/geek_cafe_saas_sdk/domains/files/services → geek_cafe_saas_sdk-0.7.0/src/geek_cafe_saas_sdk/domains/messaging/handlers}/__init__.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/messaging/handlers/chat_channels/create/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/messaging/handlers/chat_channels/delete/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/messaging/handlers/chat_channels/get/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/messaging/handlers/chat_channels/list/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/messaging/handlers/chat_channels/update/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/messaging/handlers/chat_messages/create/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/messaging/handlers/chat_messages/delete/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/messaging/handlers/chat_messages/get/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/messaging/handlers/chat_messages/list/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/messaging/handlers/chat_messages/update/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/messaging/handlers/contact_threads/create/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/messaging/handlers/contact_threads/delete/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/messaging/handlers/contact_threads/get/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/messaging/handlers/contact_threads/list/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/messaging/handlers/contact_threads/update/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/messaging/models/__init__.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/messaging/models/chat_channel.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/messaging/models/chat_channel_member.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/messaging/models/chat_message.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/messaging/models/contact_thread.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/messaging/services/__init__.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/messaging/services/chat_channel_service.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/messaging/services/chat_message_service.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/messaging/services/contact_thread_service.py +0 -0
- {geek_cafe_saas_sdk-0.6.0/src/geek_cafe_saas_sdk/domains/messaging → geek_cafe_saas_sdk-0.7.0/src/geek_cafe_saas_sdk/domains/tenancy}/__init__.py +0 -0
- {geek_cafe_saas_sdk-0.6.0/src/geek_cafe_saas_sdk/domains/messaging → geek_cafe_saas_sdk-0.7.0/src/geek_cafe_saas_sdk/domains/tenancy}/handlers/__init__.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/tenancy/handlers/subscriptions/activate/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/tenancy/handlers/subscriptions/active/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/tenancy/handlers/subscriptions/cancel/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/tenancy/handlers/subscriptions/get/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/tenancy/handlers/subscriptions/list/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/tenancy/handlers/subscriptions/record_payment/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/tenancy/handlers/tenants/get/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/tenancy/handlers/tenants/me/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/tenancy/handlers/tenants/signup/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/tenancy/handlers/tenants/update/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/tenancy/models/__init__.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/tenancy/models/subscription.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/tenancy/models/tenant.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/tenancy/services/__init__.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/tenancy/services/subscription_service.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/tenancy/services/tenant_service.py +0 -0
- {geek_cafe_saas_sdk-0.6.0/src/geek_cafe_saas_sdk/domains/tenancy → geek_cafe_saas_sdk-0.7.0/src/geek_cafe_saas_sdk/domains/voting}/__init__.py +0 -0
- {geek_cafe_saas_sdk-0.6.0/src/geek_cafe_saas_sdk/domains/tenancy → geek_cafe_saas_sdk-0.7.0/src/geek_cafe_saas_sdk/domains/voting}/handlers/__init__.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/voting/handlers/votes/create/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/voting/handlers/votes/delete/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/voting/handlers/votes/get/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/voting/handlers/votes/list/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/voting/handlers/votes/summerize/README.md +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/voting/handlers/votes/update/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/voting/models/__init__.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/voting/models/vote.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/voting/models/vote_summary.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/voting/services/__init__.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/voting/services/vote_service.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/voting/services/vote_summary_service.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/domains/voting/services/vote_tally_service.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/lambda_handlers/README.md +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/lambda_handlers/__init__.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/lambda_handlers/_base/__init__.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/lambda_handlers/_base/api_key_handler.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/lambda_handlers/_base/authorized_secure_handler.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/lambda_handlers/_base/base_handler.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/lambda_handlers/_base/handler_factory.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/lambda_handlers/_base/public_handler.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/lambda_handlers/_base/secure_handler.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/lambda_handlers/_base/service_pool.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/lambda_handlers/directories/create/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/lambda_handlers/directories/delete/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/lambda_handlers/directories/get/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/lambda_handlers/directories/list/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/lambda_handlers/directories/move/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/lambda_handlers/files/delete/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/lambda_handlers/files/download/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/lambda_handlers/files/get/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/lambda_handlers/files/list/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/lambda_handlers/files/share/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/lambda_handlers/files/shares/list/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/lambda_handlers/files/shares/revoke/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/lambda_handlers/files/update/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/lambda_handlers/files/upload/app.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/middleware/__init__.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/middleware/auth.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/middleware/authorization.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/middleware/cors.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/middleware/error_handling.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/middleware/validation.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/models/__init__.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/models/base_model.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/services/__init__.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/services/database_service.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/utilities/__init__.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/utilities/custom_exceptions.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/utilities/datetime_utility.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/utilities/dictionary_utility.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/utilities/dynamodb_utils.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/utilities/environment_loader.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/utilities/environment_variables.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/utilities/http_body_parameters.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/utilities/http_path_parameters.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/utilities/http_status_code.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/utilities/jwt_utility.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/utilities/lambda_event_utility.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/utilities/logging_utility.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/utilities/message_query_helper.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/utilities/response.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/src/geek_cafe_saas_sdk/utilities/string_functions.py +0 -0
- {geek_cafe_saas_sdk-0.6.0 → geek_cafe_saas_sdk-0.7.0}/update_readme_badges.py +0 -0
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
# File Lineage Implementation Summary
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
File lineage tracking has been successfully implemented in the Geek Cafe SaaS SDK. This feature allows tracking of file transformations through data processing pipelines.
|
|
6
|
+
|
|
7
|
+
**Implementation Date:** October 2025
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## What Was Added
|
|
12
|
+
|
|
13
|
+
### 1. File Model Extensions
|
|
14
|
+
|
|
15
|
+
**File:** `src/geek_cafe_saas_sdk/domains/files/models/file.py`
|
|
16
|
+
|
|
17
|
+
**New Fields:**
|
|
18
|
+
- `file_role`: str - Role in lineage chain ("standalone", "original", "main", "derived")
|
|
19
|
+
- `original_file_id`: str | None - Root file in lineage chain
|
|
20
|
+
- `parent_file_id`: str | None - Immediate parent file
|
|
21
|
+
- `transformation_type`: str | None - Type of transformation ("convert", "clean", "process")
|
|
22
|
+
- `transformation_operation`: str | None - Specific operation name
|
|
23
|
+
- `transformation_metadata`: dict | None - Additional operation details
|
|
24
|
+
- `derived_file_count`: int - Number of files derived from this one
|
|
25
|
+
|
|
26
|
+
**New Properties:**
|
|
27
|
+
- All fields have getter/setter properties with validation
|
|
28
|
+
|
|
29
|
+
**New Helper Methods:**
|
|
30
|
+
- `has_lineage()` - Check if file participates in lineage
|
|
31
|
+
- `is_original()` - Check if this is an original file
|
|
32
|
+
- `is_main()` - Check if this is a main file
|
|
33
|
+
- `is_derived()` - Check if this is a derived file
|
|
34
|
+
- `is_standalone()` - Check if this is a standalone file (no lineage)
|
|
35
|
+
- `increment_derived_count()` - Increment derived file counter
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
### 2. FileLineageService
|
|
40
|
+
|
|
41
|
+
**File:** `src/geek_cafe_saas_sdk/domains/files/services/file_lineage_service.py`
|
|
42
|
+
|
|
43
|
+
**Purpose:** Helper service for managing file lineage and transformations.
|
|
44
|
+
|
|
45
|
+
**Methods:**
|
|
46
|
+
|
|
47
|
+
#### `create_main_file()`
|
|
48
|
+
Create a main file from an original file (e.g., XLS → CSV conversion).
|
|
49
|
+
|
|
50
|
+
**Parameters:**
|
|
51
|
+
- `tenant_id`, `user_id`, `original_file_id`
|
|
52
|
+
- `file_name`, `file_data`, `mime_type`
|
|
53
|
+
- `transformation_operation`, `transformation_metadata`
|
|
54
|
+
- `directory_id` (optional)
|
|
55
|
+
|
|
56
|
+
**Returns:** ServiceResult with main File
|
|
57
|
+
|
|
58
|
+
#### `create_derived_file()`
|
|
59
|
+
Create a derived file from a main file (e.g., data cleaning).
|
|
60
|
+
|
|
61
|
+
**Parameters:**
|
|
62
|
+
- `tenant_id`, `user_id`, `main_file_id`
|
|
63
|
+
- `file_name`, `file_data`
|
|
64
|
+
- `transformation_operation`, `transformation_metadata`
|
|
65
|
+
- `directory_id` (optional)
|
|
66
|
+
|
|
67
|
+
**Returns:** ServiceResult with derived File
|
|
68
|
+
|
|
69
|
+
**Note:** Derived files are ALWAYS created from main files (non-chained).
|
|
70
|
+
|
|
71
|
+
#### `get_lineage()`
|
|
72
|
+
Get complete lineage for a file.
|
|
73
|
+
|
|
74
|
+
**Returns:** Dictionary with:
|
|
75
|
+
- `selected`: The selected file
|
|
76
|
+
- `main`: Main file (if exists)
|
|
77
|
+
- `original`: Original file (if exists)
|
|
78
|
+
- `all_derived`: List of all derived files (if viewing main)
|
|
79
|
+
|
|
80
|
+
#### `list_derived_files()`
|
|
81
|
+
List all files derived from a main file.
|
|
82
|
+
|
|
83
|
+
**Returns:** ServiceResult with list of derived Files
|
|
84
|
+
|
|
85
|
+
#### `prepare_lineage_bundle()`
|
|
86
|
+
Prepare bundle of files for lineage (selected, main, original).
|
|
87
|
+
|
|
88
|
+
**Returns:** Dictionary with files and transformation chain metadata
|
|
89
|
+
|
|
90
|
+
#### `download_lineage_bundle()`
|
|
91
|
+
Download all files in lineage chain with their data.
|
|
92
|
+
|
|
93
|
+
**Returns:** Dictionary with file objects and binary data
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
### 3. FileSystemService Updates
|
|
98
|
+
|
|
99
|
+
**File:** `src/geek_cafe_saas_sdk/domains/files/services/file_system_service.py`
|
|
100
|
+
|
|
101
|
+
**Changes to `create()` method:**
|
|
102
|
+
|
|
103
|
+
Added optional lineage parameters:
|
|
104
|
+
- `file_role`
|
|
105
|
+
- `parent_file_id`
|
|
106
|
+
- `original_file_id`
|
|
107
|
+
- `transformation_type`
|
|
108
|
+
- `transformation_operation`
|
|
109
|
+
- `transformation_metadata`
|
|
110
|
+
|
|
111
|
+
These parameters are set on the File model when provided.
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
### 4. Service Exports
|
|
116
|
+
|
|
117
|
+
**File:** `src/geek_cafe_saas_sdk/domains/files/services/__init__.py`
|
|
118
|
+
|
|
119
|
+
Added export for `FileLineageService` along with existing services:
|
|
120
|
+
- FileSystemService
|
|
121
|
+
- DirectoryService
|
|
122
|
+
- FileVersionService
|
|
123
|
+
- FileShareService
|
|
124
|
+
- S3FileService
|
|
125
|
+
- **FileLineageService** (NEW)
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
### 5. Model Exports
|
|
130
|
+
|
|
131
|
+
**File:** `src/geek_cafe_saas_sdk/domains/files/models/__init__.py`
|
|
132
|
+
|
|
133
|
+
Added exports for all file models:
|
|
134
|
+
- File
|
|
135
|
+
- Directory
|
|
136
|
+
- FileVersion
|
|
137
|
+
- FileShare
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
### 6. Example Code
|
|
142
|
+
|
|
143
|
+
**File:** `examples/file_lineage_example.py`
|
|
144
|
+
|
|
145
|
+
Complete working example demonstrating:
|
|
146
|
+
1. Upload original file
|
|
147
|
+
2. Convert to main file
|
|
148
|
+
3. Create derived files (data cleaning)
|
|
149
|
+
4. Query lineage
|
|
150
|
+
5. Prepare lineage bundle
|
|
151
|
+
6. Download complete bundle
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## Usage Example
|
|
156
|
+
|
|
157
|
+
```python
|
|
158
|
+
from geek_cafe_saas_sdk.domains.files.services import (
|
|
159
|
+
FileSystemService,
|
|
160
|
+
S3FileService,
|
|
161
|
+
FileLineageService
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
# Initialize services
|
|
165
|
+
file_service = FileSystemService(...)
|
|
166
|
+
lineage_service = FileLineageService(
|
|
167
|
+
file_service=file_service,
|
|
168
|
+
s3_service=s3_service
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
# 1. Upload original file
|
|
172
|
+
original = file_service.create(
|
|
173
|
+
tenant_id="tenant-123",
|
|
174
|
+
user_id="user-456",
|
|
175
|
+
file_name="data.xls",
|
|
176
|
+
file_data=xls_bytes,
|
|
177
|
+
mime_type="application/vnd.ms-excel",
|
|
178
|
+
file_role="original" # Mark as original
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
# 2. Convert to main file
|
|
182
|
+
main = lineage_service.create_main_file(
|
|
183
|
+
tenant_id="tenant-123",
|
|
184
|
+
user_id="user-456",
|
|
185
|
+
original_file_id=original.data.file_id,
|
|
186
|
+
file_name="data.csv",
|
|
187
|
+
file_data=csv_bytes,
|
|
188
|
+
mime_type="text/csv",
|
|
189
|
+
transformation_operation="xls_to_csv"
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
# 3. Create derived files (cleaning)
|
|
193
|
+
for version in range(1, 55):
|
|
194
|
+
cleaned = lineage_service.create_derived_file(
|
|
195
|
+
tenant_id="tenant-123",
|
|
196
|
+
user_id="user-456",
|
|
197
|
+
main_file_id=main.data.file_id,
|
|
198
|
+
file_name=f"data_clean_v{version}.csv",
|
|
199
|
+
file_data=cleaned_bytes,
|
|
200
|
+
transformation_operation=f"data_cleaning_v{version}"
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
# 4. Get lineage for lineage
|
|
204
|
+
lineage = lineage_service.get_lineage(
|
|
205
|
+
file_id="cleaned_v54_id",
|
|
206
|
+
tenant_id="tenant-123",
|
|
207
|
+
user_id="user-456"
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
# 5. Prepare bundle (selected, main, original)
|
|
211
|
+
bundle = lineage_service.prepare_lineage_bundle(
|
|
212
|
+
selected_file_id="cleaned_v54_id",
|
|
213
|
+
tenant_id="tenant-123",
|
|
214
|
+
user_id="user-456"
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
# Use bundle.data['selected_file'], bundle.data['main_file'], etc.
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## Key Features
|
|
223
|
+
|
|
224
|
+
### ✅ Non-Chained Transformations
|
|
225
|
+
Derived files are ALWAYS created from the main file, never from other derived files. This matches your exact use case.
|
|
226
|
+
|
|
227
|
+
### ✅ Seamless Integration
|
|
228
|
+
Files with and without lineage work together. Lineage is optional.
|
|
229
|
+
|
|
230
|
+
### ✅ Backward Compatible
|
|
231
|
+
Existing files automatically have `file_role="standalone"`. No migration needed.
|
|
232
|
+
|
|
233
|
+
### ✅ Included in Queries
|
|
234
|
+
When listing files, lineage information is automatically present on each file object.
|
|
235
|
+
|
|
236
|
+
### ✅ Complete Audit Trail
|
|
237
|
+
Track every transformation with operation names and metadata.
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## Architecture
|
|
242
|
+
|
|
243
|
+
```
|
|
244
|
+
Original File (data.xls)
|
|
245
|
+
↓ convert
|
|
246
|
+
Main File (data.csv)
|
|
247
|
+
↓ clean (not chained)
|
|
248
|
+
├── Derived v1
|
|
249
|
+
├── Derived v2
|
|
250
|
+
├── Derived v3
|
|
251
|
+
└── Derived v54
|
|
252
|
+
|
|
253
|
+
User selects v54 → System bundles: v54 + main + original
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
## Files Modified/Created
|
|
259
|
+
|
|
260
|
+
### Modified:
|
|
261
|
+
1. `src/geek_cafe_saas_sdk/domains/files/models/file.py` - Added lineage fields
|
|
262
|
+
2. `src/geek_cafe_saas_sdk/domains/files/services/file_system_service.py` - Added lineage parameters
|
|
263
|
+
3. `src/geek_cafe_saas_sdk/domains/files/services/__init__.py` - Added exports
|
|
264
|
+
4. `src/geek_cafe_saas_sdk/domains/files/models/__init__.py` - Added exports
|
|
265
|
+
|
|
266
|
+
### Created:
|
|
267
|
+
1. `src/geek_cafe_saas_sdk/domains/files/services/file_lineage_service.py` - New service
|
|
268
|
+
2. `examples/file_lineage_example.py` - Usage example
|
|
269
|
+
3. `docs/help/file-system/07-file-lineage.md` - User guide
|
|
270
|
+
4. `docs/help/file-system/08-lineage-implementation.md` - Implementation guide
|
|
271
|
+
5. `LINEAGE_IMPLEMENTATION_SUMMARY.md` - This file
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## Documentation
|
|
276
|
+
|
|
277
|
+
Complete documentation added to `docs/help/file-system/`:
|
|
278
|
+
|
|
279
|
+
1. **07-file-lineage.md** - User guide for file lineage
|
|
280
|
+
- Concepts and use cases
|
|
281
|
+
- Creating lineage chains
|
|
282
|
+
- Querying lineage
|
|
283
|
+
- Bundling for lineage
|
|
284
|
+
- UI integration examples
|
|
285
|
+
|
|
286
|
+
2. **08-lineage-implementation.md** - Implementation guide
|
|
287
|
+
- Architecture decision
|
|
288
|
+
- Complete code for File model extensions
|
|
289
|
+
- Complete FileLineageService implementation
|
|
290
|
+
- Usage examples
|
|
291
|
+
- Migration guide
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
## Testing Recommendations
|
|
296
|
+
|
|
297
|
+
1. **Unit Tests** - Test FileLineageService methods
|
|
298
|
+
- `create_main_file()` with valid/invalid original files
|
|
299
|
+
- `create_derived_file()` with valid/invalid main files
|
|
300
|
+
- `get_lineage()` with various file roles
|
|
301
|
+
- `list_derived_files()` with multiple versions
|
|
302
|
+
|
|
303
|
+
2. **Integration Tests** - Test full pipeline
|
|
304
|
+
- Upload → Convert → Clean → Bundle
|
|
305
|
+
- Verify lineage relationships
|
|
306
|
+
- Verify bundle contents
|
|
307
|
+
|
|
308
|
+
3. **Edge Cases**
|
|
309
|
+
- Creating main from non-original file (should fail)
|
|
310
|
+
- Creating derived from non-main file (should fail)
|
|
311
|
+
- Getting lineage for standalone file
|
|
312
|
+
- Getting lineage for file with missing parent/original
|
|
313
|
+
|
|
314
|
+
---
|
|
315
|
+
|
|
316
|
+
## Next Steps
|
|
317
|
+
|
|
318
|
+
1. **Run Tests** - Ensure all tests pass with new fields
|
|
319
|
+
2. **Update Database** - No migration needed (fields have defaults)
|
|
320
|
+
3. **Deploy** - Deploy updated code to your environment
|
|
321
|
+
4. **Monitor** - Monitor file creation with lineage fields
|
|
322
|
+
5. **Document Internal** - Add to your internal docs/wikis
|
|
323
|
+
|
|
324
|
+
---
|
|
325
|
+
|
|
326
|
+
## Support
|
|
327
|
+
|
|
328
|
+
For questions or issues:
|
|
329
|
+
- Review `docs/help/file-system/07-file-lineage.md`
|
|
330
|
+
- Check `examples/file_lineage_example.py`
|
|
331
|
+
- See `docs/help/file-system/08-lineage-implementation.md`
|
|
332
|
+
|
|
333
|
+
---
|
|
334
|
+
|
|
335
|
+
**Implementation Status:** ✅ Complete and Ready for Testing
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: geek_cafe_saas_sdk
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
4
4
|
Summary: Base Reusable Services for SaaS
|
|
5
5
|
Project-URL: Homepage, https://github.com/geekcafe/geek-cafe-services
|
|
6
6
|
Project-URL: Documentation, https://github.com/geekcafe/geek-cafe-services/blob/main/README.md
|
|
@@ -87,20 +87,20 @@ Description-Content-Type: text/markdown
|
|
|
87
87
|
<!-- COVERAGE-BADGE:START -->
|
|
88
88
|
## Test Coverage
|
|
89
89
|
|
|
90
|
-

|
|
91
|
+

|
|
92
92
|
|
|
93
|
-
**Overall Coverage:**
|
|
93
|
+
**Overall Coverage:** 83.1% (9646/11611 statements)
|
|
94
94
|
|
|
95
95
|
### Coverage Summary
|
|
96
96
|
|
|
97
97
|
| Metric | Value |
|
|
98
98
|
|--------|-------|
|
|
99
|
-
| Total Statements | 11,
|
|
100
|
-
| Covered Statements | 9,
|
|
101
|
-
| Missing Statements | 1,
|
|
102
|
-
| Coverage Percentage |
|
|
103
|
-
| Total Tests |
|
|
99
|
+
| Total Statements | 11,611 |
|
|
100
|
+
| Covered Statements | 9,646 |
|
|
101
|
+
| Missing Statements | 1,965 |
|
|
102
|
+
| Coverage Percentage | 83.1% |
|
|
103
|
+
| Total Tests | 1145 |
|
|
104
104
|
| Test Status | ✅ All Passing |
|
|
105
105
|
|
|
106
106
|
### Files Needing Attention (< 80% coverage)
|
|
@@ -118,7 +118,7 @@ Description-Content-Type: text/markdown
|
|
|
118
118
|
| 63.4% | 86 | `domains/communities/services/community_service.py` |
|
|
119
119
|
| 64.0% | 41 | `domains/files/services/s3_file_service.py` |
|
|
120
120
|
|
|
121
|
-
*... and
|
|
121
|
+
*... and 22 more files with < 80% coverage*
|
|
122
122
|
|
|
123
123
|
### Running Tests
|
|
124
124
|
|
|
@@ -130,7 +130,7 @@ Description-Content-Type: text/markdown
|
|
|
130
130
|
open reports/coverage/index.html
|
|
131
131
|
```
|
|
132
132
|
|
|
133
|
-
*Last updated: 2025-10-
|
|
133
|
+
*Last updated: 2025-10-16 13:22:11*
|
|
134
134
|
|
|
135
135
|
---
|
|
136
136
|
|
|
@@ -12,20 +12,20 @@
|
|
|
12
12
|
<!-- COVERAGE-BADGE:START -->
|
|
13
13
|
## Test Coverage
|
|
14
14
|
|
|
15
|
-

|
|
16
|
+

|
|
17
17
|
|
|
18
|
-
**Overall Coverage:**
|
|
18
|
+
**Overall Coverage:** 83.1% (9646/11611 statements)
|
|
19
19
|
|
|
20
20
|
### Coverage Summary
|
|
21
21
|
|
|
22
22
|
| Metric | Value |
|
|
23
23
|
|--------|-------|
|
|
24
|
-
| Total Statements | 11,
|
|
25
|
-
| Covered Statements | 9,
|
|
26
|
-
| Missing Statements | 1,
|
|
27
|
-
| Coverage Percentage |
|
|
28
|
-
| Total Tests |
|
|
24
|
+
| Total Statements | 11,611 |
|
|
25
|
+
| Covered Statements | 9,646 |
|
|
26
|
+
| Missing Statements | 1,965 |
|
|
27
|
+
| Coverage Percentage | 83.1% |
|
|
28
|
+
| Total Tests | 1145 |
|
|
29
29
|
| Test Status | ✅ All Passing |
|
|
30
30
|
|
|
31
31
|
### Files Needing Attention (< 80% coverage)
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
| 63.4% | 86 | `domains/communities/services/community_service.py` |
|
|
44
44
|
| 64.0% | 41 | `domains/files/services/s3_file_service.py` |
|
|
45
45
|
|
|
46
|
-
*... and
|
|
46
|
+
*... and 22 more files with < 80% coverage*
|
|
47
47
|
|
|
48
48
|
### Running Tests
|
|
49
49
|
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
open reports/coverage/index.html
|
|
56
56
|
```
|
|
57
57
|
|
|
58
|
-
*Last updated: 2025-10-
|
|
58
|
+
*Last updated: 2025-10-16 13:22:11*
|
|
59
59
|
|
|
60
60
|
---
|
|
61
61
|
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Example: Using File Lineage System
|
|
3
|
+
|
|
4
|
+
This example demonstrates how to track file transformations through
|
|
5
|
+
a data processing pipeline.
|
|
6
|
+
|
|
7
|
+
Geek Cafe, LLC
|
|
8
|
+
MIT License. See Project Root for the license information.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from boto3_assist.dynamodb.dynamodb import DynamoDB
|
|
12
|
+
from boto3_assist.s3.s3_connection import S3Connection
|
|
13
|
+
from boto3_assist.s3.s3_object import S3Object
|
|
14
|
+
from boto3_assist.s3.s3_bucket import S3Bucket
|
|
15
|
+
|
|
16
|
+
from geek_cafe_saas_sdk.domains.files.services import (
|
|
17
|
+
FileSystemService,
|
|
18
|
+
S3FileService,
|
|
19
|
+
FileLineageService
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def setup_services():
|
|
24
|
+
"""Initialize file system services."""
|
|
25
|
+
db = DynamoDB()
|
|
26
|
+
connection = S3Connection()
|
|
27
|
+
|
|
28
|
+
s3_service = S3FileService(
|
|
29
|
+
s3_object=S3Object(connection=connection),
|
|
30
|
+
s3_bucket=S3Bucket(connection=connection),
|
|
31
|
+
default_bucket="my-files-bucket"
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
file_service = FileSystemService(
|
|
35
|
+
dynamodb=db,
|
|
36
|
+
table_name="files-table",
|
|
37
|
+
s3_service=s3_service,
|
|
38
|
+
default_bucket="my-files-bucket"
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
lineage_service = FileLineageService(
|
|
42
|
+
file_service=file_service,
|
|
43
|
+
s3_service=s3_service
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
return file_service, lineage_service
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def example_data_pipeline():
|
|
50
|
+
"""
|
|
51
|
+
Example: Data processing pipeline with lineage tracking.
|
|
52
|
+
|
|
53
|
+
Flow:
|
|
54
|
+
1. User uploads original file (measurements.xls)
|
|
55
|
+
2. System converts to main file (measurements.csv)
|
|
56
|
+
3. Data cleaning produces derived files (v1, v2, v3...)
|
|
57
|
+
4. User selects derived file for lineage
|
|
58
|
+
5. System bundles selected + main + original
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
file_service, lineage_service = setup_services()
|
|
62
|
+
|
|
63
|
+
tenant_id = "tenant-123"
|
|
64
|
+
user_id = "user-456"
|
|
65
|
+
|
|
66
|
+
# Step 1: Upload original file
|
|
67
|
+
print("Step 1: Uploading original file...")
|
|
68
|
+
with open("measurements.xls", "rb") as f:
|
|
69
|
+
xls_data = f.read()
|
|
70
|
+
|
|
71
|
+
original_result = file_service.create(
|
|
72
|
+
tenant_id=tenant_id,
|
|
73
|
+
user_id=user_id,
|
|
74
|
+
file_name="measurements.xls",
|
|
75
|
+
file_data=xls_data,
|
|
76
|
+
mime_type="application/vnd.ms-excel",
|
|
77
|
+
file_role="original" # Mark as original
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
if not original_result.success:
|
|
81
|
+
print(f"Error: {original_result.message}")
|
|
82
|
+
return
|
|
83
|
+
|
|
84
|
+
original_file = original_result.data
|
|
85
|
+
print(f"✓ Original file uploaded: {original_file.file_id}")
|
|
86
|
+
|
|
87
|
+
# Step 2: Convert to main file (XLS → CSV)
|
|
88
|
+
print("\nStep 2: Converting to CSV...")
|
|
89
|
+
|
|
90
|
+
# Simulate conversion (replace with actual conversion logic)
|
|
91
|
+
csv_data = convert_xls_to_csv(xls_data)
|
|
92
|
+
|
|
93
|
+
main_result = lineage_service.create_main_file(
|
|
94
|
+
tenant_id=tenant_id,
|
|
95
|
+
user_id=user_id,
|
|
96
|
+
original_file_id=original_file.file_id,
|
|
97
|
+
file_name="measurements.csv",
|
|
98
|
+
file_data=csv_data,
|
|
99
|
+
mime_type="text/csv",
|
|
100
|
+
transformation_operation="xls_to_csv",
|
|
101
|
+
transformation_metadata={
|
|
102
|
+
'converter_version': '1.0',
|
|
103
|
+
'source_format': 'xls',
|
|
104
|
+
'target_format': 'csv'
|
|
105
|
+
}
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
if not main_result.success:
|
|
109
|
+
print(f"Error: {main_result.message}")
|
|
110
|
+
return
|
|
111
|
+
|
|
112
|
+
main_file = main_result.data
|
|
113
|
+
print(f"✓ Main file created: {main_file.file_id}")
|
|
114
|
+
print(f" Role: {main_file.file_role}")
|
|
115
|
+
print(f" Operation: {main_file.transformation_operation}")
|
|
116
|
+
|
|
117
|
+
# Step 3: Create derived files (data cleaning)
|
|
118
|
+
print("\nStep 3: Creating cleaned versions...")
|
|
119
|
+
|
|
120
|
+
derived_files = []
|
|
121
|
+
for version in range(1, 4):
|
|
122
|
+
# Simulate data cleaning
|
|
123
|
+
cleaned_data = perform_data_cleaning(csv_data, version)
|
|
124
|
+
|
|
125
|
+
derived_result = lineage_service.create_derived_file(
|
|
126
|
+
tenant_id=tenant_id,
|
|
127
|
+
user_id=user_id,
|
|
128
|
+
main_file_id=main_file.file_id,
|
|
129
|
+
file_name=f"measurements_clean_v{version}.csv",
|
|
130
|
+
file_data=cleaned_data,
|
|
131
|
+
transformation_operation=f"data_cleaning_v{version}",
|
|
132
|
+
transformation_metadata={
|
|
133
|
+
'cleaning_version': version,
|
|
134
|
+
'operations': ['remove_nulls', 'normalize_units'],
|
|
135
|
+
'rows_processed': 1000
|
|
136
|
+
}
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
if derived_result.success:
|
|
140
|
+
derived_file = derived_result.data
|
|
141
|
+
derived_files.append(derived_file)
|
|
142
|
+
print(f"✓ Derived v{version} created: {derived_file.file_id}")
|
|
143
|
+
|
|
144
|
+
# Step 4: Get lineage for a derived file
|
|
145
|
+
print("\nStep 4: Getting lineage for derived v2...")
|
|
146
|
+
|
|
147
|
+
selected_file_id = derived_files[1].file_id # v2
|
|
148
|
+
lineage_result = lineage_service.get_lineage(
|
|
149
|
+
file_id=selected_file_id,
|
|
150
|
+
tenant_id=tenant_id,
|
|
151
|
+
user_id=user_id
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
if lineage_result.success:
|
|
155
|
+
lineage = lineage_result.data
|
|
156
|
+
print(f"Selected: {lineage['selected'].file_name}")
|
|
157
|
+
print(f"Main: {lineage['main'].file_name}")
|
|
158
|
+
print(f"Original: {lineage['original'].file_name}")
|
|
159
|
+
print(f"All derived versions: {len(lineage['all_derived'])}")
|
|
160
|
+
|
|
161
|
+
# Step 5: Prepare lineage bundle
|
|
162
|
+
print("\nStep 5: Preparing lineage bundle...")
|
|
163
|
+
|
|
164
|
+
bundle_result = lineage_service.prepare_lineage_bundle(
|
|
165
|
+
selected_file_id=selected_file_id,
|
|
166
|
+
tenant_id=tenant_id,
|
|
167
|
+
user_id=user_id
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
if bundle_result.success:
|
|
171
|
+
bundle = bundle_result.data
|
|
172
|
+
print("Bundle contents:")
|
|
173
|
+
print(f" - Selected: {bundle['selected_file'].file_name}")
|
|
174
|
+
print(f" - Main: {bundle['main_file'].file_name}")
|
|
175
|
+
print(f" - Original: {bundle['original_file'].file_name}")
|
|
176
|
+
print(f"\nTransformation chain:")
|
|
177
|
+
for step in bundle['metadata']['transformation_chain']:
|
|
178
|
+
print(f" {step['step']}. {step['type']}: {step['file_name']}")
|
|
179
|
+
if 'operation' in step:
|
|
180
|
+
print(f" Operation: {step['operation']}")
|
|
181
|
+
|
|
182
|
+
# Step 6: Download complete bundle
|
|
183
|
+
print("\nStep 6: Downloading complete bundle...")
|
|
184
|
+
|
|
185
|
+
download_result = lineage_service.download_lineage_bundle(
|
|
186
|
+
selected_file_id=selected_file_id,
|
|
187
|
+
tenant_id=tenant_id,
|
|
188
|
+
user_id=user_id
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
if download_result.success:
|
|
192
|
+
download_bundle = download_result.data
|
|
193
|
+
|
|
194
|
+
# Save each file
|
|
195
|
+
if download_bundle['original']:
|
|
196
|
+
save_file('output/original/', download_bundle['original'])
|
|
197
|
+
|
|
198
|
+
if download_bundle['main']:
|
|
199
|
+
save_file('output/main/', download_bundle['main'])
|
|
200
|
+
|
|
201
|
+
if download_bundle['selected']:
|
|
202
|
+
save_file('output/processed/', download_bundle['selected'])
|
|
203
|
+
|
|
204
|
+
print("✓ Bundle downloaded successfully!")
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def convert_xls_to_csv(xls_data: bytes) -> bytes:
|
|
208
|
+
"""Simulate XLS to CSV conversion."""
|
|
209
|
+
# In production, use a library like openpyxl or pandas
|
|
210
|
+
# For example:
|
|
211
|
+
# import pandas as pd
|
|
212
|
+
# df = pd.read_excel(io.BytesIO(xls_data))
|
|
213
|
+
# return df.to_csv().encode('utf-8')
|
|
214
|
+
|
|
215
|
+
return b"mock,csv,data\n1,2,3\n4,5,6"
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def perform_data_cleaning(csv_data: bytes, version: int) -> bytes:
|
|
219
|
+
"""Simulate data cleaning."""
|
|
220
|
+
# In production, implement actual cleaning logic
|
|
221
|
+
# For example: remove nulls, normalize units, etc.
|
|
222
|
+
|
|
223
|
+
return csv_data + f"\n# Cleaned v{version}".encode('utf-8')
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def save_file(directory: str, file_bundle: dict):
|
|
227
|
+
"""Save file to disk."""
|
|
228
|
+
import os
|
|
229
|
+
|
|
230
|
+
os.makedirs(directory, exist_ok=True)
|
|
231
|
+
|
|
232
|
+
file_path = os.path.join(directory, file_bundle['file'].file_name)
|
|
233
|
+
with open(file_path, 'wb') as f:
|
|
234
|
+
f.write(file_bundle['data'])
|
|
235
|
+
|
|
236
|
+
print(f" Saved: {file_path}")
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
if __name__ == "__main__":
|
|
240
|
+
example_data_pipeline()
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Geek Cafe Services - Base Reusable Services for SaaS
|
|
3
3
|
|
|
4
|
-
Version 0.
|
|
4
|
+
Version 0.6.0 adds File System Service
|
|
5
5
|
"""
|
|
6
|
-
__version__ = "0.
|
|
6
|
+
__version__ = "0.7.0"
|
|
7
7
|
|
|
8
8
|
# Import main modules for easier access
|
|
9
9
|
from . import services
|