SymfWebAPI 1.26.10.1__py3-none-any.whl
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.
- SymfWebAPI/WebAPI/Interface/BankAccounts/Interfaces/IBankAccountsController/__init__.py +83 -0
- SymfWebAPI/WebAPI/Interface/BankAccounts/Interfaces/IBankAccountsController/_common.py +37 -0
- SymfWebAPI/WebAPI/Interface/BankAccounts/Interfaces/IBankAccountsController/_ops.py +33 -0
- SymfWebAPI/WebAPI/Interface/BankAccounts/Interfaces/__init__.py +21 -0
- SymfWebAPI/WebAPI/Interface/BankAccounts/ViewModels/__init__.py +16 -0
- SymfWebAPI/WebAPI/Interface/BankAccounts/__init__.py +22 -0
- SymfWebAPI/WebAPI/Interface/Common/Interfaces/ICurrencyRatesController/__init__.py +56 -0
- SymfWebAPI/WebAPI/Interface/Common/Interfaces/ICurrencyRatesController/_common.py +33 -0
- SymfWebAPI/WebAPI/Interface/Common/Interfaces/ICurrencyRatesController/_ops.py +26 -0
- SymfWebAPI/WebAPI/Interface/Common/Interfaces/IDocumentSeriesController/__init__.py +27 -0
- SymfWebAPI/WebAPI/Interface/Common/Interfaces/IDocumentSeriesController/_common.py +10 -0
- SymfWebAPI/WebAPI/Interface/Common/Interfaces/IDocumentSeriesController/_ops.py +13 -0
- SymfWebAPI/WebAPI/Interface/Common/Interfaces/IDocumentTypesController/__init__.py +41 -0
- SymfWebAPI/WebAPI/Interface/Common/Interfaces/IDocumentTypesController/_common.py +17 -0
- SymfWebAPI/WebAPI/Interface/Common/Interfaces/IDocumentTypesController/_ops.py +19 -0
- SymfWebAPI/WebAPI/Interface/Common/Interfaces/IKsefController/__init__.py +40 -0
- SymfWebAPI/WebAPI/Interface/Common/Interfaces/IKsefController/_common.py +20 -0
- SymfWebAPI/WebAPI/Interface/Common/Interfaces/IKsefController/_ops.py +14 -0
- SymfWebAPI/WebAPI/Interface/Common/Interfaces/IPaymentFormsController/__init__.py +27 -0
- SymfWebAPI/WebAPI/Interface/Common/Interfaces/IPaymentFormsController/_common.py +10 -0
- SymfWebAPI/WebAPI/Interface/Common/Interfaces/IPaymentFormsController/_ops.py +13 -0
- SymfWebAPI/WebAPI/Interface/Common/Interfaces/__init__.py +25 -0
- SymfWebAPI/WebAPI/Interface/Common/ViewModels/Aspects/__init__.py +45 -0
- SymfWebAPI/WebAPI/Interface/Common/ViewModels/__init__.py +118 -0
- SymfWebAPI/WebAPI/Interface/Common/__init__.py +22 -0
- SymfWebAPI/WebAPI/Interface/Contractors/Interfaces/IContractorCardIndexController/__init__.py +54 -0
- SymfWebAPI/WebAPI/Interface/Contractors/Interfaces/IContractorCardIndexController/_common.py +24 -0
- SymfWebAPI/WebAPI/Interface/Contractors/Interfaces/IContractorCardIndexController/_ops.py +17 -0
- SymfWebAPI/WebAPI/Interface/Contractors/Interfaces/IContractorDeliveryAddressesController/__init__.py +55 -0
- SymfWebAPI/WebAPI/Interface/Contractors/Interfaces/IContractorDeliveryAddressesController/_common.py +24 -0
- SymfWebAPI/WebAPI/Interface/Contractors/Interfaces/IContractorDeliveryAddressesController/_ops.py +23 -0
- SymfWebAPI/WebAPI/Interface/Contractors/Interfaces/IContractorDimensions2Controller/__init__.py +27 -0
- SymfWebAPI/WebAPI/Interface/Contractors/Interfaces/IContractorDimensions2Controller/_common.py +10 -0
- SymfWebAPI/WebAPI/Interface/Contractors/Interfaces/IContractorDimensions2Controller/_ops.py +13 -0
- SymfWebAPI/WebAPI/Interface/Contractors/Interfaces/IContractorDimensionsController/__init__.py +41 -0
- SymfWebAPI/WebAPI/Interface/Contractors/Interfaces/IContractorDimensionsController/_common.py +19 -0
- SymfWebAPI/WebAPI/Interface/Contractors/Interfaces/IContractorDimensionsController/_ops.py +17 -0
- SymfWebAPI/WebAPI/Interface/Contractors/Interfaces/IContractorsController/__init__.py +230 -0
- SymfWebAPI/WebAPI/Interface/Contractors/Interfaces/IContractorsController/_common.py +109 -0
- SymfWebAPI/WebAPI/Interface/Contractors/Interfaces/IContractorsController/_ops.py +100 -0
- SymfWebAPI/WebAPI/Interface/Contractors/Interfaces/__init__.py +25 -0
- SymfWebAPI/WebAPI/Interface/Contractors/ViewModels/__init__.py +64 -0
- SymfWebAPI/WebAPI/Interface/Contractors/__init__.py +22 -0
- SymfWebAPI/WebAPI/Interface/Dictionaries/Interfaces/IFKDictionariesController/__init__.py +129 -0
- SymfWebAPI/WebAPI/Interface/Dictionaries/Interfaces/IFKDictionariesController/_common.py +59 -0
- SymfWebAPI/WebAPI/Interface/Dictionaries/Interfaces/IFKDictionariesController/_ops.py +48 -0
- SymfWebAPI/WebAPI/Interface/Dictionaries/Interfaces/__init__.py +21 -0
- SymfWebAPI/WebAPI/Interface/Dictionaries/ViewModels/__init__.py +49 -0
- SymfWebAPI/WebAPI/Interface/Dictionaries/__init__.py +22 -0
- SymfWebAPI/WebAPI/Interface/Enums/FKConfigurator/__init__.py +41 -0
- SymfWebAPI/WebAPI/Interface/Enums/__init__.py +459 -0
- SymfWebAPI/WebAPI/Interface/FKF/AccountsChart/Interfaces/IFKAccountsChartController/__init__.py +42 -0
- SymfWebAPI/WebAPI/Interface/FKF/AccountsChart/Interfaces/IFKAccountsChartController/_common.py +17 -0
- SymfWebAPI/WebAPI/Interface/FKF/AccountsChart/Interfaces/IFKAccountsChartController/_ops.py +20 -0
- SymfWebAPI/WebAPI/Interface/FKF/AccountsChart/Interfaces/__init__.py +21 -0
- SymfWebAPI/WebAPI/Interface/FKF/AccountsChart/ViewModels/__init__.py +30 -0
- SymfWebAPI/WebAPI/Interface/FKF/AccountsChart/__init__.py +22 -0
- SymfWebAPI/WebAPI/Interface/FKF/Calculations/Interfaces/IFKCalculationsBusinessController/__init__.py +28 -0
- SymfWebAPI/WebAPI/Interface/FKF/Calculations/Interfaces/IFKCalculationsBusinessController/_common.py +9 -0
- SymfWebAPI/WebAPI/Interface/FKF/Calculations/Interfaces/IFKCalculationsBusinessController/_ops.py +14 -0
- SymfWebAPI/WebAPI/Interface/FKF/Calculations/Interfaces/IFKCalculationsController/__init__.py +478 -0
- SymfWebAPI/WebAPI/Interface/FKF/Calculations/Interfaces/IFKCalculationsController/_common.py +353 -0
- SymfWebAPI/WebAPI/Interface/FKF/Calculations/Interfaces/IFKCalculationsController/_ops.py +208 -0
- SymfWebAPI/WebAPI/Interface/FKF/Calculations/Interfaces/__init__.py +22 -0
- SymfWebAPI/WebAPI/Interface/FKF/Calculations/ViewModels/__init__.py +149 -0
- SymfWebAPI/WebAPI/Interface/FKF/Calculations/__init__.py +22 -0
- SymfWebAPI/WebAPI/Interface/FKF/Common/Interfaces/IFKCurrenciesTablesController/__init__.py +56 -0
- SymfWebAPI/WebAPI/Interface/FKF/Common/Interfaces/IFKCurrenciesTablesController/_common.py +33 -0
- SymfWebAPI/WebAPI/Interface/FKF/Common/Interfaces/IFKCurrenciesTablesController/_ops.py +26 -0
- SymfWebAPI/WebAPI/Interface/FKF/Common/Interfaces/IFKYearsController/__init__.py +27 -0
- SymfWebAPI/WebAPI/Interface/FKF/Common/Interfaces/IFKYearsController/_common.py +9 -0
- SymfWebAPI/WebAPI/Interface/FKF/Common/Interfaces/IFKYearsController/_ops.py +12 -0
- SymfWebAPI/WebAPI/Interface/FKF/Common/Interfaces/__init__.py +22 -0
- SymfWebAPI/WebAPI/Interface/FKF/Common/ViewModels/CriteriaFilter/__init__.py +14 -0
- SymfWebAPI/WebAPI/Interface/FKF/Common/ViewModels/__init__.py +50 -0
- SymfWebAPI/WebAPI/Interface/FKF/Common/__init__.py +22 -0
- SymfWebAPI/WebAPI/Interface/FKF/Contractors/Interfaces/IFKContractorDimensions2Controller/__init__.py +55 -0
- SymfWebAPI/WebAPI/Interface/FKF/Contractors/Interfaces/IFKContractorDimensions2Controller/_common.py +24 -0
- SymfWebAPI/WebAPI/Interface/FKF/Contractors/Interfaces/IFKContractorDimensions2Controller/_ops.py +25 -0
- SymfWebAPI/WebAPI/Interface/FKF/Contractors/Interfaces/IFKContractorDimensionsController/__init__.py +97 -0
- SymfWebAPI/WebAPI/Interface/FKF/Contractors/Interfaces/IFKContractorDimensionsController/_common.py +47 -0
- SymfWebAPI/WebAPI/Interface/FKF/Contractors/Interfaces/IFKContractorDimensionsController/_ops.py +37 -0
- SymfWebAPI/WebAPI/Interface/FKF/Contractors/Interfaces/IFKContractorsController/__init__.py +158 -0
- SymfWebAPI/WebAPI/Interface/FKF/Contractors/Interfaces/IFKContractorsController/_common.py +73 -0
- SymfWebAPI/WebAPI/Interface/FKF/Contractors/Interfaces/IFKContractorsController/_ops.py +70 -0
- SymfWebAPI/WebAPI/Interface/FKF/Contractors/Interfaces/__init__.py +23 -0
- SymfWebAPI/WebAPI/Interface/FKF/Contractors/ViewModels/V2026_1/__init__.py +35 -0
- SymfWebAPI/WebAPI/Interface/FKF/Contractors/ViewModels/__init__.py +79 -0
- SymfWebAPI/WebAPI/Interface/FKF/Contractors/__init__.py +22 -0
- SymfWebAPI/WebAPI/Interface/FKF/Dimensions/Interfaces/IFKDimensionsController/__init__.py +42 -0
- SymfWebAPI/WebAPI/Interface/FKF/Dimensions/Interfaces/IFKDimensionsController/_common.py +19 -0
- SymfWebAPI/WebAPI/Interface/FKF/Dimensions/Interfaces/IFKDimensionsController/_ops.py +20 -0
- SymfWebAPI/WebAPI/Interface/FKF/Dimensions/Interfaces/__init__.py +21 -0
- SymfWebAPI/WebAPI/Interface/FKF/Dimensions/__init__.py +21 -0
- SymfWebAPI/WebAPI/Interface/FKF/Documents/Interfaces/IFKDocumentAttachmentsController/__init__.py +41 -0
- SymfWebAPI/WebAPI/Interface/FKF/Documents/Interfaces/IFKDocumentAttachmentsController/_common.py +19 -0
- SymfWebAPI/WebAPI/Interface/FKF/Documents/Interfaces/IFKDocumentAttachmentsController/_ops.py +14 -0
- SymfWebAPI/WebAPI/Interface/FKF/Documents/Interfaces/IFKDocumentLinksController/__init__.py +41 -0
- SymfWebAPI/WebAPI/Interface/FKF/Documents/Interfaces/IFKDocumentLinksController/_common.py +19 -0
- SymfWebAPI/WebAPI/Interface/FKF/Documents/Interfaces/IFKDocumentLinksController/_ops.py +14 -0
- SymfWebAPI/WebAPI/Interface/FKF/Documents/Interfaces/IFKDocumentsBusinessIssueController/__init__.py +70 -0
- SymfWebAPI/WebAPI/Interface/FKF/Documents/Interfaces/IFKDocumentsBusinessIssueController/_common.py +27 -0
- SymfWebAPI/WebAPI/Interface/FKF/Documents/Interfaces/IFKDocumentsBusinessIssueController/_ops.py +31 -0
- SymfWebAPI/WebAPI/Interface/FKF/Documents/Interfaces/IFKDocumentsController/__init__.py +161 -0
- SymfWebAPI/WebAPI/Interface/FKF/Documents/Interfaces/IFKDocumentsController/_common.py +91 -0
- SymfWebAPI/WebAPI/Interface/FKF/Documents/Interfaces/IFKDocumentsController/_ops.py +75 -0
- SymfWebAPI/WebAPI/Interface/FKF/Documents/Interfaces/IFKDocumentsIssueController/__init__.py +43 -0
- SymfWebAPI/WebAPI/Interface/FKF/Documents/Interfaces/IFKDocumentsIssueController/_common.py +15 -0
- SymfWebAPI/WebAPI/Interface/FKF/Documents/Interfaces/IFKDocumentsIssueController/_ops.py +21 -0
- SymfWebAPI/WebAPI/Interface/FKF/Documents/Interfaces/__init__.py +25 -0
- SymfWebAPI/WebAPI/Interface/FKF/Documents/ViewModels/Issue/Business/__init__.py +75 -0
- SymfWebAPI/WebAPI/Interface/FKF/Documents/ViewModels/Issue/Custom/__init__.py +151 -0
- SymfWebAPI/WebAPI/Interface/FKF/Documents/ViewModels/Issue/__init__.py +12 -0
- SymfWebAPI/WebAPI/Interface/FKF/Documents/ViewModels/Rdf/__init__.py +13 -0
- SymfWebAPI/WebAPI/Interface/FKF/Documents/ViewModels/Transactions/__init__.py +33 -0
- SymfWebAPI/WebAPI/Interface/FKF/Documents/ViewModels/V2026_1/__init__.py +73 -0
- SymfWebAPI/WebAPI/Interface/FKF/Documents/ViewModels/__init__.py +227 -0
- SymfWebAPI/WebAPI/Interface/FKF/Documents/__init__.py +22 -0
- SymfWebAPI/WebAPI/Interface/FKF/Employees/Interfaces/IFKEmployeesController/__init__.py +99 -0
- SymfWebAPI/WebAPI/Interface/FKF/Employees/Interfaces/IFKEmployeesController/_common.py +45 -0
- SymfWebAPI/WebAPI/Interface/FKF/Employees/Interfaces/IFKEmployeesController/_ops.py +42 -0
- SymfWebAPI/WebAPI/Interface/FKF/Employees/Interfaces/__init__.py +21 -0
- SymfWebAPI/WebAPI/Interface/FKF/Employees/ViewModels/__init__.py +30 -0
- SymfWebAPI/WebAPI/Interface/FKF/Employees/__init__.py +22 -0
- SymfWebAPI/WebAPI/Interface/FKF/__init__.py +27 -0
- SymfWebAPI/WebAPI/Interface/HMF/Develogic/Interfaces/IDevelogicPurchasesController/__init__.py +28 -0
- SymfWebAPI/WebAPI/Interface/HMF/Develogic/Interfaces/IDevelogicPurchasesController/_common.py +10 -0
- SymfWebAPI/WebAPI/Interface/HMF/Develogic/Interfaces/IDevelogicPurchasesController/_ops.py +13 -0
- SymfWebAPI/WebAPI/Interface/HMF/Develogic/Interfaces/IDevelogicSalesController/__init__.py +58 -0
- SymfWebAPI/WebAPI/Interface/HMF/Develogic/Interfaces/IDevelogicSalesController/_common.py +27 -0
- SymfWebAPI/WebAPI/Interface/HMF/Develogic/Interfaces/IDevelogicSalesController/_ops.py +27 -0
- SymfWebAPI/WebAPI/Interface/HMF/Develogic/Interfaces/__init__.py +22 -0
- SymfWebAPI/WebAPI/Interface/HMF/Develogic/ViewModels/V2026_1/__init__.py +62 -0
- SymfWebAPI/WebAPI/Interface/HMF/Develogic/ViewModels/__init__.py +69 -0
- SymfWebAPI/WebAPI/Interface/HMF/Develogic/__init__.py +22 -0
- SymfWebAPI/WebAPI/Interface/HMF/__init__.py +21 -0
- SymfWebAPI/WebAPI/Interface/Interfaces/ISessionController/__init__.py +34 -0
- SymfWebAPI/WebAPI/Interface/Interfaces/ISessionController/_common.py +10 -0
- SymfWebAPI/WebAPI/Interface/Interfaces/ISessionController/_ops.py +9 -0
- SymfWebAPI/WebAPI/Interface/Interfaces/__init__.py +21 -0
- SymfWebAPI/WebAPI/Interface/InventoryStates/Interfaces/IInventoryStatesController/__init__.py +98 -0
- SymfWebAPI/WebAPI/Interface/InventoryStates/Interfaces/IInventoryStatesController/_common.py +46 -0
- SymfWebAPI/WebAPI/Interface/InventoryStates/Interfaces/IInventoryStatesController/_ops.py +44 -0
- SymfWebAPI/WebAPI/Interface/InventoryStates/Interfaces/__init__.py +21 -0
- SymfWebAPI/WebAPI/Interface/InventoryStates/ViewModels/__init__.py +11 -0
- SymfWebAPI/WebAPI/Interface/InventoryStates/__init__.py +22 -0
- SymfWebAPI/WebAPI/Interface/OSS/Interfaces/IOssContractorsController/__init__.py +55 -0
- SymfWebAPI/WebAPI/Interface/OSS/Interfaces/IOssContractorsController/_common.py +24 -0
- SymfWebAPI/WebAPI/Interface/OSS/Interfaces/IOssContractorsController/_ops.py +22 -0
- SymfWebAPI/WebAPI/Interface/OSS/Interfaces/IOssOrderController/__init__.py +58 -0
- SymfWebAPI/WebAPI/Interface/OSS/Interfaces/IOssOrderController/_common.py +25 -0
- SymfWebAPI/WebAPI/Interface/OSS/Interfaces/IOssOrderController/_ops.py +28 -0
- SymfWebAPI/WebAPI/Interface/OSS/Interfaces/IOssProductController/__init__.py +55 -0
- SymfWebAPI/WebAPI/Interface/OSS/Interfaces/IOssProductController/_common.py +24 -0
- SymfWebAPI/WebAPI/Interface/OSS/Interfaces/IOssProductController/_ops.py +24 -0
- SymfWebAPI/WebAPI/Interface/OSS/Interfaces/IOssProductMapsController/__init__.py +84 -0
- SymfWebAPI/WebAPI/Interface/OSS/Interfaces/IOssProductMapsController/_common.py +37 -0
- SymfWebAPI/WebAPI/Interface/OSS/Interfaces/IOssProductMapsController/_ops.py +36 -0
- SymfWebAPI/WebAPI/Interface/OSS/Interfaces/IOssReportsController/__init__.py +55 -0
- SymfWebAPI/WebAPI/Interface/OSS/Interfaces/IOssReportsController/_common.py +24 -0
- SymfWebAPI/WebAPI/Interface/OSS/Interfaces/IOssReportsController/_ops.py +24 -0
- SymfWebAPI/WebAPI/Interface/OSS/Interfaces/IOssSaleController/__init__.py +58 -0
- SymfWebAPI/WebAPI/Interface/OSS/Interfaces/IOssSaleController/_common.py +27 -0
- SymfWebAPI/WebAPI/Interface/OSS/Interfaces/IOssSaleController/_ops.py +28 -0
- SymfWebAPI/WebAPI/Interface/OSS/Interfaces/__init__.py +26 -0
- SymfWebAPI/WebAPI/Interface/OSS/ViewModels/Common/__init__.py +35 -0
- SymfWebAPI/WebAPI/Interface/OSS/ViewModels/Orders/__init__.py +64 -0
- SymfWebAPI/WebAPI/Interface/OSS/ViewModels/Sales/V2026_1/__init__.py +43 -0
- SymfWebAPI/WebAPI/Interface/OSS/ViewModels/Sales/__init__.py +85 -0
- SymfWebAPI/WebAPI/Interface/OSS/ViewModels/__init__.py +38 -0
- SymfWebAPI/WebAPI/Interface/OSS/__init__.py +22 -0
- SymfWebAPI/WebAPI/Interface/Orders/Interfaces/IOrderDimensions2Controller/__init__.py +70 -0
- SymfWebAPI/WebAPI/Interface/Orders/Interfaces/IOrderDimensions2Controller/_common.py +33 -0
- SymfWebAPI/WebAPI/Interface/Orders/Interfaces/IOrderDimensions2Controller/_ops.py +32 -0
- SymfWebAPI/WebAPI/Interface/Orders/Interfaces/IOrderDimensionsController/__init__.py +128 -0
- SymfWebAPI/WebAPI/Interface/Orders/Interfaces/IOrderDimensionsController/_common.py +63 -0
- SymfWebAPI/WebAPI/Interface/Orders/Interfaces/IOrderDimensionsController/_ops.py +52 -0
- SymfWebAPI/WebAPI/Interface/Orders/Interfaces/IOrdersController/__init__.py +236 -0
- SymfWebAPI/WebAPI/Interface/Orders/Interfaces/IOrdersController/_common.py +130 -0
- SymfWebAPI/WebAPI/Interface/Orders/Interfaces/IOrdersController/_ops.py +110 -0
- SymfWebAPI/WebAPI/Interface/Orders/Interfaces/IOrdersIssueController/__init__.py +115 -0
- SymfWebAPI/WebAPI/Interface/Orders/Interfaces/IOrdersIssueController/_common.py +55 -0
- SymfWebAPI/WebAPI/Interface/Orders/Interfaces/IOrdersIssueController/_ops.py +49 -0
- SymfWebAPI/WebAPI/Interface/Orders/Interfaces/__init__.py +24 -0
- SymfWebAPI/WebAPI/Interface/Orders/ViewModels/__init__.py +302 -0
- SymfWebAPI/WebAPI/Interface/Orders/__init__.py +22 -0
- SymfWebAPI/WebAPI/Interface/OwnOrders/Interfaces/IOwnOrderDimensions2Controller/__init__.py +70 -0
- SymfWebAPI/WebAPI/Interface/OwnOrders/Interfaces/IOwnOrderDimensions2Controller/_common.py +33 -0
- SymfWebAPI/WebAPI/Interface/OwnOrders/Interfaces/IOwnOrderDimensions2Controller/_ops.py +32 -0
- SymfWebAPI/WebAPI/Interface/OwnOrders/Interfaces/IOwnOrderDimensionsController/__init__.py +128 -0
- SymfWebAPI/WebAPI/Interface/OwnOrders/Interfaces/IOwnOrderDimensionsController/_common.py +63 -0
- SymfWebAPI/WebAPI/Interface/OwnOrders/Interfaces/IOwnOrderDimensionsController/_ops.py +52 -0
- SymfWebAPI/WebAPI/Interface/OwnOrders/Interfaces/IOwnOrdersController/__init__.py +207 -0
- SymfWebAPI/WebAPI/Interface/OwnOrders/Interfaces/IOwnOrdersController/_common.py +115 -0
- SymfWebAPI/WebAPI/Interface/OwnOrders/Interfaces/IOwnOrdersController/_ops.py +97 -0
- SymfWebAPI/WebAPI/Interface/OwnOrders/Interfaces/IOwnOrdersIssueController/__init__.py +99 -0
- SymfWebAPI/WebAPI/Interface/OwnOrders/Interfaces/IOwnOrdersIssueController/_common.py +47 -0
- SymfWebAPI/WebAPI/Interface/OwnOrders/Interfaces/IOwnOrdersIssueController/_ops.py +39 -0
- SymfWebAPI/WebAPI/Interface/OwnOrders/Interfaces/__init__.py +24 -0
- SymfWebAPI/WebAPI/Interface/OwnOrders/ViewModels/__init__.py +205 -0
- SymfWebAPI/WebAPI/Interface/OwnOrders/__init__.py +22 -0
- SymfWebAPI/WebAPI/Interface/Payments/Interfaces/IPaymentsController/__init__.py +189 -0
- SymfWebAPI/WebAPI/Interface/Payments/Interfaces/IPaymentsController/_common.py +104 -0
- SymfWebAPI/WebAPI/Interface/Payments/Interfaces/IPaymentsController/_ops.py +85 -0
- SymfWebAPI/WebAPI/Interface/Payments/Interfaces/ISettlementsController/__init__.py +114 -0
- SymfWebAPI/WebAPI/Interface/Payments/Interfaces/ISettlementsController/_common.py +69 -0
- SymfWebAPI/WebAPI/Interface/Payments/Interfaces/ISettlementsController/_ops.py +48 -0
- SymfWebAPI/WebAPI/Interface/Payments/Interfaces/__init__.py +22 -0
- SymfWebAPI/WebAPI/Interface/Payments/ViewModels/Issue/__init__.py +38 -0
- SymfWebAPI/WebAPI/Interface/Payments/ViewModels/IssueKP/__init__.py +30 -0
- SymfWebAPI/WebAPI/Interface/Payments/ViewModels/__init__.py +124 -0
- SymfWebAPI/WebAPI/Interface/Payments/__init__.py +22 -0
- SymfWebAPI/WebAPI/Interface/Products/Interfaces/IPriceListsController/__init__.py +42 -0
- SymfWebAPI/WebAPI/Interface/Products/Interfaces/IPriceListsController/_common.py +16 -0
- SymfWebAPI/WebAPI/Interface/Products/Interfaces/IPriceListsController/_ops.py +20 -0
- SymfWebAPI/WebAPI/Interface/Products/Interfaces/IProductDimensions2Controller/__init__.py +27 -0
- SymfWebAPI/WebAPI/Interface/Products/Interfaces/IProductDimensions2Controller/_common.py +10 -0
- SymfWebAPI/WebAPI/Interface/Products/Interfaces/IProductDimensions2Controller/_ops.py +13 -0
- SymfWebAPI/WebAPI/Interface/Products/Interfaces/IProductDimensionsController/__init__.py +41 -0
- SymfWebAPI/WebAPI/Interface/Products/Interfaces/IProductDimensionsController/_common.py +19 -0
- SymfWebAPI/WebAPI/Interface/Products/Interfaces/IProductDimensionsController/_ops.py +17 -0
- SymfWebAPI/WebAPI/Interface/Products/Interfaces/IProductPhotosController/__init__.py +28 -0
- SymfWebAPI/WebAPI/Interface/Products/Interfaces/IProductPhotosController/_common.py +11 -0
- SymfWebAPI/WebAPI/Interface/Products/Interfaces/IProductPhotosController/_ops.py +13 -0
- SymfWebAPI/WebAPI/Interface/Products/Interfaces/IProductPricesController/__init__.py +178 -0
- SymfWebAPI/WebAPI/Interface/Products/Interfaces/IProductPricesController/_common.py +77 -0
- SymfWebAPI/WebAPI/Interface/Products/Interfaces/IProductPricesController/_ops.py +80 -0
- SymfWebAPI/WebAPI/Interface/Products/Interfaces/IProductsController/__init__.py +247 -0
- SymfWebAPI/WebAPI/Interface/Products/Interfaces/IProductsController/_common.py +113 -0
- SymfWebAPI/WebAPI/Interface/Products/Interfaces/IProductsController/_ops.py +109 -0
- SymfWebAPI/WebAPI/Interface/Products/Interfaces/__init__.py +26 -0
- SymfWebAPI/WebAPI/Interface/Products/ViewModels/PriceCalculations/__init__.py +91 -0
- SymfWebAPI/WebAPI/Interface/Products/ViewModels/PriceLists/__init__.py +60 -0
- SymfWebAPI/WebAPI/Interface/Products/ViewModels/Prices/__init__.py +128 -0
- SymfWebAPI/WebAPI/Interface/Products/ViewModels/__init__.py +217 -0
- SymfWebAPI/WebAPI/Interface/Products/__init__.py +22 -0
- SymfWebAPI/WebAPI/Interface/Purchases/Interfaces/IPurchasesController/__init__.py +221 -0
- SymfWebAPI/WebAPI/Interface/Purchases/Interfaces/IPurchasesController/_common.py +124 -0
- SymfWebAPI/WebAPI/Interface/Purchases/Interfaces/IPurchasesController/_ops.py +103 -0
- SymfWebAPI/WebAPI/Interface/Purchases/Interfaces/IPurchasesDimensions2Controller/__init__.py +70 -0
- SymfWebAPI/WebAPI/Interface/Purchases/Interfaces/IPurchasesDimensions2Controller/_common.py +33 -0
- SymfWebAPI/WebAPI/Interface/Purchases/Interfaces/IPurchasesDimensions2Controller/_ops.py +32 -0
- SymfWebAPI/WebAPI/Interface/Purchases/Interfaces/IPurchasesDimensionsController/__init__.py +128 -0
- SymfWebAPI/WebAPI/Interface/Purchases/Interfaces/IPurchasesDimensionsController/_common.py +63 -0
- SymfWebAPI/WebAPI/Interface/Purchases/Interfaces/IPurchasesDimensionsController/_ops.py +52 -0
- SymfWebAPI/WebAPI/Interface/Purchases/Interfaces/IPurchasesIssueController/__init__.py +86 -0
- SymfWebAPI/WebAPI/Interface/Purchases/Interfaces/IPurchasesIssueController/_common.py +40 -0
- SymfWebAPI/WebAPI/Interface/Purchases/Interfaces/IPurchasesIssueController/_ops.py +38 -0
- SymfWebAPI/WebAPI/Interface/Purchases/Interfaces/__init__.py +24 -0
- SymfWebAPI/WebAPI/Interface/Purchases/ViewModels/V2026_1/__init__.py +171 -0
- SymfWebAPI/WebAPI/Interface/Purchases/ViewModels/__init__.py +245 -0
- SymfWebAPI/WebAPI/Interface/Purchases/__init__.py +22 -0
- SymfWebAPI/WebAPI/Interface/RepX/Interfaces/IReportsController/__init__.py +28 -0
- SymfWebAPI/WebAPI/Interface/RepX/Interfaces/IReportsController/_common.py +11 -0
- SymfWebAPI/WebAPI/Interface/RepX/Interfaces/IReportsController/_ops.py +13 -0
- SymfWebAPI/WebAPI/Interface/RepX/Interfaces/__init__.py +21 -0
- SymfWebAPI/WebAPI/Interface/RepX/ViewModels/__init__.py +14 -0
- SymfWebAPI/WebAPI/Interface/RepX/__init__.py +22 -0
- SymfWebAPI/WebAPI/Interface/Reservations/Interfaces/IReservationsController/__init__.py +114 -0
- SymfWebAPI/WebAPI/Interface/Reservations/Interfaces/IReservationsController/_common.py +50 -0
- SymfWebAPI/WebAPI/Interface/Reservations/Interfaces/IReservationsController/_ops.py +48 -0
- SymfWebAPI/WebAPI/Interface/Reservations/Interfaces/__init__.py +21 -0
- SymfWebAPI/WebAPI/Interface/Reservations/ViewModels/__init__.py +110 -0
- SymfWebAPI/WebAPI/Interface/Reservations/__init__.py +22 -0
- SymfWebAPI/WebAPI/Interface/Sales/Interfaces/IFiscalPrinterController/__init__.py +27 -0
- SymfWebAPI/WebAPI/Interface/Sales/Interfaces/IFiscalPrinterController/_common.py +10 -0
- SymfWebAPI/WebAPI/Interface/Sales/Interfaces/IFiscalPrinterController/_ops.py +12 -0
- SymfWebAPI/WebAPI/Interface/Sales/Interfaces/ISalesController/__init__.py +237 -0
- SymfWebAPI/WebAPI/Interface/Sales/Interfaces/ISalesController/_common.py +130 -0
- SymfWebAPI/WebAPI/Interface/Sales/Interfaces/ISalesController/_ops.py +111 -0
- SymfWebAPI/WebAPI/Interface/Sales/Interfaces/ISalesDimensions2Controller/__init__.py +70 -0
- SymfWebAPI/WebAPI/Interface/Sales/Interfaces/ISalesDimensions2Controller/_common.py +33 -0
- SymfWebAPI/WebAPI/Interface/Sales/Interfaces/ISalesDimensions2Controller/_ops.py +32 -0
- SymfWebAPI/WebAPI/Interface/Sales/Interfaces/ISalesDimensionsController/__init__.py +128 -0
- SymfWebAPI/WebAPI/Interface/Sales/Interfaces/ISalesDimensionsController/_common.py +63 -0
- SymfWebAPI/WebAPI/Interface/Sales/Interfaces/ISalesDimensionsController/_ops.py +52 -0
- SymfWebAPI/WebAPI/Interface/Sales/Interfaces/ISalesIssueController/__init__.py +129 -0
- SymfWebAPI/WebAPI/Interface/Sales/Interfaces/ISalesIssueController/_common.py +63 -0
- SymfWebAPI/WebAPI/Interface/Sales/Interfaces/ISalesIssueController/_ops.py +53 -0
- SymfWebAPI/WebAPI/Interface/Sales/Interfaces/__init__.py +25 -0
- SymfWebAPI/WebAPI/Interface/Sales/ViewModels/CorrectionIssue/V2026_1/__init__.py +42 -0
- SymfWebAPI/WebAPI/Interface/Sales/ViewModels/CorrectionIssue/__init__.py +23 -0
- SymfWebAPI/WebAPI/Interface/Sales/ViewModels/DocumentIssue/__init__.py +11 -0
- SymfWebAPI/WebAPI/Interface/Sales/ViewModels/__init__.py +325 -0
- SymfWebAPI/WebAPI/Interface/Sales/__init__.py +22 -0
- SymfWebAPI/WebAPI/Interface/ViewModels/__init__.py +16 -0
- SymfWebAPI/WebAPI/Interface/Warehouse/Interfaces/IDeliveriesController/__init__.py +27 -0
- SymfWebAPI/WebAPI/Interface/Warehouse/Interfaces/IDeliveriesController/_common.py +11 -0
- SymfWebAPI/WebAPI/Interface/Warehouse/Interfaces/IDeliveriesController/_ops.py +13 -0
- SymfWebAPI/WebAPI/Interface/Warehouse/Interfaces/IDeliveryDimensionsController/__init__.py +41 -0
- SymfWebAPI/WebAPI/Interface/Warehouse/Interfaces/IDeliveryDimensionsController/_common.py +19 -0
- SymfWebAPI/WebAPI/Interface/Warehouse/Interfaces/IDeliveryDimensionsController/_ops.py +17 -0
- SymfWebAPI/WebAPI/Interface/Warehouse/Interfaces/IWarehouseDocumentDimensions2Controller/__init__.py +70 -0
- SymfWebAPI/WebAPI/Interface/Warehouse/Interfaces/IWarehouseDocumentDimensions2Controller/_common.py +33 -0
- SymfWebAPI/WebAPI/Interface/Warehouse/Interfaces/IWarehouseDocumentDimensions2Controller/_ops.py +32 -0
- SymfWebAPI/WebAPI/Interface/Warehouse/Interfaces/IWarehouseDocumentDimensionsController/__init__.py +128 -0
- SymfWebAPI/WebAPI/Interface/Warehouse/Interfaces/IWarehouseDocumentDimensionsController/_common.py +63 -0
- SymfWebAPI/WebAPI/Interface/Warehouse/Interfaces/IWarehouseDocumentDimensionsController/_ops.py +52 -0
- SymfWebAPI/WebAPI/Interface/Warehouse/Interfaces/IWarehouseDocumentsController/__init__.py +177 -0
- SymfWebAPI/WebAPI/Interface/Warehouse/Interfaces/IWarehouseDocumentsController/_common.py +100 -0
- SymfWebAPI/WebAPI/Interface/Warehouse/Interfaces/IWarehouseDocumentsController/_ops.py +83 -0
- SymfWebAPI/WebAPI/Interface/Warehouse/Interfaces/IWarehouseDocumentsIssueController/__init__.py +85 -0
- SymfWebAPI/WebAPI/Interface/Warehouse/Interfaces/IWarehouseDocumentsIssueController/_common.py +38 -0
- SymfWebAPI/WebAPI/Interface/Warehouse/Interfaces/IWarehouseDocumentsIssueController/_ops.py +34 -0
- SymfWebAPI/WebAPI/Interface/Warehouse/Interfaces/__init__.py +26 -0
- SymfWebAPI/WebAPI/Interface/Warehouse/ViewModels/__init__.py +265 -0
- SymfWebAPI/WebAPI/Interface/Warehouse/__init__.py +22 -0
- SymfWebAPI/WebAPI/Interface/__init__.py +40 -0
- SymfWebAPI/WebAPI/__init__.py +21 -0
- SymfWebAPI/__init__.py +63 -0
- SymfWebAPI/client.py +129 -0
- SymfWebAPI/config.py +60 -0
- SymfWebAPI/enums.py +36 -0
- SymfWebAPI/errors.py +47 -0
- SymfWebAPI/executors.py +92 -0
- SymfWebAPI/operations.py +116 -0
- SymfWebAPI/protocols.py +85 -0
- SymfWebAPI/request_engine.py +43 -0
- SymfWebAPI/response.py +21 -0
- SymfWebAPI/runtime.py +85 -0
- SymfWebAPI/session.py +349 -0
- SymfWebAPI/transport/__init__.py +9 -0
- SymfWebAPI/transport/httpx_async.py +77 -0
- SymfWebAPI/transport/httpx_sync.py +78 -0
- symfwebapi-1.26.10.1.dist-info/METADATA +78 -0
- symfwebapi-1.26.10.1.dist-info/RECORD +329 -0
- symfwebapi-1.26.10.1.dist-info/WHEEL +5 -0
- symfwebapi-1.26.10.1.dist-info/licenses/LICENSE +29 -0
- symfwebapi-1.26.10.1.dist-info/top_level.txt +1 -0
SymfWebAPI/client.py
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"""High-level async/sync clients wrapping transport + session manager."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import asyncio
|
|
6
|
+
from contextlib import AbstractAsyncContextManager, AbstractContextManager
|
|
7
|
+
from typing import Any, Awaitable, Callable, Optional
|
|
8
|
+
|
|
9
|
+
from .config import ClientConfig
|
|
10
|
+
from .executors import AsyncRequestExecutor, SyncRequestExecutor
|
|
11
|
+
from .operations import OperationSpec
|
|
12
|
+
from .response import ResponseEnvelope
|
|
13
|
+
from .session import SessionManager
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class AsyncAPI(AbstractAsyncContextManager["AsyncAPI"]):
|
|
17
|
+
def __init__(
|
|
18
|
+
self,
|
|
19
|
+
config: ClientConfig,
|
|
20
|
+
session_manager: SessionManager,
|
|
21
|
+
request_fn: Callable[..., Any],
|
|
22
|
+
shutdown_hook: Optional[Callable[[], Awaitable[None]]] = None,
|
|
23
|
+
):
|
|
24
|
+
self._config = config
|
|
25
|
+
self._session = session_manager
|
|
26
|
+
self._executor = AsyncRequestExecutor(config, session_manager, request_fn)
|
|
27
|
+
self._shutdown_hook = shutdown_hook
|
|
28
|
+
|
|
29
|
+
async def __aenter__(self) -> "AsyncAPI":
|
|
30
|
+
await self.open()
|
|
31
|
+
return self
|
|
32
|
+
|
|
33
|
+
async def __aexit__(self, exc_type, exc, tb) -> None:
|
|
34
|
+
await self.close()
|
|
35
|
+
|
|
36
|
+
async def open(self) -> "AsyncAPI":
|
|
37
|
+
await self._session.ensure_async()
|
|
38
|
+
return self
|
|
39
|
+
|
|
40
|
+
async def close(self) -> None:
|
|
41
|
+
try:
|
|
42
|
+
await self._session.close_async()
|
|
43
|
+
finally:
|
|
44
|
+
if self._shutdown_hook:
|
|
45
|
+
await self._shutdown_hook()
|
|
46
|
+
|
|
47
|
+
async def ensure_session(self) -> str:
|
|
48
|
+
return await self._executor.ensure_session()
|
|
49
|
+
|
|
50
|
+
async def request(
|
|
51
|
+
self,
|
|
52
|
+
method: str,
|
|
53
|
+
path: str,
|
|
54
|
+
*,
|
|
55
|
+
params: Optional[dict] = None,
|
|
56
|
+
data: Any = None,
|
|
57
|
+
) -> ResponseEnvelope[Any]:
|
|
58
|
+
return await self._executor.request(method, path, params=params, data=data)
|
|
59
|
+
|
|
60
|
+
def invalidate_session(self) -> None:
|
|
61
|
+
self._executor.invalidate_session()
|
|
62
|
+
|
|
63
|
+
async def invoke(
|
|
64
|
+
self,
|
|
65
|
+
operation: OperationSpec,
|
|
66
|
+
*,
|
|
67
|
+
params: Optional[dict] = None,
|
|
68
|
+
data: Any = None,
|
|
69
|
+
) -> ResponseEnvelope[Any]:
|
|
70
|
+
envelope = await self.request(operation.method, operation.path, params=params, data=data)
|
|
71
|
+
if self._config.offload_async_parsing:
|
|
72
|
+
return await asyncio.to_thread(operation.parser, envelope)
|
|
73
|
+
return operation.parser(envelope)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class SyncAPI(AbstractContextManager["SyncAPI"]):
|
|
77
|
+
def __init__(
|
|
78
|
+
self,
|
|
79
|
+
config: ClientConfig,
|
|
80
|
+
session_manager: SessionManager,
|
|
81
|
+
request_fn: Callable[..., Any],
|
|
82
|
+
shutdown_hook: Optional[Callable[[], None]] = None,
|
|
83
|
+
):
|
|
84
|
+
self._session = session_manager
|
|
85
|
+
self._executor = SyncRequestExecutor(config, session_manager, request_fn)
|
|
86
|
+
self._shutdown_hook = shutdown_hook
|
|
87
|
+
|
|
88
|
+
def __enter__(self) -> "SyncAPI":
|
|
89
|
+
return self.open()
|
|
90
|
+
|
|
91
|
+
def __exit__(self, exc_type, exc, tb) -> None:
|
|
92
|
+
self.close()
|
|
93
|
+
|
|
94
|
+
def open(self) -> "SyncAPI":
|
|
95
|
+
self._session.ensure_sync()
|
|
96
|
+
return self
|
|
97
|
+
|
|
98
|
+
def close(self) -> None:
|
|
99
|
+
try:
|
|
100
|
+
self._session.close_sync()
|
|
101
|
+
finally:
|
|
102
|
+
if self._shutdown_hook:
|
|
103
|
+
self._shutdown_hook()
|
|
104
|
+
|
|
105
|
+
def ensure_session(self) -> str:
|
|
106
|
+
return self._executor.ensure_session()
|
|
107
|
+
|
|
108
|
+
def request(
|
|
109
|
+
self,
|
|
110
|
+
method: str,
|
|
111
|
+
path: str,
|
|
112
|
+
*,
|
|
113
|
+
params: Optional[dict] = None,
|
|
114
|
+
data: Any = None,
|
|
115
|
+
) -> ResponseEnvelope[Any]:
|
|
116
|
+
return self._executor.request(method, path, params=params, data=data)
|
|
117
|
+
|
|
118
|
+
def invalidate_session(self) -> None:
|
|
119
|
+
self._executor.invalidate_session()
|
|
120
|
+
|
|
121
|
+
def invoke(
|
|
122
|
+
self,
|
|
123
|
+
operation: OperationSpec,
|
|
124
|
+
*,
|
|
125
|
+
params: Optional[dict] = None,
|
|
126
|
+
data: Any = None,
|
|
127
|
+
) -> ResponseEnvelope[Any]:
|
|
128
|
+
envelope = self.request(operation.method, operation.path, params=params, data=data)
|
|
129
|
+
return operation.parser(envelope)
|
SymfWebAPI/config.py
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""Konfiguracja klienta Symfonia WebAPI."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass, field
|
|
6
|
+
from datetime import timedelta
|
|
7
|
+
import re
|
|
8
|
+
from typing import Final
|
|
9
|
+
|
|
10
|
+
from .errors import ConfigurationError
|
|
11
|
+
|
|
12
|
+
_GUID_RE: Final[re.Pattern[str]] = re.compile(
|
|
13
|
+
r"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _validate_guid(label: str, value: str) -> None:
|
|
18
|
+
if not _GUID_RE.fullmatch(value or ""):
|
|
19
|
+
raise ConfigurationError(f"{label} must be a GUID (got: {value!r})")
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _validate_non_empty(label: str, value: str) -> None:
|
|
23
|
+
if not value or not value.strip():
|
|
24
|
+
raise ConfigurationError(f"{label} must be a non-empty string")
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _validate_domain(domain: str) -> None:
|
|
28
|
+
# ClientConfig builds the scheme from `https`, so domain must not include http/https prefix.
|
|
29
|
+
if "://" in domain:
|
|
30
|
+
raise ConfigurationError("domain must not include URL scheme (use https flag instead)")
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@dataclass(slots=True)
|
|
34
|
+
class ClientConfig:
|
|
35
|
+
"""Podstawowe parametry wymagane do połączenia z WebAPI."""
|
|
36
|
+
|
|
37
|
+
domain: str
|
|
38
|
+
application_key: str
|
|
39
|
+
device_name: str
|
|
40
|
+
https: bool = False
|
|
41
|
+
request_timeout: float = 30.0
|
|
42
|
+
offload_async_parsing: bool = False
|
|
43
|
+
max_session_age: timedelta | None = field(
|
|
44
|
+
default_factory=lambda: timedelta(minutes=25)
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
def __post_init__(self) -> None:
|
|
48
|
+
_validate_non_empty("domain", self.domain)
|
|
49
|
+
_validate_non_empty("device_name", self.device_name)
|
|
50
|
+
_validate_domain(self.domain)
|
|
51
|
+
_validate_guid("application_key", self.application_key)
|
|
52
|
+
if self.request_timeout <= 0:
|
|
53
|
+
raise ConfigurationError("request_timeout must be positive")
|
|
54
|
+
if self.max_session_age is not None and self.max_session_age.total_seconds() <= 0:
|
|
55
|
+
raise ConfigurationError("max_session_age must be positive when set")
|
|
56
|
+
|
|
57
|
+
@property
|
|
58
|
+
def base_url(self) -> str:
|
|
59
|
+
scheme = "https" if self.https else "http"
|
|
60
|
+
return f"{scheme}://{self.domain}"
|
SymfWebAPI/enums.py
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"""Forward-compatible enum primitives used by generated models."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from enum import Enum
|
|
6
|
+
import re
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
_UNRECOGNIZED_NAME_SANITIZE_RE = re.compile(r"[^0-9A-Za-z_]")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ForwardCompatibleEnum(Enum):
|
|
13
|
+
"""Enum that preserves unknown values returned by the server."""
|
|
14
|
+
|
|
15
|
+
@property
|
|
16
|
+
def is_unrecognized(self) -> bool:
|
|
17
|
+
return bool(getattr(self, "_unrecognized_", False))
|
|
18
|
+
|
|
19
|
+
@property
|
|
20
|
+
def raw_value(self) -> Any:
|
|
21
|
+
return self.value
|
|
22
|
+
|
|
23
|
+
@classmethod
|
|
24
|
+
def _missing_(cls, value: object):
|
|
25
|
+
cached = cls._value2member_map_.get(value)
|
|
26
|
+
if cached is not None:
|
|
27
|
+
return cached
|
|
28
|
+
|
|
29
|
+
pseudo_member = object.__new__(cls)
|
|
30
|
+
value_repr = str(value)
|
|
31
|
+
safe_value = _UNRECOGNIZED_NAME_SANITIZE_RE.sub("_", value_repr).strip("_") or "VALUE"
|
|
32
|
+
pseudo_member._name_ = f"UNRECOGNIZED_{safe_value}"
|
|
33
|
+
pseudo_member._value_ = value
|
|
34
|
+
pseudo_member._unrecognized_ = True
|
|
35
|
+
cls._value2member_map_[value] = pseudo_member
|
|
36
|
+
return pseudo_member
|
SymfWebAPI/errors.py
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"""Error hierarchy for Symfonia WebAPI client runtime."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import Optional
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class SymfoniaError(RuntimeError):
|
|
10
|
+
"""Base exception for all runtime errors."""
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ConfigurationError(SymfoniaError):
|
|
14
|
+
"""Raised when client configuration is invalid."""
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class TransportError(SymfoniaError):
|
|
18
|
+
"""Wrapping lower-level HTTP/IO errors."""
|
|
19
|
+
|
|
20
|
+
def __init__(self, message: str, *, endpoint: Optional[str] = None) -> None:
|
|
21
|
+
super().__init__(message)
|
|
22
|
+
self.endpoint = endpoint
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class SessionError(SymfoniaError):
|
|
26
|
+
"""Base class for session-specific issues."""
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class SessionExpiredError(SessionError):
|
|
30
|
+
"""Raised when session token is no longer valid."""
|
|
31
|
+
|
|
32
|
+
def __init__(self, message: str, *, endpoint: Optional[str] = None) -> None:
|
|
33
|
+
super().__init__(message)
|
|
34
|
+
self.endpoint = endpoint
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@dataclass(slots=True)
|
|
38
|
+
class WebAPIHttpError(SymfoniaError):
|
|
39
|
+
"""Raised for non-success HTTP responses."""
|
|
40
|
+
|
|
41
|
+
status_code: int
|
|
42
|
+
endpoint: str
|
|
43
|
+
response_text: str
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class SessionManagementBypassWarning(UserWarning):
|
|
47
|
+
"""Warning emitted when manual session endpoints are called directly."""
|
SymfWebAPI/executors.py
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"""Sync/async executors implementing one shared request flow policy."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any, Callable, Optional
|
|
6
|
+
|
|
7
|
+
from .config import ClientConfig
|
|
8
|
+
from .errors import SessionExpiredError
|
|
9
|
+
from .request_engine import normalize_query_params, should_retry_auth, to_envelope_or_raise
|
|
10
|
+
from .response import ResponseEnvelope
|
|
11
|
+
from .session import SessionManager
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class SyncRequestExecutor:
|
|
15
|
+
def __init__(
|
|
16
|
+
self,
|
|
17
|
+
_config: ClientConfig,
|
|
18
|
+
session_manager: SessionManager,
|
|
19
|
+
request_fn: Callable[..., Any],
|
|
20
|
+
) -> None:
|
|
21
|
+
self._session = session_manager
|
|
22
|
+
self._request = request_fn
|
|
23
|
+
|
|
24
|
+
def ensure_session(self) -> str:
|
|
25
|
+
state = self._session.ensure_sync()
|
|
26
|
+
if not state.token:
|
|
27
|
+
raise SessionExpiredError("Session not established")
|
|
28
|
+
return state.token
|
|
29
|
+
|
|
30
|
+
def invalidate_session(self) -> None:
|
|
31
|
+
self._session.invalidate()
|
|
32
|
+
|
|
33
|
+
def request(
|
|
34
|
+
self,
|
|
35
|
+
method: str,
|
|
36
|
+
path: str,
|
|
37
|
+
*,
|
|
38
|
+
params: Optional[dict] = None,
|
|
39
|
+
data: Any = None,
|
|
40
|
+
) -> ResponseEnvelope[Any]:
|
|
41
|
+
normalized_params = normalize_query_params(params)
|
|
42
|
+
token = self.ensure_session()
|
|
43
|
+
response = self._request(method, path, token=token, params=normalized_params, data=data)
|
|
44
|
+
if should_retry_auth(response.status_code):
|
|
45
|
+
self.invalidate_session()
|
|
46
|
+
token = self.ensure_session()
|
|
47
|
+
response = self._request(method, path, token=token, params=normalized_params, data=data)
|
|
48
|
+
return to_envelope_or_raise(response, path=path)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class AsyncRequestExecutor:
|
|
52
|
+
def __init__(
|
|
53
|
+
self,
|
|
54
|
+
config: ClientConfig,
|
|
55
|
+
session_manager: SessionManager,
|
|
56
|
+
request_fn: Callable[..., Any],
|
|
57
|
+
) -> None:
|
|
58
|
+
self._config = config
|
|
59
|
+
self._session = session_manager
|
|
60
|
+
self._request = request_fn
|
|
61
|
+
|
|
62
|
+
async def ensure_session(self) -> str:
|
|
63
|
+
# Fast path for hot request loops: avoid full async synchronization when
|
|
64
|
+
# a non-expired token is already present in shared session state.
|
|
65
|
+
cached_state = self._session.state
|
|
66
|
+
if cached_state.token and not cached_state.is_expired(max_age=self._config.max_session_age):
|
|
67
|
+
return cached_state.token
|
|
68
|
+
|
|
69
|
+
state = await self._session.ensure_async()
|
|
70
|
+
if not state.token:
|
|
71
|
+
raise SessionExpiredError("Session not established")
|
|
72
|
+
return state.token
|
|
73
|
+
|
|
74
|
+
def invalidate_session(self) -> None:
|
|
75
|
+
self._session.invalidate()
|
|
76
|
+
|
|
77
|
+
async def request(
|
|
78
|
+
self,
|
|
79
|
+
method: str,
|
|
80
|
+
path: str,
|
|
81
|
+
*,
|
|
82
|
+
params: Optional[dict] = None,
|
|
83
|
+
data: Any = None,
|
|
84
|
+
) -> ResponseEnvelope[Any]:
|
|
85
|
+
normalized_params = normalize_query_params(params)
|
|
86
|
+
token = await self.ensure_session()
|
|
87
|
+
response = await self._request(method, path, token=token, params=normalized_params, data=data)
|
|
88
|
+
if should_retry_auth(response.status_code):
|
|
89
|
+
self.invalidate_session()
|
|
90
|
+
token = await self.ensure_session()
|
|
91
|
+
response = await self._request(method, path, token=token, params=normalized_params, data=data)
|
|
92
|
+
return to_envelope_or_raise(response, path=path)
|
SymfWebAPI/operations.py
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"""Operation descriptors and shared invocation helpers for generated controllers."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
import inspect
|
|
7
|
+
from typing import Any, Awaitable, Callable, Optional, TypeVar, overload, cast
|
|
8
|
+
|
|
9
|
+
from pydantic import TypeAdapter
|
|
10
|
+
|
|
11
|
+
from .protocols import (
|
|
12
|
+
AsyncInvokerProtocol,
|
|
13
|
+
AsyncRequestProtocol,
|
|
14
|
+
SyncInvokerProtocol,
|
|
15
|
+
SyncRequestProtocol,
|
|
16
|
+
)
|
|
17
|
+
from .response import ResponseEnvelope
|
|
18
|
+
|
|
19
|
+
T = TypeVar("T")
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@dataclass(frozen=True, slots=True)
|
|
23
|
+
class OperationSpec:
|
|
24
|
+
"""Descriptor of one API endpoint call with response parser."""
|
|
25
|
+
|
|
26
|
+
method: str
|
|
27
|
+
path: str
|
|
28
|
+
parser: Callable[[ResponseEnvelope[Any]], ResponseEnvelope[Any]]
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def parse_with_adapter(envelope: ResponseEnvelope[Any], adapter: TypeAdapter[T]) -> ResponseEnvelope[T]:
|
|
32
|
+
if envelope.model is not None:
|
|
33
|
+
model = cast(T, envelope.model)
|
|
34
|
+
else:
|
|
35
|
+
model = adapter.validate_json(envelope.raw_text or "null")
|
|
36
|
+
return ResponseEnvelope(
|
|
37
|
+
model=model,
|
|
38
|
+
status=envelope.status,
|
|
39
|
+
headers=envelope.headers,
|
|
40
|
+
raw_text=envelope.raw_text,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def parse_none(envelope: ResponseEnvelope[Any]) -> ResponseEnvelope[None]:
|
|
45
|
+
return ResponseEnvelope(
|
|
46
|
+
model=None,
|
|
47
|
+
status=envelope.status,
|
|
48
|
+
headers=envelope.headers,
|
|
49
|
+
raw_text=envelope.raw_text,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@overload
|
|
54
|
+
def invoke_operation(
|
|
55
|
+
api: SyncInvokerProtocol,
|
|
56
|
+
operation: OperationSpec,
|
|
57
|
+
*,
|
|
58
|
+
params: Optional[dict] = None,
|
|
59
|
+
data: Any = None,
|
|
60
|
+
) -> ResponseEnvelope[Any]: ...
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@overload
|
|
64
|
+
def invoke_operation(
|
|
65
|
+
api: AsyncInvokerProtocol,
|
|
66
|
+
operation: OperationSpec,
|
|
67
|
+
*,
|
|
68
|
+
params: Optional[dict] = None,
|
|
69
|
+
data: Any = None,
|
|
70
|
+
) -> Awaitable[ResponseEnvelope[Any]]: ...
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@overload
|
|
74
|
+
def invoke_operation(
|
|
75
|
+
api: SyncRequestProtocol,
|
|
76
|
+
operation: OperationSpec,
|
|
77
|
+
*,
|
|
78
|
+
params: Optional[dict] = None,
|
|
79
|
+
data: Any = None,
|
|
80
|
+
) -> ResponseEnvelope[Any]: ...
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
@overload
|
|
84
|
+
def invoke_operation(
|
|
85
|
+
api: AsyncRequestProtocol,
|
|
86
|
+
operation: OperationSpec,
|
|
87
|
+
*,
|
|
88
|
+
params: Optional[dict] = None,
|
|
89
|
+
data: Any = None,
|
|
90
|
+
) -> Awaitable[ResponseEnvelope[Any]]: ...
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def invoke_operation(
|
|
94
|
+
api: object,
|
|
95
|
+
operation: OperationSpec,
|
|
96
|
+
*,
|
|
97
|
+
params: Optional[dict] = None,
|
|
98
|
+
data: Any = None,
|
|
99
|
+
) -> ResponseEnvelope[Any] | Awaitable[ResponseEnvelope[Any]]:
|
|
100
|
+
invoker = getattr(api, "invoke", None)
|
|
101
|
+
if callable(invoker):
|
|
102
|
+
return invoker(operation, params=params, data=data)
|
|
103
|
+
|
|
104
|
+
requester = getattr(api, "request", None)
|
|
105
|
+
if not callable(requester):
|
|
106
|
+
raise TypeError("api must expose either invoke(...) or request(...)")
|
|
107
|
+
|
|
108
|
+
result = requester(operation.method, operation.path, params=params, data=data)
|
|
109
|
+
if inspect.isawaitable(result):
|
|
110
|
+
async def _resolve() -> ResponseEnvelope[Any]:
|
|
111
|
+
envelope = await cast(Awaitable[ResponseEnvelope[Any]], result)
|
|
112
|
+
return operation.parser(envelope)
|
|
113
|
+
|
|
114
|
+
return _resolve()
|
|
115
|
+
|
|
116
|
+
return operation.parser(cast(ResponseEnvelope[Any], result))
|
SymfWebAPI/protocols.py
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"""Structural protocols used by generated controllers and runtime builders."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING, Any, Awaitable, Optional, Protocol, TypeVar
|
|
6
|
+
|
|
7
|
+
from .response import ResponseEnvelope
|
|
8
|
+
from .session import SessionBackend
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from .operations import OperationSpec
|
|
12
|
+
|
|
13
|
+
T = TypeVar("T")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class SyncRequestProtocol(Protocol):
|
|
17
|
+
def request(
|
|
18
|
+
self,
|
|
19
|
+
method: str,
|
|
20
|
+
path: str,
|
|
21
|
+
*,
|
|
22
|
+
params: Optional[dict] = None,
|
|
23
|
+
data: Any = None,
|
|
24
|
+
) -> ResponseEnvelope[Any]:
|
|
25
|
+
...
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class AsyncRequestProtocol(Protocol):
|
|
29
|
+
async def request(
|
|
30
|
+
self,
|
|
31
|
+
method: str,
|
|
32
|
+
path: str,
|
|
33
|
+
*,
|
|
34
|
+
params: Optional[dict] = None,
|
|
35
|
+
data: Any = None,
|
|
36
|
+
) -> ResponseEnvelope[Any]:
|
|
37
|
+
...
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class SyncInvokerProtocol(Protocol):
|
|
41
|
+
def invoke(
|
|
42
|
+
self,
|
|
43
|
+
operation: "OperationSpec[T]",
|
|
44
|
+
*,
|
|
45
|
+
params: Optional[dict] = None,
|
|
46
|
+
data: Any = None,
|
|
47
|
+
) -> ResponseEnvelope[T]:
|
|
48
|
+
...
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class AsyncInvokerProtocol(Protocol):
|
|
52
|
+
def invoke(
|
|
53
|
+
self,
|
|
54
|
+
operation: "OperationSpec[T]",
|
|
55
|
+
*,
|
|
56
|
+
params: Optional[dict] = None,
|
|
57
|
+
data: Any = None,
|
|
58
|
+
) -> Awaitable[ResponseEnvelope[T]]:
|
|
59
|
+
...
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class SyncTransportProtocol(SessionBackend, Protocol):
|
|
63
|
+
def request(
|
|
64
|
+
self,
|
|
65
|
+
method: str,
|
|
66
|
+
path: str,
|
|
67
|
+
*,
|
|
68
|
+
token: str,
|
|
69
|
+
params: Optional[dict] = None,
|
|
70
|
+
data: Any = None,
|
|
71
|
+
) -> Any:
|
|
72
|
+
...
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class AsyncTransportProtocol(SessionBackend, Protocol):
|
|
76
|
+
async def request(
|
|
77
|
+
self,
|
|
78
|
+
method: str,
|
|
79
|
+
path: str,
|
|
80
|
+
*,
|
|
81
|
+
token: str,
|
|
82
|
+
params: Optional[dict] = None,
|
|
83
|
+
data: Any = None,
|
|
84
|
+
) -> Any:
|
|
85
|
+
...
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""Shared request policy and response mapping for sync/async clients."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from datetime import date, datetime
|
|
6
|
+
from typing import Any, Optional
|
|
7
|
+
|
|
8
|
+
from .errors import WebAPIHttpError
|
|
9
|
+
from .response import ResponseEnvelope
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def normalize_query_value(value: Any) -> Any:
|
|
13
|
+
if isinstance(value, datetime):
|
|
14
|
+
return value.isoformat()
|
|
15
|
+
if isinstance(value, date):
|
|
16
|
+
return value.isoformat()
|
|
17
|
+
if isinstance(value, dict):
|
|
18
|
+
return {key: normalize_query_value(item) for key, item in value.items()}
|
|
19
|
+
if isinstance(value, (list, tuple)):
|
|
20
|
+
return [normalize_query_value(item) for item in value]
|
|
21
|
+
return value
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def normalize_query_params(params: Optional[dict]) -> Optional[dict]:
|
|
25
|
+
if params is None:
|
|
26
|
+
return None
|
|
27
|
+
return {key: normalize_query_value(value) for key, value in params.items()}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def should_retry_auth(status_code: int) -> bool:
|
|
31
|
+
return status_code == 401
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def to_envelope_or_raise(response: Any, *, path: str) -> ResponseEnvelope[Any]:
|
|
35
|
+
if 200 <= response.status_code < 300:
|
|
36
|
+
text = response.text
|
|
37
|
+
return ResponseEnvelope(
|
|
38
|
+
model=None,
|
|
39
|
+
status=response.status_code,
|
|
40
|
+
headers=dict(response.headers),
|
|
41
|
+
raw_text=text,
|
|
42
|
+
)
|
|
43
|
+
raise WebAPIHttpError(response.status_code, endpoint=path, response_text=response.text)
|
SymfWebAPI/response.py
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""Response container shared by async/sync controllers."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import Generic, Optional, TypeVar
|
|
7
|
+
|
|
8
|
+
T = TypeVar("T")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass(slots=True)
|
|
12
|
+
class ResponseEnvelope(Generic[T]):
|
|
13
|
+
model: Optional[T]
|
|
14
|
+
status: int
|
|
15
|
+
headers: dict
|
|
16
|
+
raw_text: Optional[str] = None
|
|
17
|
+
|
|
18
|
+
def unwrap(self) -> T:
|
|
19
|
+
if self.model is None:
|
|
20
|
+
raise ValueError("Response has no model")
|
|
21
|
+
return self.model
|