diff --git a/.speakeasy/gen.lock b/.speakeasy/gen.lock index 774e937..4555b9b 100644 --- a/.speakeasy/gen.lock +++ b/.speakeasy/gen.lock @@ -1,29 +1,29 @@ lockVersion: 2.0.0 id: 0c8d1667-2710-4860-aee3-7d221dbc0a60 management: - docChecksum: be5c022f6de13e02a50df9b4c318826c + docChecksum: 260025ff02294167140cc43bce211de2 docVersion: 1.0.0 - speakeasyVersion: 1.771.0 - generationVersion: 2.893.0 - releaseVersion: 1.2.0 - configChecksum: c4c3331ffaa1803aa7003ee9cf596fc7 + speakeasyVersion: 1.784.0 + generationVersion: 2.911.0 + releaseVersion: 1.3.0 + configChecksum: c05e65bfebb246dd7bde95e549f3a7f1 repoURL: https://github.com/kombohq/python-sdk.git installationURL: https://github.com/kombohq/python-sdk.git published: true persistentEdits: - generation_id: 8376918f-2882-4652-8c06-6e1d5686c1dd - pristine_commit_hash: bf630fb39ba1f183d8d4111c242004c3338bff3b - pristine_tree_hash: ed6ab239daa1155eeee85e35248e749660a23339 + generation_id: 7c5ec979-d0fe-4524-b58b-e19924945593 + pristine_commit_hash: f316d222379d58ffce0846e4d2a88ae345d9b811 + pristine_tree_hash: 94c6144e0db35a383fe74109d90c3f3edae2bce5 features: python: additionalDependencies: 1.1.0 constsAndDefaults: 1.0.7 - core: 6.0.24 + core: 6.0.30 defaultEnabledRetries: 0.2.0 deprecations: 3.0.2 enumUnions: 0.1.1 envVarSecurityUsage: 0.3.3 - errors: 3.3.6 + errors: 3.4.2 flatRequests: 1.0.1 flattening: 3.1.1 globalSecurity: 3.0.7 @@ -34,17 +34,17 @@ features: groups: 3.0.1 hiddenGlobals: 1.0.0 ignores: 3.0.1 - methodArguments: 1.1.0 + methodArguments: 1.1.1 nameOverrides: 3.0.3 nullables: 1.0.2 openEnums: 1.0.4 operationTimeout: 0.3.1 pagination: 3.0.10 responseFormat: 1.1.0 - retries: 3.0.5 - sdkHooks: 1.2.1 + retries: 3.0.7 + sdkHooks: 1.2.2 serverIDs: 3.0.0 - unions: 3.1.5 + unions: 3.1.6 webhooks: 2.0.0 trackedFiles: .gitattributes: @@ -1885,8 +1885,8 @@ trackedFiles: pristine_git_object: 95d7af043b98494373f18f3ceae6a530e7e4af71 docs/models/integrationtool.md: id: 59f82e2d180c - last_write_checksum: sha1:155c697eca020f2addbea35baa181b5a406813aa - pristine_git_object: a3fdc3a9b931b0b8dee0bd1eac2b0002da6b52b7 + last_write_checksum: sha1:5122196499a34c56620addcea23df7335a9248df + pristine_git_object: 47d21b7cc30fe71e113787e0f310ae7d4159b150 docs/models/internal/globals.md: id: 9c173b87f41f last_write_checksum: sha1:3969d44e1ad9258f466c40b241681eb82c1ac29a @@ -2463,6 +2463,10 @@ trackedFiles: id: ba2ad2a72373 last_write_checksum: sha1:0be2bc26f3b7b42af19599230742e52427622836 pristine_git_object: 6e91e32d74176c28dbc8e064fedff4633782045e + docs/models/postatscandidatesrequestbodyaktiv.md: + id: b1a9b6838577 + last_write_checksum: sha1:548881e6b8e795dab7bf3684a0c815f7fe74caba + pristine_git_object: 8062598746c2603b44d0f94fe3541d37741c0d38 docs/models/postatscandidatesrequestbodyanswer.md: id: 34fa4def625e last_write_checksum: sha1:9421c6b15946056ae3e7ed55bd0d265e900e2b4f @@ -2521,8 +2525,8 @@ trackedFiles: pristine_git_object: 825cc4294186d38f956660ceb702f343bc8fb643 docs/models/postatscandidatesrequestbodycovetorestcandidate.md: id: 3da95f5ce314 - last_write_checksum: sha1:8bd175ad12a83e7bcf5826603f356d4b262d52d7 - pristine_git_object: 95eb78e5cff47ac19f472a82bddeadddce682290 + last_write_checksum: sha1:4cc2fb5a3c919b7932d2998bdc04b38f0c58ea51 + pristine_git_object: c6ca9a888d9e8b2c89afce97516b7598fe3c2b85 docs/models/postatscandidatesrequestbodydegreereference.md: id: 80f9c5593c46 last_write_checksum: sha1:57b4c36ae98e1a1ba2ba3189ccac93dca297457d @@ -3063,6 +3067,10 @@ trackedFiles: id: 13103fe3fd19 last_write_checksum: sha1:5e7daafbc534116496a45c46619daeec1332d335 pristine_git_object: 022677d19d941a59776acfaba3d052840ecbbd07 + docs/models/postatsjobsjobidapplicationsrequestbodyaktiv.md: + id: b004afc8c1c0 + last_write_checksum: sha1:366937ba3b4a58852d1b485b548a49a1d5a1f76d + pristine_git_object: 23770fa4d78810c2a7e018cb6daae97a19ca2f06 docs/models/postatsjobsjobidapplicationsrequestbodyanswer.md: id: 8ceefc23692d last_write_checksum: sha1:df5dc671e8e16b9269640c4181e3bf18da23bbef @@ -3117,8 +3125,8 @@ trackedFiles: pristine_git_object: 806f3e2cbf4f21c6cc3958a22fe3dbb9d152e23a docs/models/postatsjobsjobidapplicationsrequestbodycovetorestcandidate.md: id: b6369fa618d1 - last_write_checksum: sha1:9b3a77793f8e3165dcfc691d7d4627b10c829dfc - pristine_git_object: 5cfee8656170c245508522e7629fc67c6a9dee96 + last_write_checksum: sha1:d27d8d36d275c39f5d58173891ed2c903a171d29 + pristine_git_object: 6eacb69599d87903add129ef984d0afb05d66f96 docs/models/postatsjobsjobidapplicationsrequestbodydegreereference.md: id: 0691556b8773 last_write_checksum: sha1:e4fd8479dfb23366dfc26024b82a16f9472aa8d0 @@ -4201,8 +4209,8 @@ trackedFiles: pristine_git_object: cb268794ca5a2389305a908323d1585a0c88d9c4 docs/sdks/general/README.md: id: ce0ada6fa2e1 - last_write_checksum: sha1:fc2bcb3eaca98e61519628c732230ea822daa573 - pristine_git_object: c2b2f9a2d73719786c624ce68468f7e5d0db94f7 + last_write_checksum: sha1:1f2e17b4926d88a04a474d8e6d0585f244ddca72 + pristine_git_object: c67e71c9bc23da77496cecf654920b570501c255 docs/sdks/hris/README.md: id: 0baa868a038c last_write_checksum: sha1:f7f2b3d812a1b1b4097d81977cda0a7384585325 @@ -4217,8 +4225,8 @@ trackedFiles: pristine_git_object: f456032107a9387ba6c98afd1c981df2f4b3d636 pyproject.toml: id: 5d07e7d72637 - last_write_checksum: sha1:580500cc0af793786031feb5fab582372a8f9b1a - pristine_git_object: 9af6c441766a04c799f00e85cb771e1c8479df69 + last_write_checksum: sha1:368141102506b68ad75f3b61ca37818eb0f62ea4 + pristine_git_object: f110a99e66b20854858eecfd7cda4ce5360b1f7b scripts/prepare_readme.py: id: e0c5957a6035 last_write_checksum: sha1:b6ad6f0515a952d7cb052befddb6a117d4f627d8 @@ -4245,16 +4253,16 @@ trackedFiles: pristine_git_object: e589e541e5fc70d336de44780721f301d754ed72 src/kombo/_version.py: id: 45cf440ad1df - last_write_checksum: sha1:195c140de357d9f060a7ff64bc953de837f17b5e - pristine_git_object: e8690c6b73fdf6fdfc80750a56674d6616dcb68c + last_write_checksum: sha1:b4e0137a67b04b958c736241e84f233fba7dc969 + pristine_git_object: 30b1e8e8918a1a634e85d91f59226b9274b903b3 src/kombo/assessment.py: id: aec6e8a7589f - last_write_checksum: sha1:8d496d8f3b781a727642d4b4f05b598a2eb73312 - pristine_git_object: 3ce2821942baa15829f5ffa13da682d1c1459678 + last_write_checksum: sha1:329b48ae9457433f57e2f2d369ccbf6d9d49fd77 + pristine_git_object: 35db2f3cab77646befa56b1c54c68578bd80547f src/kombo/ats.py: id: a9839762f5c3 - last_write_checksum: sha1:692427a4775843bded62cc15174c702a7c304501 - pristine_git_object: 4f7b1fd0bb79d601b5ba82ea5b68b56411519c18 + last_write_checksum: sha1:7949bf6b71c589d6073b980a88db5fc379562b79 + pristine_git_object: 7ecf321f14095ebc951e6dec4f420df56f812737 src/kombo/basesdk.py: id: 8f30a0bd36ff last_write_checksum: sha1:f7cceecb507a387fd50740b9f4cd3cfe5cb3451b @@ -4297,20 +4305,20 @@ trackedFiles: pristine_git_object: 16ac2977e80b6eabe4020aa8a21dd28e83032f9a src/kombo/general.py: id: 107ecb9f3651 - last_write_checksum: sha1:ab187ee80dce4bc01acfd1c0f198d222c2f90152 - pristine_git_object: 300563cfc39258f4cef7d0f239783237c3ddf106 + last_write_checksum: sha1:68eff6df77f159978a5eb359740c375ea71161c2 + pristine_git_object: 0fa0989e884785221423b2b129c3d1ba479ddba6 src/kombo/hris.py: id: 9ba1b37ab10a - last_write_checksum: sha1:d1ca512354d793007457f28726e1328c33f4e07e - pristine_git_object: 8cd4b95a3689eaf1bb3a3b722dff73e155bd07e7 + last_write_checksum: sha1:d31b54af3d755e96499332399c7641a178e59b4a + pristine_git_object: 709aeed662250edee159b51ab369b06aaa361363 src/kombo/httpclient.py: id: 4e74c7821304 last_write_checksum: sha1:5e55338d6ee9f01ab648cad4380201a8a3da7dd7 pristine_git_object: 89560b566073785535643e694c112bedbd3db13d src/kombo/models/__init__.py: id: 45e6e8c7f07f - last_write_checksum: sha1:dfd0ef20f72098a755ffbba3d6c77a471a80f6e8 - pristine_git_object: be1fd21d250f0529d6d889f3c80d65d57aaff1ea + last_write_checksum: sha1:202e90805768dd8e9aba69c0e9b5e84b2c12031b + pristine_git_object: d25f8e8c3c15826dc3fee4585e403fa562cba22c src/kombo/models/assessmentorderreceivedwebhookpayload.py: id: 532c2db2ee93 last_write_checksum: sha1:a89544ec063f76ec1faa875bf51141a32963ef51 @@ -4773,8 +4781,8 @@ trackedFiles: pristine_git_object: 7a97ad39aca8886d0999a4573a69626c1bfc5cbb src/kombo/models/postatscandidatesrequestbody.py: id: ac6e98f043e9 - last_write_checksum: sha1:1c2a00a300c5ff1c41c1e229b27d12ffe151fe1c - pristine_git_object: 8b75b535aac4db5cc21e39e15b5741750f310f15 + last_write_checksum: sha1:d16a8de7664b303200e1e54e7e55604f23aaba69 + pristine_git_object: 10c979af1efc590bad89da93b81f8179975d9dbc src/kombo/models/postatsimporttrackedapplicationop.py: id: d36d9960022a last_write_checksum: sha1:e0aa98b306d9e4852785f10e40e97c34f084efef @@ -4797,16 +4805,16 @@ trackedFiles: pristine_git_object: 20ba13411c0885c7b43e5c4c0d6ae721b13f02e1 src/kombo/models/postatsjobsjobidapplicationsrequestbody.py: id: a451a5e6b515 - last_write_checksum: sha1:09db6b0487d91fec741b7ad576d7e4ea07f8d916 - pristine_git_object: 21542d5073ab790ad7230b4065c2f3ba1ef89a19 + last_write_checksum: sha1:8918091ab51b4d494cc6c18e365455df66067a21 + pristine_git_object: 09113eee9879092ca797921e9fbac75d683ae394 src/kombo/models/postconnectcreatelinkpositiveresponse.py: id: a3271239a82f last_write_checksum: sha1:db8f52f9bed614766c9bd4c0f1286ee5859b38f8 pristine_git_object: 91e8d75513c8015aeb3f8dd2e38e2ec090b0770c src/kombo/models/postconnectcreatelinkrequestbody.py: id: 8ae6871fd392 - last_write_checksum: sha1:af4e8bf4687b98a3060358158d7b05ef8c394b31 - pristine_git_object: c0cd102fdac772f321cdbbc75528a7f0a188f11e + last_write_checksum: sha1:4697f61723d07f24753c66a01f302f1acd04a4a1 + pristine_git_object: e0452b90e1f6cb25827446cf87f3510e99ef06af src/kombo/models/postforcesyncop.py: id: 695738b0e4fb last_write_checksum: sha1:4288d66c5efda40419ee3602e124d5186662a99e @@ -5033,8 +5041,8 @@ trackedFiles: pristine_git_object: faa268137bc01c9d08cfadc4797017db48747a96 src/kombo/types/base64fileinput.py: id: 70d02f7057ad - last_write_checksum: sha1:4780e893d3853b5a6e28d9a6ca3ee102ce0f502d - pristine_git_object: 25fc53989ed497649363f983219fc58705c8bf87 + last_write_checksum: sha1:1522687ae3398374c35710cad993a6e82b5ab99d + pristine_git_object: 862566fe2b1db830276b390e136e65090e5963d2 src/kombo/types/basemodel.py: id: fcedd4cc094d last_write_checksum: sha1:10d84aedeb9d35edfdadf2c3020caa1d24d8b584 @@ -5061,12 +5069,12 @@ trackedFiles: pristine_git_object: 3324e1bc2668c54c4d5f5a1a845675319757a828 src/kombo/utils/eventstreaming.py: id: 5014efc778bb - last_write_checksum: sha1:620d78a8b4e3b854e08d136e02e40a01a786bd70 - pristine_git_object: 3bdcd6d3d4fc772cb7f5fca8685dcdc8c85e13e8 + last_write_checksum: sha1:7d1dc68f8b48486ab646653aa05cc38752e1f912 + pristine_git_object: a8d4fe5cc88d3c7337339e1b36a61bbf7ca8c4eb src/kombo/utils/forms.py: id: 99d47e485fec - last_write_checksum: sha1:15fa7e9ab1611e062a9984cf06cb20969713d295 - pristine_git_object: f961e76beaf0a8b1fe0dda44754a74eebd3608e7 + last_write_checksum: sha1:a971cdb120ad3d416d296d5d0ad89e4808350a7f + pristine_git_object: fdf0dc9b2a67bca773eefe6b471498cccaa83424 src/kombo/utils/headers.py: id: d586650ae4bc last_write_checksum: sha1:7c6df233ee006332b566a8afa9ce9a245941d935 @@ -5089,16 +5097,16 @@ trackedFiles: pristine_git_object: 591415af8e64baa410627b507d2740afb5387d13 src/kombo/utils/retries.py: id: bc594ff11adc - last_write_checksum: sha1:471372f5c5d1dd5583239c9cf3c75f1b636e5d87 - pristine_git_object: af07d4e941007af4213c5ec9047ef8a2fca04e5e + last_write_checksum: sha1:3585b891142f30a597fbf7a2f0340700babef8e4 + pristine_git_object: ca7b59efebbbd9545744d0207ef42725c4cc5143 src/kombo/utils/security.py: id: acd4ded0aa8d last_write_checksum: sha1:c11eef495b6aaa249178c24c796940cc540b7a00 pristine_git_object: 42d8d78e9981eed7507670014d99588e27ab325a src/kombo/utils/serializers.py: id: 5d7d8c5e2d73 - last_write_checksum: sha1:61009f2e4ef6613a1a5af813fe020373dae5a492 - pristine_git_object: d2149f8b909cb96628db140ac3cddb1b1e981367 + last_write_checksum: sha1:7485f1425b0661fd84836186570df90207eec6af + pristine_git_object: 1031ed930bad5ece220cf7416a56c29f40f0588b src/kombo/utils/unmarshal_json_response.py: id: 78f7ac328026 last_write_checksum: sha1:e2ea836c8f9063fbf985278bb705dec1a077ca25 @@ -7714,7 +7722,7 @@ examples: default: application/json: {"status": "error", "error": {"code": "PLATFORM.RATE_LIMIT_EXCEEDED", "title": null, "message": "", "log_url": "https://married-yin.org/"}} examplesVersion: 1.0.2 -releaseNotes: "## Python SDK Changes:\n* `kombo.hris.get_employees()`: `error.code.enum(hris.staffing_entity_closed)` **Added** (Breaking ⚠️)\n* `kombo.hris.get_employee_form()`: \n * `request` **Changed** (Breaking ⚠️)\n * `error.code.enum(hris.staffing_entity_closed)` **Added** (Breaking ⚠️)\n* `kombo.hris.create_employee_with_form()`: \n * `request.staffing_entity_id` **Added**\n * `error.code.enum(hris.staffing_entity_closed)` **Added** (Breaking ⚠️)\n* `kombo.hris.add_employee_document()`: `error.code.enum(hris.staffing_entity_closed)` **Added** (Breaking ⚠️)\n* `kombo.hris.get_employee_document_categories()`: `error.code.enum(hris.staffing_entity_closed)` **Added** (Breaking ⚠️)\n* `kombo.hris.get_groups()`: `error.code.enum(hris.staffing_entity_closed)` **Added** (Breaking ⚠️)\n* `kombo.hris.get_employments()`: `error.code.enum(hris.staffing_entity_closed)` **Added** (Breaking ⚠️)\n* `kombo.hris.get_locations()`: `error.code.enum(hris.staffing_entity_closed)` **Added** (Breaking ⚠️)\n* `kombo.hris.get_absence_types()`: `error.code.enum(hris.staffing_entity_closed)` **Added** (Breaking ⚠️)\n* `kombo.hris.get_time_off_balances()`: `error.code.enum(hris.staffing_entity_closed)` **Added** (Breaking ⚠️)\n* `kombo.hris.get_absences()`: `error.code.enum(hris.staffing_entity_closed)` **Added** (Breaking ⚠️)\n* `kombo.hris.create_absence()`: `error.code.enum(hris.staffing_entity_closed)` **Added** (Breaking ⚠️)\n* `kombo.hris.delete_absence()`: `error.code.enum(hris.staffing_entity_closed)` **Added** (Breaking ⚠️)\n* `kombo.hris.get_legal_entities()`: `error.code.enum(hris.staffing_entity_closed)` **Added** (Breaking ⚠️)\n* `kombo.hris.get_timesheets()`: `error.code.enum(hris.staffing_entity_closed)` **Added** (Breaking ⚠️)\n* `kombo.hris.get_performance_review_cycles()`: `error.code.enum(hris.staffing_entity_closed)` **Added** (Breaking ⚠️)\n* `kombo.hris.get_performance_reviews()`: `error.code.enum(hris.staffing_entity_closed)` **Added** (Breaking ⚠️)\n* `kombo.hris.get_staffing_entities()`: `error.code.enum(hris.staffing_entity_closed)` **Added** (Breaking ⚠️)\n* `kombo.ats.create_candidate()`: \n * `request.remote_fields.covetorest.candidate.status` **Added**\n* `kombo.ats.create_application()`: \n * `request.remote_fields.covetorest.candidate.status` **Added**\n* `kombo.assessment.update_order_result()`: \n * `request.remote_fields.workday` **Added**\n* `kombo.connect.create_connection_link()`: `request.integration_tool` **Changed**\n" +releaseNotes: "## Python SDK Changes:\n* `kombo.ats.create_candidate()`: \n * `request.remote_fields.covetorest.candidate.aktiv` **Added**\n* `kombo.ats.create_application()`: \n * `request.remote_fields.covetorest.candidate.aktiv` **Added**\n* `kombo.connect.create_connection_link()`: `request.integration_tool` **Changed**\n" generatedFiles: - .gitattributes - .vscode/settings.json diff --git a/.speakeasy/gen.yaml b/.speakeasy/gen.yaml index aa0d58c..f782145 100644 --- a/.speakeasy/gen.yaml +++ b/.speakeasy/gen.yaml @@ -31,7 +31,7 @@ generation: generateNewTests: true skipResponseBodyAssertions: false python: - version: 1.2.0 + version: 1.3.0 additionalDependencies: dev: inline-snapshot: '>=0.13.0' @@ -53,6 +53,10 @@ python: description: The official Python SDK for the Kombo Unified API enableCustomCodeRegions: false enumFormat: union + errorSchemaValidation: true + eventStreamClassNames: + async: EventStreamAsync + sync: EventStream fixFlags: asyncPaginationSep2025: true conflictResistantModelImportsFeb2026: false @@ -72,6 +76,7 @@ python: webhooks: "" inferUnionDiscriminators: true inputModelSuffix: input + inputTypedDictSuffix: TypedDict legacyPyright: false license: "" maxMethodParams: 999 @@ -89,6 +94,7 @@ python: pytestTimeout: 0 rawResponseHelpers: false responseFormat: flat + responseSchemaValidation: true sseFlatResponse: false templateVersion: v2 useAsyncHooks: false diff --git a/.speakeasy/workflow.lock b/.speakeasy/workflow.lock index 7931567..d87e0be 100644 --- a/.speakeasy/workflow.lock +++ b/.speakeasy/workflow.lock @@ -1,9 +1,9 @@ -speakeasyVersion: 1.771.0 +speakeasyVersion: 1.784.0 sources: kombo-prepared-spec: sourceNamespace: kombo-api - sourceRevisionDigest: sha256:26400cad28773013cca90a0c587483fb4d201d1807badde6f783b44a77d0a550 - sourceBlobDigest: sha256:b5916e82d018ffec07eae810ab9a36840e04c9ca308f46d447a48f5cf4899b59 + sourceRevisionDigest: sha256:0b7c2e367cb1cdb42ceb4d8b9f85511f761393c66252122ce09efc13b5cd3ed2 + sourceBlobDigest: sha256:1d7bc8e3398742fffa43a0ada21817cc740c99d509d9434af5012515cb9ae938 tags: - latest - 1.0.0 @@ -11,10 +11,10 @@ targets: kombo-python: source: kombo-prepared-spec sourceNamespace: kombo-api - sourceRevisionDigest: sha256:26400cad28773013cca90a0c587483fb4d201d1807badde6f783b44a77d0a550 - sourceBlobDigest: sha256:b5916e82d018ffec07eae810ab9a36840e04c9ca308f46d447a48f5cf4899b59 + sourceRevisionDigest: sha256:0b7c2e367cb1cdb42ceb4d8b9f85511f761393c66252122ce09efc13b5cd3ed2 + sourceBlobDigest: sha256:1d7bc8e3398742fffa43a0ada21817cc740c99d509d9434af5012515cb9ae938 codeSamplesNamespace: kombo-api-python-code-samples - codeSamplesRevisionDigest: sha256:8c0d04c52852071bedbdec19d6148e3bf239304c7d5bd5a38ec1591a9ee58772 + codeSamplesRevisionDigest: sha256:d298f7465906d0caf75af33252c8215e6b5ddd3310600b6752ec21d737bcdd68 workflow: workflowVersion: 1.0.0 speakeasyVersion: latest diff --git a/RELEASES.md b/RELEASES.md index 8a1f8ef..609c211 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -218,4 +218,14 @@ Based on: ### Generated - [python v1.2.0] . ### Releases -- [PyPI v1.2.0] https://pypi.org/project/kombo/1.2.0 - . \ No newline at end of file +- [PyPI v1.2.0] https://pypi.org/project/kombo/1.2.0 - . + +## 2026-06-21 01:00:46 +### Changes +Based on: +- OpenAPI Doc +- Speakeasy CLI 1.784.0 (2.911.0) https://github.com/speakeasy-api/speakeasy +### Generated +- [python v1.3.0] . +### Releases +- [PyPI v1.3.0] https://pypi.org/project/kombo/1.3.0 - . \ No newline at end of file diff --git a/docs/models/integrationtool.md b/docs/models/integrationtool.md index a3fdc3a..47d21b7 100644 --- a/docs/models/integrationtool.md +++ b/docs/models/integrationtool.md @@ -123,6 +123,7 @@ value: IntegrationTool = "workday" - `"logicmelon"` - `"loxo"` - `"kula"` +- `"pageup"` - `"workdaycustomreport"` - `"workdaycustomreportsftp"` - `"ukgprowfm"` @@ -204,6 +205,7 @@ value: IntegrationTool = "workday" - `"sftpfetch"` - `"360learning"` - `"talentlms"` +- `"docebo"` - `"udemy"` - `"linkedinlearning"` - `"moodle"` diff --git a/docs/models/postatscandidatesrequestbodyaktiv.md b/docs/models/postatscandidatesrequestbodyaktiv.md new file mode 100644 index 0000000..8062598 --- /dev/null +++ b/docs/models/postatscandidatesrequestbodyaktiv.md @@ -0,0 +1,16 @@ +# PostAtsCandidatesRequestBodyAktiv + +Whether the candidate is created as active (`Ja`) or inactive (`Nein`) in Coveto. If omitted, Coveto applies its default (active). + +## Example Usage + +```python +from kombo.models import PostAtsCandidatesRequestBodyAktiv +value: PostAtsCandidatesRequestBodyAktiv = "Ja" +``` + + +## Values + +- `"Ja"` +- `"Nein"` diff --git a/docs/models/postatscandidatesrequestbodycovetorestcandidate.md b/docs/models/postatscandidatesrequestbodycovetorestcandidate.md index 95eb78e..c6ca9a8 100644 --- a/docs/models/postatscandidatesrequestbodycovetorestcandidate.md +++ b/docs/models/postatscandidatesrequestbodycovetorestcandidate.md @@ -8,4 +8,5 @@ Additional candidate fields that will be passed to the Coveto candidate creation | Field | Type | Required | Description | | ------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | | `mandant` | *Optional[float]* | :heavy_minus_sign: | The mandant field for the candidate in Coveto. | -| `status` | *Optional[int]* | :heavy_minus_sign: | The numeric status ID to assign to the candidate on creation in Coveto. Refer to your Coveto `/bewerber-status` endpoint for available IDs. | \ No newline at end of file +| `status` | *Optional[int]* | :heavy_minus_sign: | The numeric status ID to assign to the candidate on creation in Coveto. Refer to your Coveto `/bewerber-status` endpoint for available IDs. | +| `aktiv` | [Optional[models.PostAtsCandidatesRequestBodyAktiv]](../models/postatscandidatesrequestbodyaktiv.md) | :heavy_minus_sign: | Whether the candidate is created as active (`Ja`) or inactive (`Nein`) in Coveto. If omitted, Coveto applies its default (active). | \ No newline at end of file diff --git a/docs/models/postatsjobsjobidapplicationsrequestbodyaktiv.md b/docs/models/postatsjobsjobidapplicationsrequestbodyaktiv.md new file mode 100644 index 0000000..23770fa --- /dev/null +++ b/docs/models/postatsjobsjobidapplicationsrequestbodyaktiv.md @@ -0,0 +1,16 @@ +# PostAtsJobsJobIDApplicationsRequestBodyAktiv + +Whether the candidate is created as active (`Ja`) or inactive (`Nein`) in Coveto. If omitted, Coveto applies its default (active). + +## Example Usage + +```python +from kombo.models import PostAtsJobsJobIDApplicationsRequestBodyAktiv +value: PostAtsJobsJobIDApplicationsRequestBodyAktiv = "Ja" +``` + + +## Values + +- `"Ja"` +- `"Nein"` diff --git a/docs/models/postatsjobsjobidapplicationsrequestbodycovetorestcandidate.md b/docs/models/postatsjobsjobidapplicationsrequestbodycovetorestcandidate.md index 5cfee86..6eacb69 100644 --- a/docs/models/postatsjobsjobidapplicationsrequestbodycovetorestcandidate.md +++ b/docs/models/postatsjobsjobidapplicationsrequestbodycovetorestcandidate.md @@ -8,4 +8,5 @@ Additional candidate fields that will be passed to the Coveto candidate creation | Field | Type | Required | Description | | ------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | | `mandant` | *Optional[float]* | :heavy_minus_sign: | The mandant field for the candidate in Coveto. | -| `status` | *Optional[int]* | :heavy_minus_sign: | The numeric status ID to assign to the candidate on creation in Coveto. Refer to your Coveto `/bewerber-status` endpoint for available IDs. | \ No newline at end of file +| `status` | *Optional[int]* | :heavy_minus_sign: | The numeric status ID to assign to the candidate on creation in Coveto. Refer to your Coveto `/bewerber-status` endpoint for available IDs. | +| `aktiv` | [Optional[models.PostAtsJobsJobIDApplicationsRequestBodyAktiv]](../models/postatsjobsjobidapplicationsrequestbodyaktiv.md) | :heavy_minus_sign: | Whether the candidate is created as active (`Ja`) or inactive (`Nein`) in Coveto. If omitted, Coveto applies its default (active). | \ No newline at end of file diff --git a/docs/sdks/general/README.md b/docs/sdks/general/README.md index c2b2f9a..c67e71c 100644 --- a/docs/sdks/general/README.md +++ b/docs/sdks/general/README.md @@ -189,14 +189,15 @@ To get started, please pick the relevant API (some tools provide multiple to due |d.vinci admin|`dvinciadmin/rest-api`|[DVinci REST API](https://static.dvinci-easy.com/files/d.vinci%20rest-api.html).| |d.vinci|`dvinci/apply-api`|The [DVinci Apply API](https://static.dvinci-easy.com/files/d.vinci%20application-apply-api.html). All requests are authenticated by Kombo and use `https://\{dvinci_domain\}/p/\{portal_path\}/` as the base URL.| |d.vinci|`dvinci/rest-api`|The [DVinci REST API](https://static.dvinci-easy.com/files/d.vinci%20rest-api.html). All requests are authenticated by Kombo and use `https://\{dvinci_domain\}/restApi/` as the base URL.| -|DATEV LAUDS|`datevlauds/lauds`|DATEV's [hr-exchange](https://developer.datev.de/de/product-detail/hr-exchange/1.0.0/overview). We automatically authenticate all requests and use `https://hr-exchange.api.datev.de/\{platform|platform-sandbox\}/v1/clients/\{client-id\}` as the base URL.| |DATEV LODAS|`datev/eau`|DATEV's [eau](https://developer.datev.de/en/product-detail/eau-api/1.0.0/overview) API. We automatically authenticate all requests and use `https://eau.api.datev.de/\{platform|platform-sandbox\}/v1/clients/\{client-id\}/` as the base URL.| +|DATEV Lohnaustauschdatenservice|`datevlauds/lauds`|DATEV's [hr-exchange](https://developer.datev.de/de/product-detail/hr-exchange/1.0.0/overview). We automatically authenticate all requests and use `https://hr-exchange.api.datev.de/\{platform|platform-sandbox\}/v1/clients/\{client-id\}` as the base URL.| |DATEV|`datevhr/eau`|DATEV's [eau](https://developer.datev.de/en/product-detail/eau-api/1.0.0/overview) API. We automatically authenticate all requests and use `https://eau.api.datev.de/\{platform|platform-sandbox\}/v1/clients/\{client-id\}/` as the base URL.| |DATEV|`datevhr/hr-exports`|DATEV's [hr-exports](https://developer.datev.de/en/product-detail/hr-exports/1.0.0/overview). We automatically authenticate all requests and use `https://hr-exports.api.datev.de/\{platform|platform-sandbox\}/v1/clients/\{client-id\}` as the base URL.| |DATEV|`datevhr/hr:payrollreports`|DATEV's [hr:payrollreports](https://developer.datev.de/en/product-detail/hr-payrollreports/2.0.0/overview) API. We automatically authenticate all requests and use `https://hr-payrollreports.api.datev.de/\{platform|platform-sandbox\}/v1/clients/\{client-id\}/` as the base URL.| |Dayforce|`dayforce/V1`|[Dayforce's API](https://developers.dayforce.com/Build/Home.aspx). We automatically authenticate all requests and use `\{\{baseUrl\}\}/Api/\{\{clientNamespace\}\}/V1` as the base URL| |Deel|`deel/api`|Deel's [API](https://developer.deel.com/reference/). We automatically authenticate all requests using the provided credentials and use `https://\{api_domain\}/rest` as the base URL.| |Digital Recruiters|`digitalrecruiters/api`|Cegid Digital Recruiters [Talent Acquisition API](https://cegid-hr-developers.talentsoft.net/docs/tutorial-basics/Talent%20Acquisition/Getting%20Started). We automatically authenticate all requests by replacing `:token` in the request URL with your configured access token and use your configured Digital Recruiters domain as the base URL.| +|Docebo|`docebo/api`|Docebo [API](https://developer.docebo.com). We automatically handle authentication and use `https://\{subdomain\}.docebosaas.com` as the base URL.| |Eightfold|`eightfold/api`|Eightfold's [API](https://apidocs.eightfold.ai/). We automatically authenticate all requests and use `https://apiv2.\{region\}/api/v2/core/` as the base URL.| |Employment Hero|`employmenthero/default`|EmploymentHero [API](https://developer.employmenthero.com/api-references/#icon-book-open-introduction). We automatically authenticate all requests using the credentials supplied by the customer and use `https://api.employmenthero.com/api` as the base URL.| |Eploy|`eploy/api`|Eploy's [API](https://www.eploy.com/resources/developers/api-documentation/). We automatically authenticate all requests. The base URL is `https://\{hostname\}/api`, where `\{hostname\}` is either `\{subdomain\}.eploy.net` or your full custom hostname when applicable.| @@ -277,6 +278,7 @@ To get started, please pick the relevant API (some tools provide multiple to due |Oracle Recruiting Cloud|`oraclerecruiting/rest`|[Oracles's REST API](https://docs.oracle.com/en/cloud/saas/human-resources/24d/farws/rest-endpoints.html). We automatically authenticate all requests and use 'https://\{company_url\}' as the base url.| |Oracle Taleo|`taleo/soap`|[Taleo's API](https://docs.oracle.com/en/cloud/saas/taleo-enterprise/23b/otwsu/c-taleoapi.html). We automatically authenticate all requests and use 'https://\{your-subdomain\}.taleo.net/enterprise/soap' as base URL.| |OTYS|`otys/json-rpc`|[OTYS JSON-RPC API](https://ows.otys.nl/info/). We authenticate with your stored API key and inject the session token as the first element of the JSON-RPC `params` array on each request (except `loginByUid`, which uses `params` as sent). Requests use `https://ows.otys.nl` as the base URL (for example `POST /jservice.php` with the RPC method in the URL fragment, matching OTYS conventions).| +|PageUp People|`pageup/v1`|We use `https://assessment-mock-api.dc0.pageuppeople.com` as the base URL. Find the official docs [here](https://developers.pageuppeople.com/Api/Partners/Assessment).| |Paradox|`paradox/v1`|We use `\{api_url\}/api/v1` as the base URL. Find the official docs [here](https://paradox.readme.io/).| |Paradox|`paradox/v1public`|We use `\{api_url\}/api/v1/public` as the base URL. Find the official docs [here](https://paradox.readme.io/).| |Paychex|`paychex/api`|Paychex [REST API](https://developer.paychex.com/documentation). We automatically authenticate all requests and use `https://api.paychex.com` as the base URL.| @@ -335,6 +337,7 @@ To get started, please pick the relevant API (some tools provide multiple to due |Visma YouServe|`youserve/learning`|Visma YouServe [Learning API](https://youserve-domain-api.github.io/SwaggerUI/learning.html). We automatically authenticate all requests using OAuth 2.0 with the provided credentials and use `https://api.youserve.nl/learning/v1.0` as the base URL.| |Workable|`workable/v1`|**Deprecated: Use `v3` instead.** Workable's [API](https://workable.readme.io/reference/generate-an-access-token). We automatically authenticate all requests using the client ID and secret and use `https://\{subdomain\}.\{environment\}.com/spi/v3` as the base URL.| |Workable|`workable/v3`|Workable's [API](https://workable.readme.io/reference/generate-an-access-token). We automatically authenticate all requests using the client ID and secret and use `https://\{subdomain\}.\{environment\}.com/spi/v3` as the base URL.| +|Workday|`workday/custom-report`|[Workday's Custom Reports](https://community.workday.com/sites/default/files/file-hosting/productionapi/index.html). We automatically authenticate all requests and use `https://\{domain\}/ccx/service/customreport2/\{tenant\}/` as the base URL. Set your `method` to `GET`. The `path` should be the report path after the tenant, e.g., `/\{report_owner\}/\{report_name\}`. You can include query parameters in the `params` object (e.g., `format=json`).| |Workday|`workday/rest`|[Workday's REST API](https://community.workday.com/sites/default/files/file-hosting/restapi/index.html). We automatically authenticate all requests and use the correct Workday REST base URL for your tenant. The base URL follows the format: https://\{domain\}/api/\{service_name\}/\{version\}/\{tenant\}. You can specify any valid REST endpoint and method. See the Workday REST API documentation for available endpoints. You must specify the `api_options` object and set `service_name` to the name of the service you want to call. You can also specify the `version` (e.g., "v1", "v2"); if omitted, it defaults to "v1".| |Workday|`workday/soap`|[Workday's SOAP API](https://community.workday.com/sites/default/files/file-hosting/productionapi/index.html). We automatically authenticate all requests. Set `data` to your raw xml string. Use `/` as your `path`, as we will always send requests to `https://\{domain\}/ccx/service/\{tenant\}/\{service_name\}`. Set your `method` to `POST`. You need to specify the `api_options` object and set `service_name` to the name of the service you want to call. Find all available services [here](https://community.workday.com/sites/default/files/file-hosting/productionapi/versions/v41.0/index.html). The string that you submit as `data` will be the content of the `soapenv:Body` tag in the request. You can set the `service_version` to any valid Workday service version (the default is `38.2`).| |workforce.com|`workforcecom/api`|Workforce.com [API](https://my.workforce.com/api/v2/documentation). We automatically authenticate all requests using the provided credentials and use `https://my.tanda.co` as the base URL.| diff --git a/pyproject.toml b/pyproject.toml index 9af6c44..f110a99 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "kombo" -version = "1.2.0" +version = "1.3.0" description = "The official Python SDK for the Kombo Unified API" authors = [{ name = "Kombo Technologies GmbH" },] readme = "README-PYPI.md" diff --git a/src/kombo/_version.py b/src/kombo/_version.py index e8690c6..30b1e8e 100644 --- a/src/kombo/_version.py +++ b/src/kombo/_version.py @@ -3,10 +3,10 @@ import importlib.metadata __title__: str = "kombo" -__version__: str = "1.2.0" +__version__: str = "1.3.0" __openapi_doc_version__: str = "1.0.0" -__gen_version__: str = "2.893.0" -__user_agent__: str = "speakeasy-sdk/python 1.2.0 2.893.0 1.0.0 kombo" +__gen_version__: str = "2.911.0" +__user_agent__: str = "speakeasy-sdk/python 1.3.0 2.911.0 1.0.0 kombo" try: if __package__ is not None: diff --git a/src/kombo/assessment.py b/src/kombo/assessment.py index 3ce2821..35db2f3 100644 --- a/src/kombo/assessment.py +++ b/src/kombo/assessment.py @@ -7,7 +7,7 @@ from kombo._hooks import HookContext from kombo.types import BaseModel, OptionalNullable, UNSET from kombo.utils.unmarshal_json_response import unmarshal_json_response -from typing import Any, Awaitable, Dict, List, Mapping, Optional, Union, cast +from typing import Any, Awaitable, Dict, Iterable, List, Mapping, Optional, Union, cast class Assessment(BaseSDK): @@ -195,8 +195,8 @@ def set_packages( self, *, packages: Union[ - List[models.PutAssessmentPackagesRequestBodyPackage], - List[models.PutAssessmentPackagesRequestBodyPackageTypedDict], + Iterable[models.PutAssessmentPackagesRequestBodyPackage], + Iterable[models.PutAssessmentPackagesRequestBodyPackageTypedDict], ], retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, @@ -313,8 +313,8 @@ async def set_packages_async( self, *, packages: Union[ - List[models.PutAssessmentPackagesRequestBodyPackage], - List[models.PutAssessmentPackagesRequestBodyPackageTypedDict], + Iterable[models.PutAssessmentPackagesRequestBodyPackage], + Iterable[models.PutAssessmentPackagesRequestBodyPackageTypedDict], ], retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, @@ -432,8 +432,8 @@ def get_assessment_orders( *, cursor: Optional[str] = None, page_size: Optional[int] = 100, - ids: Optional[List[str]] = None, - statuses: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + statuses: Optional[Iterable[str]] = None, created_after: Optional[datetime] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, @@ -469,8 +469,8 @@ def get_assessment_orders( request = models.GetAssessmentOrdersRequest( cursor=cursor, page_size=page_size, - ids=ids, - statuses=statuses, + ids=utils.unmarshal(ids, Optional[List[str]]), + statuses=utils.unmarshal(statuses, Optional[List[str]]), created_after=created_after, ) @@ -558,8 +558,8 @@ async def get_assessment_orders_async( *, cursor: Optional[str] = None, page_size: Optional[int] = 100, - ids: Optional[List[str]] = None, - statuses: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + statuses: Optional[Iterable[str]] = None, created_after: Optional[datetime] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, @@ -595,8 +595,8 @@ async def get_assessment_orders_async( request = models.GetAssessmentOrdersRequest( cursor=cursor, page_size=page_size, - ids=ids, - statuses=statuses, + ids=utils.unmarshal(ids, Optional[List[str]]), + statuses=utils.unmarshal(statuses, Optional[List[str]]), created_after=created_after, ) @@ -692,14 +692,14 @@ def update_order_result( score: Optional[float] = None, max_score: Optional[float] = None, attributes: Optional[ - Union[List[models.Attribute], List[models.AttributeTypedDict]] + Union[Iterable[models.Attribute], Iterable[models.AttributeTypedDict]] ] = None, attachments: Optional[ Union[ - List[ + Iterable[ models.PutAssessmentOrdersAssessmentOrderIDResultRequestBodyAttachment ], - List[ + Iterable[ models.PutAssessmentOrdersAssessmentOrderIDResultRequestBodyAttachmentTypedDict ], ] @@ -883,14 +883,14 @@ async def update_order_result_async( score: Optional[float] = None, max_score: Optional[float] = None, attributes: Optional[ - Union[List[models.Attribute], List[models.AttributeTypedDict]] + Union[Iterable[models.Attribute], Iterable[models.AttributeTypedDict]] ] = None, attachments: Optional[ Union[ - List[ + Iterable[ models.PutAssessmentOrdersAssessmentOrderIDResultRequestBodyAttachment ], - List[ + Iterable[ models.PutAssessmentOrdersAssessmentOrderIDResultRequestBodyAttachmentTypedDict ], ] diff --git a/src/kombo/ats.py b/src/kombo/ats.py index 4f7b1fd..7ecf321 100644 --- a/src/kombo/ats.py +++ b/src/kombo/ats.py @@ -7,7 +7,7 @@ from kombo._hooks import HookContext from kombo.types import Nullable, OptionalNullable, UNSET from kombo.utils.unmarshal_json_response import unmarshal_json_response -from typing import Any, Awaitable, Dict, List, Mapping, Optional, Union +from typing import Any, Awaitable, Dict, Iterable, List, Mapping, Optional, Union class Ats(BaseSDK): @@ -19,12 +19,12 @@ def get_applications( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, - outcomes: Optional[List[str]] = None, - job_ids: Optional[List[str]] = None, - job_remote_ids: Optional[List[str]] = None, - current_stage_ids: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, + outcomes: Optional[Iterable[str]] = None, + job_ids: Optional[Iterable[str]] = None, + job_remote_ids: Optional[Iterable[str]] = None, + current_stage_ids: Optional[Iterable[str]] = None, remote_created_after: Optional[datetime] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, @@ -100,12 +100,12 @@ def get_applications( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, - outcomes=outcomes, - job_ids=job_ids, - job_remote_ids=job_remote_ids, - current_stage_ids=current_stage_ids, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), + outcomes=utils.unmarshal(outcomes, Optional[List[str]]), + job_ids=utils.unmarshal(job_ids, Optional[List[str]]), + job_remote_ids=utils.unmarshal(job_remote_ids, Optional[List[str]]), + current_stage_ids=utils.unmarshal(current_stage_ids, Optional[List[str]]), remote_created_after=remote_created_after, ) @@ -203,12 +203,12 @@ async def get_applications_async( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, - outcomes: Optional[List[str]] = None, - job_ids: Optional[List[str]] = None, - job_remote_ids: Optional[List[str]] = None, - current_stage_ids: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, + outcomes: Optional[Iterable[str]] = None, + job_ids: Optional[Iterable[str]] = None, + job_remote_ids: Optional[Iterable[str]] = None, + current_stage_ids: Optional[Iterable[str]] = None, remote_created_after: Optional[datetime] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, @@ -284,12 +284,12 @@ async def get_applications_async( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, - outcomes=outcomes, - job_ids=job_ids, - job_remote_ids=job_remote_ids, - current_stage_ids=current_stage_ids, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), + outcomes=utils.unmarshal(outcomes, Optional[List[str]]), + job_ids=utils.unmarshal(job_ids, Optional[List[str]]), + job_remote_ids=utils.unmarshal(job_remote_ids, Optional[List[str]]), + current_stage_ids=utils.unmarshal(current_stage_ids, Optional[List[str]]), remote_created_after=remote_created_after, ) @@ -1958,10 +1958,10 @@ def get_candidates( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, email: Optional[str] = None, - job_ids: Optional[List[str]] = None, + job_ids: Optional[Iterable[str]] = None, first_name: Optional[str] = None, last_name: Optional[str] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, @@ -2022,10 +2022,10 @@ def get_candidates( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), email=email, - job_ids=job_ids, + job_ids=utils.unmarshal(job_ids, Optional[List[str]]), first_name=first_name, last_name=last_name, ) @@ -2123,10 +2123,10 @@ async def get_candidates_async( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, email: Optional[str] = None, - job_ids: Optional[List[str]] = None, + job_ids: Optional[Iterable[str]] = None, first_name: Optional[str] = None, last_name: Optional[str] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, @@ -2187,10 +2187,10 @@ async def get_candidates_async( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), email=email, - job_ids=job_ids, + job_ids=utils.unmarshal(job_ids, Optional[List[str]]), first_name=first_name, last_name=last_name, ) @@ -2296,16 +2296,16 @@ def create_candidate( ], screening_question_answers: Optional[ Union[ - List[models.PostAtsCandidatesRequestBodyScreeningQuestionAnswer], - List[ + Iterable[models.PostAtsCandidatesRequestBodyScreeningQuestionAnswer], + Iterable[ models.PostAtsCandidatesRequestBodyScreeningQuestionAnswerTypedDict ], ] ] = None, attachments: Optional[ Union[ - List[models.PostAtsCandidatesRequestBodyAttachment], - List[models.PostAtsCandidatesRequestBodyAttachmentTypedDict], + Iterable[models.PostAtsCandidatesRequestBodyAttachment], + Iterable[models.PostAtsCandidatesRequestBodyAttachmentTypedDict], ] ] = None, source: Optional[ @@ -2547,16 +2547,16 @@ async def create_candidate_async( ], screening_question_answers: Optional[ Union[ - List[models.PostAtsCandidatesRequestBodyScreeningQuestionAnswer], - List[ + Iterable[models.PostAtsCandidatesRequestBodyScreeningQuestionAnswer], + Iterable[ models.PostAtsCandidatesRequestBodyScreeningQuestionAnswerTypedDict ], ] ] = None, attachments: Optional[ Union[ - List[models.PostAtsCandidatesRequestBodyAttachment], - List[models.PostAtsCandidatesRequestBodyAttachmentTypedDict], + Iterable[models.PostAtsCandidatesRequestBodyAttachment], + Iterable[models.PostAtsCandidatesRequestBodyAttachmentTypedDict], ] ] = None, source: Optional[ @@ -4119,8 +4119,8 @@ def get_tags( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, timeout_ms: Optional[int] = None, @@ -4166,8 +4166,8 @@ def get_tags( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), ) req = self._build_request( @@ -4259,8 +4259,8 @@ async def get_tags_async( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, timeout_ms: Optional[int] = None, @@ -4306,8 +4306,8 @@ async def get_tags_async( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), ) req = self._build_request_async( @@ -4402,8 +4402,8 @@ def get_application_stages( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, timeout_ms: Optional[int] = None, @@ -4459,8 +4459,8 @@ def get_application_stages( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), ) req = self._build_request( @@ -4552,8 +4552,8 @@ async def get_application_stages_async( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, timeout_ms: Optional[int] = None, @@ -4609,8 +4609,8 @@ async def get_application_stages_async( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), ) req = self._build_request_async( @@ -4705,13 +4705,13 @@ def get_jobs( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, - job_codes: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, + job_codes: Optional[Iterable[str]] = None, post_url: Optional[str] = None, - statuses: Optional[List[str]] = None, - employment_types: Optional[List[str]] = None, - visibilities: Optional[List[str]] = None, + statuses: Optional[Iterable[str]] = None, + employment_types: Optional[Iterable[str]] = None, + visibilities: Optional[Iterable[str]] = None, remote_created_after: Optional[datetime] = None, name_contains: Optional[str] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, @@ -4789,13 +4789,13 @@ def get_jobs( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, - job_codes=job_codes, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), + job_codes=utils.unmarshal(job_codes, Optional[List[str]]), post_url=post_url, - statuses=statuses, - employment_types=employment_types, - visibilities=visibilities, + statuses=utils.unmarshal(statuses, Optional[List[str]]), + employment_types=utils.unmarshal(employment_types, Optional[List[str]]), + visibilities=utils.unmarshal(visibilities, Optional[List[str]]), remote_created_after=remote_created_after, name_contains=name_contains, ) @@ -4896,13 +4896,13 @@ async def get_jobs_async( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, - job_codes: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, + job_codes: Optional[Iterable[str]] = None, post_url: Optional[str] = None, - statuses: Optional[List[str]] = None, - employment_types: Optional[List[str]] = None, - visibilities: Optional[List[str]] = None, + statuses: Optional[Iterable[str]] = None, + employment_types: Optional[Iterable[str]] = None, + visibilities: Optional[Iterable[str]] = None, remote_created_after: Optional[datetime] = None, name_contains: Optional[str] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, @@ -4980,13 +4980,13 @@ async def get_jobs_async( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, - job_codes=job_codes, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), + job_codes=utils.unmarshal(job_codes, Optional[List[str]]), post_url=post_url, - statuses=statuses, - employment_types=employment_types, - visibilities=visibilities, + statuses=utils.unmarshal(statuses, Optional[List[str]]), + employment_types=utils.unmarshal(employment_types, Optional[List[str]]), + visibilities=utils.unmarshal(visibilities, Optional[List[str]]), remote_created_after=remote_created_after, name_contains=name_contains, ) @@ -5093,8 +5093,10 @@ def create_application( stage_id: Optional[str] = None, attachments: Optional[ Union[ - List[models.PostAtsJobsJobIDApplicationsRequestBodyAttachment], - List[models.PostAtsJobsJobIDApplicationsRequestBodyAttachmentTypedDict], + Iterable[models.PostAtsJobsJobIDApplicationsRequestBodyAttachment], + Iterable[ + models.PostAtsJobsJobIDApplicationsRequestBodyAttachmentTypedDict + ], ] ] = None, source: Optional[ @@ -5123,10 +5125,10 @@ def create_application( ] = None, screening_question_answers: Optional[ Union[ - List[ + Iterable[ models.PostAtsJobsJobIDApplicationsRequestBodyScreeningQuestionAnswer ], - List[ + Iterable[ models.PostAtsJobsJobIDApplicationsRequestBodyScreeningQuestionAnswerTypedDict ], ] @@ -5350,8 +5352,10 @@ async def create_application_async( stage_id: Optional[str] = None, attachments: Optional[ Union[ - List[models.PostAtsJobsJobIDApplicationsRequestBodyAttachment], - List[models.PostAtsJobsJobIDApplicationsRequestBodyAttachmentTypedDict], + Iterable[models.PostAtsJobsJobIDApplicationsRequestBodyAttachment], + Iterable[ + models.PostAtsJobsJobIDApplicationsRequestBodyAttachmentTypedDict + ], ] ] = None, source: Optional[ @@ -5380,10 +5384,10 @@ async def create_application_async( ] = None, screening_question_answers: Optional[ Union[ - List[ + Iterable[ models.PostAtsJobsJobIDApplicationsRequestBodyScreeningQuestionAnswer ], - List[ + Iterable[ models.PostAtsJobsJobIDApplicationsRequestBodyScreeningQuestionAnswerTypedDict ], ] @@ -5604,9 +5608,9 @@ def get_users( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, - emails: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, + emails: Optional[Iterable[str]] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, timeout_ms: Optional[int] = None, @@ -5659,9 +5663,9 @@ def get_users( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, - emails=emails, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), + emails=utils.unmarshal(emails, Optional[List[str]]), ) req = self._build_request( @@ -5754,9 +5758,9 @@ async def get_users_async( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, - emails: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, + emails: Optional[Iterable[str]] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, timeout_ms: Optional[int] = None, @@ -5809,9 +5813,9 @@ async def get_users_async( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, - emails=emails, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), + emails=utils.unmarshal(emails, Optional[List[str]]), ) req = self._build_request_async( @@ -5907,9 +5911,9 @@ def get_roles( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, - scopes: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, + scopes: Optional[Iterable[str]] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, timeout_ms: Optional[int] = None, @@ -5963,9 +5967,9 @@ def get_roles( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, - scopes=scopes, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), + scopes=utils.unmarshal(scopes, Optional[List[str]]), ) req = self._build_request( @@ -6058,9 +6062,9 @@ async def get_roles_async( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, - scopes: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, + scopes: Optional[Iterable[str]] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, timeout_ms: Optional[int] = None, @@ -6114,9 +6118,9 @@ async def get_roles_async( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, - scopes=scopes, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), + scopes=utils.unmarshal(scopes, Optional[List[str]]), ) req = self._build_request_async( @@ -6212,8 +6216,8 @@ def get_offers( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, timeout_ms: Optional[int] = None, @@ -6267,8 +6271,8 @@ def get_offers( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), ) req = self._build_request( @@ -6360,8 +6364,8 @@ async def get_offers_async( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, timeout_ms: Optional[int] = None, @@ -6415,8 +6419,8 @@ async def get_offers_async( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), ) req = self._build_request_async( @@ -6511,8 +6515,8 @@ def get_rejection_reasons( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, timeout_ms: Optional[int] = None, @@ -6560,8 +6564,8 @@ def get_rejection_reasons( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), ) req = self._build_request( @@ -6653,8 +6657,8 @@ async def get_rejection_reasons_async( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, timeout_ms: Optional[int] = None, @@ -6702,8 +6706,8 @@ async def get_rejection_reasons_async( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), ) req = self._build_request_async( @@ -6798,9 +6802,9 @@ def get_interviews( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, - job_ids: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, + job_ids: Optional[Iterable[str]] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, timeout_ms: Optional[int] = None, @@ -6856,9 +6860,9 @@ def get_interviews( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, - job_ids=job_ids, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), + job_ids=utils.unmarshal(job_ids, Optional[List[str]]), ) req = self._build_request( @@ -6951,9 +6955,9 @@ async def get_interviews_async( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, - job_ids: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, + job_ids: Optional[Iterable[str]] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, timeout_ms: Optional[int] = None, @@ -7009,9 +7013,9 @@ async def get_interviews_async( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, - job_ids=job_ids, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), + job_ids=utils.unmarshal(job_ids, Optional[List[str]]), ) req = self._build_request_async( diff --git a/src/kombo/general.py b/src/kombo/general.py index 300563c..0fa0989 100644 --- a/src/kombo/general.py +++ b/src/kombo/general.py @@ -6,7 +6,7 @@ from kombo._hooks import HookContext from kombo.types import Nullable, OptionalNullable, UNSET from kombo.utils.unmarshal_json_response import unmarshal_json_response -from typing import Any, Awaitable, Dict, List, Mapping, Optional, Union +from typing import Any, Awaitable, Dict, Iterable, List, Mapping, Optional, Union class General(BaseSDK): @@ -361,17 +361,17 @@ def send_passthrough_request( api: str, method: models.Method, path: str, - headers: Optional[Dict[str, str]] = None, - params: Optional[Dict[str, str]] = None, + headers: Optional[Mapping[str, str]] = None, + params: Optional[Mapping[str, str]] = None, data: Optional[Any] = None, response_as_base64: Optional[bool] = None, multipart_form_data: Optional[ Union[ - List[models.MultipartFormDatum], - List[models.MultipartFormDatumTypedDict], + Iterable[models.MultipartFormDatum], + Iterable[models.MultipartFormDatumTypedDict], ] ] = None, - api_options: Optional[Dict[str, str]] = None, + api_options: Optional[Mapping[str, str]] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, timeout_ms: Optional[int] = None, @@ -430,14 +430,15 @@ def send_passthrough_request( |d.vinci admin|`dvinciadmin/rest-api`|[DVinci REST API](https://static.dvinci-easy.com/files/d.vinci%20rest-api.html).| |d.vinci|`dvinci/apply-api`|The [DVinci Apply API](https://static.dvinci-easy.com/files/d.vinci%20application-apply-api.html). All requests are authenticated by Kombo and use `https://\{dvinci_domain\}/p/\{portal_path\}/` as the base URL.| |d.vinci|`dvinci/rest-api`|The [DVinci REST API](https://static.dvinci-easy.com/files/d.vinci%20rest-api.html). All requests are authenticated by Kombo and use `https://\{dvinci_domain\}/restApi/` as the base URL.| - |DATEV LAUDS|`datevlauds/lauds`|DATEV's [hr-exchange](https://developer.datev.de/de/product-detail/hr-exchange/1.0.0/overview). We automatically authenticate all requests and use `https://hr-exchange.api.datev.de/\{platform|platform-sandbox\}/v1/clients/\{client-id\}` as the base URL.| |DATEV LODAS|`datev/eau`|DATEV's [eau](https://developer.datev.de/en/product-detail/eau-api/1.0.0/overview) API. We automatically authenticate all requests and use `https://eau.api.datev.de/\{platform|platform-sandbox\}/v1/clients/\{client-id\}/` as the base URL.| + |DATEV Lohnaustauschdatenservice|`datevlauds/lauds`|DATEV's [hr-exchange](https://developer.datev.de/de/product-detail/hr-exchange/1.0.0/overview). We automatically authenticate all requests and use `https://hr-exchange.api.datev.de/\{platform|platform-sandbox\}/v1/clients/\{client-id\}` as the base URL.| |DATEV|`datevhr/eau`|DATEV's [eau](https://developer.datev.de/en/product-detail/eau-api/1.0.0/overview) API. We automatically authenticate all requests and use `https://eau.api.datev.de/\{platform|platform-sandbox\}/v1/clients/\{client-id\}/` as the base URL.| |DATEV|`datevhr/hr-exports`|DATEV's [hr-exports](https://developer.datev.de/en/product-detail/hr-exports/1.0.0/overview). We automatically authenticate all requests and use `https://hr-exports.api.datev.de/\{platform|platform-sandbox\}/v1/clients/\{client-id\}` as the base URL.| |DATEV|`datevhr/hr:payrollreports`|DATEV's [hr:payrollreports](https://developer.datev.de/en/product-detail/hr-payrollreports/2.0.0/overview) API. We automatically authenticate all requests and use `https://hr-payrollreports.api.datev.de/\{platform|platform-sandbox\}/v1/clients/\{client-id\}/` as the base URL.| |Dayforce|`dayforce/V1`|[Dayforce's API](https://developers.dayforce.com/Build/Home.aspx). We automatically authenticate all requests and use `\{\{baseUrl\}\}/Api/\{\{clientNamespace\}\}/V1` as the base URL| |Deel|`deel/api`|Deel's [API](https://developer.deel.com/reference/). We automatically authenticate all requests using the provided credentials and use `https://\{api_domain\}/rest` as the base URL.| |Digital Recruiters|`digitalrecruiters/api`|Cegid Digital Recruiters [Talent Acquisition API](https://cegid-hr-developers.talentsoft.net/docs/tutorial-basics/Talent%20Acquisition/Getting%20Started). We automatically authenticate all requests by replacing `:token` in the request URL with your configured access token and use your configured Digital Recruiters domain as the base URL.| + |Docebo|`docebo/api`|Docebo [API](https://developer.docebo.com). We automatically handle authentication and use `https://\{subdomain\}.docebosaas.com` as the base URL.| |Eightfold|`eightfold/api`|Eightfold's [API](https://apidocs.eightfold.ai/). We automatically authenticate all requests and use `https://apiv2.\{region\}/api/v2/core/` as the base URL.| |Employment Hero|`employmenthero/default`|EmploymentHero [API](https://developer.employmenthero.com/api-references/#icon-book-open-introduction). We automatically authenticate all requests using the credentials supplied by the customer and use `https://api.employmenthero.com/api` as the base URL.| |Eploy|`eploy/api`|Eploy's [API](https://www.eploy.com/resources/developers/api-documentation/). We automatically authenticate all requests. The base URL is `https://\{hostname\}/api`, where `\{hostname\}` is either `\{subdomain\}.eploy.net` or your full custom hostname when applicable.| @@ -518,6 +519,7 @@ def send_passthrough_request( |Oracle Recruiting Cloud|`oraclerecruiting/rest`|[Oracles's REST API](https://docs.oracle.com/en/cloud/saas/human-resources/24d/farws/rest-endpoints.html). We automatically authenticate all requests and use 'https://\{company_url\}' as the base url.| |Oracle Taleo|`taleo/soap`|[Taleo's API](https://docs.oracle.com/en/cloud/saas/taleo-enterprise/23b/otwsu/c-taleoapi.html). We automatically authenticate all requests and use 'https://\{your-subdomain\}.taleo.net/enterprise/soap' as base URL.| |OTYS|`otys/json-rpc`|[OTYS JSON-RPC API](https://ows.otys.nl/info/). We authenticate with your stored API key and inject the session token as the first element of the JSON-RPC `params` array on each request (except `loginByUid`, which uses `params` as sent). Requests use `https://ows.otys.nl` as the base URL (for example `POST /jservice.php` with the RPC method in the URL fragment, matching OTYS conventions).| + |PageUp People|`pageup/v1`|We use `https://assessment-mock-api.dc0.pageuppeople.com` as the base URL. Find the official docs [here](https://developers.pageuppeople.com/Api/Partners/Assessment).| |Paradox|`paradox/v1`|We use `\{api_url\}/api/v1` as the base URL. Find the official docs [here](https://paradox.readme.io/).| |Paradox|`paradox/v1public`|We use `\{api_url\}/api/v1/public` as the base URL. Find the official docs [here](https://paradox.readme.io/).| |Paychex|`paychex/api`|Paychex [REST API](https://developer.paychex.com/documentation). We automatically authenticate all requests and use `https://api.paychex.com` as the base URL.| @@ -576,6 +578,7 @@ def send_passthrough_request( |Visma YouServe|`youserve/learning`|Visma YouServe [Learning API](https://youserve-domain-api.github.io/SwaggerUI/learning.html). We automatically authenticate all requests using OAuth 2.0 with the provided credentials and use `https://api.youserve.nl/learning/v1.0` as the base URL.| |Workable|`workable/v1`|**Deprecated: Use `v3` instead.** Workable's [API](https://workable.readme.io/reference/generate-an-access-token). We automatically authenticate all requests using the client ID and secret and use `https://\{subdomain\}.\{environment\}.com/spi/v3` as the base URL.| |Workable|`workable/v3`|Workable's [API](https://workable.readme.io/reference/generate-an-access-token). We automatically authenticate all requests using the client ID and secret and use `https://\{subdomain\}.\{environment\}.com/spi/v3` as the base URL.| + |Workday|`workday/custom-report`|[Workday's Custom Reports](https://community.workday.com/sites/default/files/file-hosting/productionapi/index.html). We automatically authenticate all requests and use `https://\{domain\}/ccx/service/customreport2/\{tenant\}/` as the base URL. Set your `method` to `GET`. The `path` should be the report path after the tenant, e.g., `/\{report_owner\}/\{report_name\}`. You can include query parameters in the `params` object (e.g., `format=json`).| |Workday|`workday/rest`|[Workday's REST API](https://community.workday.com/sites/default/files/file-hosting/restapi/index.html). We automatically authenticate all requests and use the correct Workday REST base URL for your tenant. The base URL follows the format: https://\{domain\}/api/\{service_name\}/\{version\}/\{tenant\}. You can specify any valid REST endpoint and method. See the Workday REST API documentation for available endpoints. You must specify the `api_options` object and set `service_name` to the name of the service you want to call. You can also specify the `version` (e.g., \"v1\", \"v2\"); if omitted, it defaults to \"v1\".| |Workday|`workday/soap`|[Workday's SOAP API](https://community.workday.com/sites/default/files/file-hosting/productionapi/index.html). We automatically authenticate all requests. Set `data` to your raw xml string. Use `/` as your `path`, as we will always send requests to `https://\{domain\}/ccx/service/\{tenant\}/\{service_name\}`. Set your `method` to `POST`. You need to specify the `api_options` object and set `service_name` to the name of the service you want to call. Find all available services [here](https://community.workday.com/sites/default/files/file-hosting/productionapi/versions/v41.0/index.html). The string that you submit as `data` will be the content of the `soapenv:Body` tag in the request. You can set the `service_version` to any valid Workday service version (the default is `38.2`).| |workforce.com|`workforcecom/api`|Workforce.com [API](https://my.workforce.com/api/v2/documentation). We automatically authenticate all requests using the provided credentials and use `https://my.tanda.co` as the base URL.| @@ -620,14 +623,14 @@ def send_passthrough_request( body=models.PostPassthroughToolAPIRequestBody( method=method, path=path, - headers=headers, - params=params, + headers=utils.unmarshal(headers, Optional[Dict[str, str]]), + params=utils.unmarshal(params, Optional[Dict[str, str]]), data=data, response_as_base64=response_as_base64, multipart_form_data=utils.get_pydantic_model( multipart_form_data, Optional[List[models.MultipartFormDatum]] ), - api_options=api_options, + api_options=utils.unmarshal(api_options, Optional[Dict[str, str]]), ), ) @@ -699,17 +702,17 @@ async def send_passthrough_request_async( api: str, method: models.Method, path: str, - headers: Optional[Dict[str, str]] = None, - params: Optional[Dict[str, str]] = None, + headers: Optional[Mapping[str, str]] = None, + params: Optional[Mapping[str, str]] = None, data: Optional[Any] = None, response_as_base64: Optional[bool] = None, multipart_form_data: Optional[ Union[ - List[models.MultipartFormDatum], - List[models.MultipartFormDatumTypedDict], + Iterable[models.MultipartFormDatum], + Iterable[models.MultipartFormDatumTypedDict], ] ] = None, - api_options: Optional[Dict[str, str]] = None, + api_options: Optional[Mapping[str, str]] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, timeout_ms: Optional[int] = None, @@ -768,14 +771,15 @@ async def send_passthrough_request_async( |d.vinci admin|`dvinciadmin/rest-api`|[DVinci REST API](https://static.dvinci-easy.com/files/d.vinci%20rest-api.html).| |d.vinci|`dvinci/apply-api`|The [DVinci Apply API](https://static.dvinci-easy.com/files/d.vinci%20application-apply-api.html). All requests are authenticated by Kombo and use `https://\{dvinci_domain\}/p/\{portal_path\}/` as the base URL.| |d.vinci|`dvinci/rest-api`|The [DVinci REST API](https://static.dvinci-easy.com/files/d.vinci%20rest-api.html). All requests are authenticated by Kombo and use `https://\{dvinci_domain\}/restApi/` as the base URL.| - |DATEV LAUDS|`datevlauds/lauds`|DATEV's [hr-exchange](https://developer.datev.de/de/product-detail/hr-exchange/1.0.0/overview). We automatically authenticate all requests and use `https://hr-exchange.api.datev.de/\{platform|platform-sandbox\}/v1/clients/\{client-id\}` as the base URL.| |DATEV LODAS|`datev/eau`|DATEV's [eau](https://developer.datev.de/en/product-detail/eau-api/1.0.0/overview) API. We automatically authenticate all requests and use `https://eau.api.datev.de/\{platform|platform-sandbox\}/v1/clients/\{client-id\}/` as the base URL.| + |DATEV Lohnaustauschdatenservice|`datevlauds/lauds`|DATEV's [hr-exchange](https://developer.datev.de/de/product-detail/hr-exchange/1.0.0/overview). We automatically authenticate all requests and use `https://hr-exchange.api.datev.de/\{platform|platform-sandbox\}/v1/clients/\{client-id\}` as the base URL.| |DATEV|`datevhr/eau`|DATEV's [eau](https://developer.datev.de/en/product-detail/eau-api/1.0.0/overview) API. We automatically authenticate all requests and use `https://eau.api.datev.de/\{platform|platform-sandbox\}/v1/clients/\{client-id\}/` as the base URL.| |DATEV|`datevhr/hr-exports`|DATEV's [hr-exports](https://developer.datev.de/en/product-detail/hr-exports/1.0.0/overview). We automatically authenticate all requests and use `https://hr-exports.api.datev.de/\{platform|platform-sandbox\}/v1/clients/\{client-id\}` as the base URL.| |DATEV|`datevhr/hr:payrollreports`|DATEV's [hr:payrollreports](https://developer.datev.de/en/product-detail/hr-payrollreports/2.0.0/overview) API. We automatically authenticate all requests and use `https://hr-payrollreports.api.datev.de/\{platform|platform-sandbox\}/v1/clients/\{client-id\}/` as the base URL.| |Dayforce|`dayforce/V1`|[Dayforce's API](https://developers.dayforce.com/Build/Home.aspx). We automatically authenticate all requests and use `\{\{baseUrl\}\}/Api/\{\{clientNamespace\}\}/V1` as the base URL| |Deel|`deel/api`|Deel's [API](https://developer.deel.com/reference/). We automatically authenticate all requests using the provided credentials and use `https://\{api_domain\}/rest` as the base URL.| |Digital Recruiters|`digitalrecruiters/api`|Cegid Digital Recruiters [Talent Acquisition API](https://cegid-hr-developers.talentsoft.net/docs/tutorial-basics/Talent%20Acquisition/Getting%20Started). We automatically authenticate all requests by replacing `:token` in the request URL with your configured access token and use your configured Digital Recruiters domain as the base URL.| + |Docebo|`docebo/api`|Docebo [API](https://developer.docebo.com). We automatically handle authentication and use `https://\{subdomain\}.docebosaas.com` as the base URL.| |Eightfold|`eightfold/api`|Eightfold's [API](https://apidocs.eightfold.ai/). We automatically authenticate all requests and use `https://apiv2.\{region\}/api/v2/core/` as the base URL.| |Employment Hero|`employmenthero/default`|EmploymentHero [API](https://developer.employmenthero.com/api-references/#icon-book-open-introduction). We automatically authenticate all requests using the credentials supplied by the customer and use `https://api.employmenthero.com/api` as the base URL.| |Eploy|`eploy/api`|Eploy's [API](https://www.eploy.com/resources/developers/api-documentation/). We automatically authenticate all requests. The base URL is `https://\{hostname\}/api`, where `\{hostname\}` is either `\{subdomain\}.eploy.net` or your full custom hostname when applicable.| @@ -856,6 +860,7 @@ async def send_passthrough_request_async( |Oracle Recruiting Cloud|`oraclerecruiting/rest`|[Oracles's REST API](https://docs.oracle.com/en/cloud/saas/human-resources/24d/farws/rest-endpoints.html). We automatically authenticate all requests and use 'https://\{company_url\}' as the base url.| |Oracle Taleo|`taleo/soap`|[Taleo's API](https://docs.oracle.com/en/cloud/saas/taleo-enterprise/23b/otwsu/c-taleoapi.html). We automatically authenticate all requests and use 'https://\{your-subdomain\}.taleo.net/enterprise/soap' as base URL.| |OTYS|`otys/json-rpc`|[OTYS JSON-RPC API](https://ows.otys.nl/info/). We authenticate with your stored API key and inject the session token as the first element of the JSON-RPC `params` array on each request (except `loginByUid`, which uses `params` as sent). Requests use `https://ows.otys.nl` as the base URL (for example `POST /jservice.php` with the RPC method in the URL fragment, matching OTYS conventions).| + |PageUp People|`pageup/v1`|We use `https://assessment-mock-api.dc0.pageuppeople.com` as the base URL. Find the official docs [here](https://developers.pageuppeople.com/Api/Partners/Assessment).| |Paradox|`paradox/v1`|We use `\{api_url\}/api/v1` as the base URL. Find the official docs [here](https://paradox.readme.io/).| |Paradox|`paradox/v1public`|We use `\{api_url\}/api/v1/public` as the base URL. Find the official docs [here](https://paradox.readme.io/).| |Paychex|`paychex/api`|Paychex [REST API](https://developer.paychex.com/documentation). We automatically authenticate all requests and use `https://api.paychex.com` as the base URL.| @@ -914,6 +919,7 @@ async def send_passthrough_request_async( |Visma YouServe|`youserve/learning`|Visma YouServe [Learning API](https://youserve-domain-api.github.io/SwaggerUI/learning.html). We automatically authenticate all requests using OAuth 2.0 with the provided credentials and use `https://api.youserve.nl/learning/v1.0` as the base URL.| |Workable|`workable/v1`|**Deprecated: Use `v3` instead.** Workable's [API](https://workable.readme.io/reference/generate-an-access-token). We automatically authenticate all requests using the client ID and secret and use `https://\{subdomain\}.\{environment\}.com/spi/v3` as the base URL.| |Workable|`workable/v3`|Workable's [API](https://workable.readme.io/reference/generate-an-access-token). We automatically authenticate all requests using the client ID and secret and use `https://\{subdomain\}.\{environment\}.com/spi/v3` as the base URL.| + |Workday|`workday/custom-report`|[Workday's Custom Reports](https://community.workday.com/sites/default/files/file-hosting/productionapi/index.html). We automatically authenticate all requests and use `https://\{domain\}/ccx/service/customreport2/\{tenant\}/` as the base URL. Set your `method` to `GET`. The `path` should be the report path after the tenant, e.g., `/\{report_owner\}/\{report_name\}`. You can include query parameters in the `params` object (e.g., `format=json`).| |Workday|`workday/rest`|[Workday's REST API](https://community.workday.com/sites/default/files/file-hosting/restapi/index.html). We automatically authenticate all requests and use the correct Workday REST base URL for your tenant. The base URL follows the format: https://\{domain\}/api/\{service_name\}/\{version\}/\{tenant\}. You can specify any valid REST endpoint and method. See the Workday REST API documentation for available endpoints. You must specify the `api_options` object and set `service_name` to the name of the service you want to call. You can also specify the `version` (e.g., \"v1\", \"v2\"); if omitted, it defaults to \"v1\".| |Workday|`workday/soap`|[Workday's SOAP API](https://community.workday.com/sites/default/files/file-hosting/productionapi/index.html). We automatically authenticate all requests. Set `data` to your raw xml string. Use `/` as your `path`, as we will always send requests to `https://\{domain\}/ccx/service/\{tenant\}/\{service_name\}`. Set your `method` to `POST`. You need to specify the `api_options` object and set `service_name` to the name of the service you want to call. Find all available services [here](https://community.workday.com/sites/default/files/file-hosting/productionapi/versions/v41.0/index.html). The string that you submit as `data` will be the content of the `soapenv:Body` tag in the request. You can set the `service_version` to any valid Workday service version (the default is `38.2`).| |workforce.com|`workforcecom/api`|Workforce.com [API](https://my.workforce.com/api/v2/documentation). We automatically authenticate all requests using the provided credentials and use `https://my.tanda.co` as the base URL.| @@ -958,14 +964,14 @@ async def send_passthrough_request_async( body=models.PostPassthroughToolAPIRequestBody( method=method, path=path, - headers=headers, - params=params, + headers=utils.unmarshal(headers, Optional[Dict[str, str]]), + params=utils.unmarshal(params, Optional[Dict[str, str]]), data=data, response_as_base64=response_as_base64, multipart_form_data=utils.get_pydantic_model( multipart_form_data, Optional[List[models.MultipartFormDatum]] ), - api_options=api_options, + api_options=utils.unmarshal(api_options, Optional[Dict[str, str]]), ), ) diff --git a/src/kombo/hris.py b/src/kombo/hris.py index 8cd4b95..709aeed 100644 --- a/src/kombo/hris.py +++ b/src/kombo/hris.py @@ -7,7 +7,7 @@ from kombo._hooks import HookContext from kombo.types import Nullable, OptionalNullable, UNSET from kombo.utils.unmarshal_json_response import unmarshal_json_response -from typing import Any, Awaitable, Dict, List, Mapping, Optional, Union +from typing import Any, Awaitable, Dict, Iterable, List, Mapping, Optional, Union class Hris(BaseSDK): @@ -19,14 +19,14 @@ def get_employees( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, - employment_statuses: Optional[List[str]] = None, - group_ids: Optional[List[str]] = None, - legal_entity_ids: Optional[List[str]] = None, - work_location_ids: Optional[List[str]] = None, - work_emails: Optional[List[str]] = None, - personal_emails: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, + employment_statuses: Optional[Iterable[str]] = None, + group_ids: Optional[Iterable[str]] = None, + legal_entity_ids: Optional[Iterable[str]] = None, + work_location_ids: Optional[Iterable[str]] = None, + work_emails: Optional[Iterable[str]] = None, + personal_emails: Optional[Iterable[str]] = None, custom_fields: Optional[str] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, @@ -100,14 +100,16 @@ def get_employees( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, - employment_statuses=employment_statuses, - group_ids=group_ids, - legal_entity_ids=legal_entity_ids, - work_location_ids=work_location_ids, - work_emails=work_emails, - personal_emails=personal_emails, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), + employment_statuses=utils.unmarshal( + employment_statuses, Optional[List[str]] + ), + group_ids=utils.unmarshal(group_ids, Optional[List[str]]), + legal_entity_ids=utils.unmarshal(legal_entity_ids, Optional[List[str]]), + work_location_ids=utils.unmarshal(work_location_ids, Optional[List[str]]), + work_emails=utils.unmarshal(work_emails, Optional[List[str]]), + personal_emails=utils.unmarshal(personal_emails, Optional[List[str]]), custom_fields=custom_fields, ) @@ -207,14 +209,14 @@ async def get_employees_async( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, - employment_statuses: Optional[List[str]] = None, - group_ids: Optional[List[str]] = None, - legal_entity_ids: Optional[List[str]] = None, - work_location_ids: Optional[List[str]] = None, - work_emails: Optional[List[str]] = None, - personal_emails: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, + employment_statuses: Optional[Iterable[str]] = None, + group_ids: Optional[Iterable[str]] = None, + legal_entity_ids: Optional[Iterable[str]] = None, + work_location_ids: Optional[Iterable[str]] = None, + work_emails: Optional[Iterable[str]] = None, + personal_emails: Optional[Iterable[str]] = None, custom_fields: Optional[str] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, @@ -288,14 +290,16 @@ async def get_employees_async( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, - employment_statuses=employment_statuses, - group_ids=group_ids, - legal_entity_ids=legal_entity_ids, - work_location_ids=work_location_ids, - work_emails=work_emails, - personal_emails=personal_emails, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), + employment_statuses=utils.unmarshal( + employment_statuses, Optional[List[str]] + ), + group_ids=utils.unmarshal(group_ids, Optional[List[str]]), + legal_entity_ids=utils.unmarshal(legal_entity_ids, Optional[List[str]]), + work_location_ids=utils.unmarshal(work_location_ids, Optional[List[str]]), + work_emails=utils.unmarshal(work_emails, Optional[List[str]]), + personal_emails=utils.unmarshal(personal_emails, Optional[List[str]]), custom_fields=custom_fields, ) @@ -720,7 +724,7 @@ def create_employee_with_form( self, *, properties: Union[ - Dict[str, models.Schema4], Dict[str, models.Schema4TypedDict] + Mapping[str, models.Schema4], Mapping[str, models.Schema4TypedDict] ], staffing_entity_id: Optional[str] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, @@ -778,7 +782,7 @@ def create_employee_with_form( request = models.PostHrisEmployeesFormRequestBody( staffing_entity_id=staffing_entity_id, - properties=properties, + properties=utils.unmarshal(properties, Dict[str, models.Schema4]), ) req = self._build_request( @@ -840,7 +844,7 @@ async def create_employee_with_form_async( self, *, properties: Union[ - Dict[str, models.Schema4], Dict[str, models.Schema4TypedDict] + Mapping[str, models.Schema4], Mapping[str, models.Schema4TypedDict] ], staffing_entity_id: Optional[str] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, @@ -898,7 +902,7 @@ async def create_employee_with_form_async( request = models.PostHrisEmployeesFormRequestBody( staffing_entity_id=staffing_entity_id, - properties=properties, + properties=utils.unmarshal(properties, Dict[str, models.Schema4]), ) req = self._build_request_async( @@ -1204,8 +1208,8 @@ def get_employee_document_categories( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, timeout_ms: Optional[int] = None, @@ -1251,8 +1255,8 @@ def get_employee_document_categories( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), ) req = self._build_request( @@ -1344,8 +1348,8 @@ async def get_employee_document_categories_async( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, timeout_ms: Optional[int] = None, @@ -1391,8 +1395,8 @@ async def get_employee_document_categories_async( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), ) req = self._build_request_async( @@ -1489,9 +1493,9 @@ def get_groups( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, - types: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, + types: Optional[Iterable[str]] = None, name_contains: Optional[str] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, @@ -1542,9 +1546,9 @@ def get_groups( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, - types=types, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), + types=utils.unmarshal(types, Optional[List[str]]), name_contains=name_contains, ) @@ -1639,9 +1643,9 @@ async def get_groups_async( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, - types: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, + types: Optional[Iterable[str]] = None, name_contains: Optional[str] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, @@ -1692,9 +1696,9 @@ async def get_groups_async( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, - types=types, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), + types=utils.unmarshal(types, Optional[List[str]]), name_contains=name_contains, ) @@ -1792,8 +1796,8 @@ def get_employments( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, timeout_ms: Optional[int] = None, @@ -1839,8 +1843,8 @@ def get_employments( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), ) req = self._build_request( @@ -1932,8 +1936,8 @@ async def get_employments_async( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, timeout_ms: Optional[int] = None, @@ -1979,8 +1983,8 @@ async def get_employments_async( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), ) req = self._build_request_async( @@ -2075,8 +2079,8 @@ def get_locations( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, name_contains: Optional[str] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, @@ -2124,8 +2128,8 @@ def get_locations( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), name_contains=name_contains, ) @@ -2219,8 +2223,8 @@ async def get_locations_async( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, name_contains: Optional[str] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, @@ -2268,8 +2272,8 @@ async def get_locations_async( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), name_contains=name_contains, ) @@ -2366,8 +2370,8 @@ def get_absence_types( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, timeout_ms: Optional[int] = None, @@ -2413,8 +2417,8 @@ def get_absence_types( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), ) req = self._build_request( @@ -2506,8 +2510,8 @@ async def get_absence_types_async( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, timeout_ms: Optional[int] = None, @@ -2553,8 +2557,8 @@ async def get_absence_types_async( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), ) req = self._build_request_async( @@ -2649,8 +2653,8 @@ def get_time_off_balances( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, employee_id: Optional[str] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, @@ -2704,8 +2708,8 @@ def get_time_off_balances( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), employee_id=employee_id, ) @@ -2799,8 +2803,8 @@ async def get_time_off_balances_async( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, employee_id: Optional[str] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, @@ -2854,8 +2858,8 @@ async def get_time_off_balances_async( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), employee_id=employee_id, ) @@ -2952,11 +2956,11 @@ def get_absences( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, date_from: Optional[datetime] = None, date_until: Optional[datetime] = None, - type_ids: Optional[List[str]] = None, + type_ids: Optional[Iterable[str]] = None, employee_id: Optional[str] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, @@ -3013,11 +3017,11 @@ def get_absences( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), date_from=date_from, date_until=date_until, - type_ids=type_ids, + type_ids=utils.unmarshal(type_ids, Optional[List[str]]), employee_id=employee_id, ) @@ -3114,11 +3118,11 @@ async def get_absences_async( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, date_from: Optional[datetime] = None, date_until: Optional[datetime] = None, - type_ids: Optional[List[str]] = None, + type_ids: Optional[Iterable[str]] = None, employee_id: Optional[str] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, @@ -3175,11 +3179,11 @@ async def get_absences_async( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), date_from=date_from, date_until=date_until, - type_ids=type_ids, + type_ids=utils.unmarshal(type_ids, Optional[List[str]]), employee_id=employee_id, ) @@ -3825,8 +3829,8 @@ def get_legal_entities( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, name_contains: Optional[str] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, @@ -3874,8 +3878,8 @@ def get_legal_entities( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), name_contains=name_contains, ) @@ -3969,8 +3973,8 @@ async def get_legal_entities_async( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, name_contains: Optional[str] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, @@ -4018,8 +4022,8 @@ async def get_legal_entities_async( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), name_contains=name_contains, ) @@ -4116,8 +4120,8 @@ def get_timesheets( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, employee_id: Optional[str] = None, started_before: Optional[datetime] = None, started_after: Optional[datetime] = None, @@ -4179,8 +4183,8 @@ def get_timesheets( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), employee_id=employee_id, started_before=started_before, started_after=started_after, @@ -4282,8 +4286,8 @@ async def get_timesheets_async( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, employee_id: Optional[str] = None, started_before: Optional[datetime] = None, started_after: Optional[datetime] = None, @@ -4345,8 +4349,8 @@ async def get_timesheets_async( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), employee_id=employee_id, started_before=started_before, started_after=started_after, @@ -4451,8 +4455,8 @@ def get_performance_review_cycles( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, timeout_ms: Optional[int] = None, @@ -4500,8 +4504,8 @@ def get_performance_review_cycles( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), ) req = self._build_request( @@ -4593,8 +4597,8 @@ async def get_performance_review_cycles_async( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, timeout_ms: Optional[int] = None, @@ -4642,8 +4646,8 @@ async def get_performance_review_cycles_async( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), ) req = self._build_request_async( @@ -4740,11 +4744,11 @@ def get_performance_reviews( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, - types: Optional[List[str]] = None, - review_cycle_ids: Optional[List[str]] = None, - reviewee_ids: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, + types: Optional[Iterable[str]] = None, + review_cycle_ids: Optional[Iterable[str]] = None, + reviewee_ids: Optional[Iterable[str]] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, timeout_ms: Optional[int] = None, @@ -4805,11 +4809,11 @@ def get_performance_reviews( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, - types=types, - review_cycle_ids=review_cycle_ids, - reviewee_ids=reviewee_ids, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), + types=utils.unmarshal(types, Optional[List[str]]), + review_cycle_ids=utils.unmarshal(review_cycle_ids, Optional[List[str]]), + reviewee_ids=utils.unmarshal(reviewee_ids, Optional[List[str]]), ) req = self._build_request( @@ -4904,11 +4908,11 @@ async def get_performance_reviews_async( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, - types: Optional[List[str]] = None, - review_cycle_ids: Optional[List[str]] = None, - reviewee_ids: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, + types: Optional[Iterable[str]] = None, + review_cycle_ids: Optional[Iterable[str]] = None, + reviewee_ids: Optional[Iterable[str]] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, timeout_ms: Optional[int] = None, @@ -4969,11 +4973,11 @@ async def get_performance_reviews_async( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, - types=types, - review_cycle_ids=review_cycle_ids, - reviewee_ids=reviewee_ids, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), + types=utils.unmarshal(types, Optional[List[str]]), + review_cycle_ids=utils.unmarshal(review_cycle_ids, Optional[List[str]]), + reviewee_ids=utils.unmarshal(reviewee_ids, Optional[List[str]]), ) req = self._build_request_async( @@ -5073,10 +5077,10 @@ def get_staffing_entities( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, - model_types: Optional[List[str]] = None, - statuses: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, + model_types: Optional[Iterable[str]] = None, + statuses: Optional[Iterable[str]] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, timeout_ms: Optional[int] = None, @@ -5146,10 +5150,10 @@ def get_staffing_entities( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, - model_types=model_types, - statuses=statuses, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), + model_types=utils.unmarshal(model_types, Optional[List[str]]), + statuses=utils.unmarshal(statuses, Optional[List[str]]), ) req = self._build_request( @@ -5243,10 +5247,10 @@ async def get_staffing_entities_async( updated_after: Optional[datetime] = None, include_deleted: Optional[bool] = False, ignore_unsupported_filters: Optional[bool] = False, - ids: Optional[List[str]] = None, - remote_ids: Optional[List[str]] = None, - model_types: Optional[List[str]] = None, - statuses: Optional[List[str]] = None, + ids: Optional[Iterable[str]] = None, + remote_ids: Optional[Iterable[str]] = None, + model_types: Optional[Iterable[str]] = None, + statuses: Optional[Iterable[str]] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, timeout_ms: Optional[int] = None, @@ -5316,10 +5320,10 @@ async def get_staffing_entities_async( updated_after=updated_after, include_deleted=include_deleted, ignore_unsupported_filters=ignore_unsupported_filters, - ids=ids, - remote_ids=remote_ids, - model_types=model_types, - statuses=statuses, + ids=utils.unmarshal(ids, Optional[List[str]]), + remote_ids=utils.unmarshal(remote_ids, Optional[List[str]]), + model_types=utils.unmarshal(model_types, Optional[List[str]]), + statuses=utils.unmarshal(statuses, Optional[List[str]]), ) req = self._build_request_async( diff --git a/src/kombo/models/__init__.py b/src/kombo/models/__init__.py index be1fd21..d25f8e8 100644 --- a/src/kombo/models/__init__.py +++ b/src/kombo/models/__init__.py @@ -1395,6 +1395,7 @@ PostAtsCandidatesRequestBodyAdditionalPhoneNumber, PostAtsCandidatesRequestBodyAdditionalPhoneNumberType, PostAtsCandidatesRequestBodyAdditionalPhoneNumberTypedDict, + PostAtsCandidatesRequestBodyAktiv, PostAtsCandidatesRequestBodyAnswer, PostAtsCandidatesRequestBodyAnswerTypedDict, PostAtsCandidatesRequestBodyAnswerUnion, @@ -1703,6 +1704,7 @@ PostAtsJobsJobIDApplicationsRequestBodyAdditionalPhoneNumber, PostAtsJobsJobIDApplicationsRequestBodyAdditionalPhoneNumberType, PostAtsJobsJobIDApplicationsRequestBodyAdditionalPhoneNumberTypedDict, + PostAtsJobsJobIDApplicationsRequestBodyAktiv, PostAtsJobsJobIDApplicationsRequestBodyAnswer, PostAtsJobsJobIDApplicationsRequestBodyAnswerTypedDict, PostAtsJobsJobIDApplicationsRequestBodyAnswerUnion, @@ -3300,6 +3302,7 @@ "PostAtsCandidatesRequestBodyAdditionalPhoneNumber", "PostAtsCandidatesRequestBodyAdditionalPhoneNumberType", "PostAtsCandidatesRequestBodyAdditionalPhoneNumberTypedDict", + "PostAtsCandidatesRequestBodyAktiv", "PostAtsCandidatesRequestBodyAnswer", "PostAtsCandidatesRequestBodyAnswerTypedDict", "PostAtsCandidatesRequestBodyAnswerUnion", @@ -3593,6 +3596,7 @@ "PostAtsJobsJobIDApplicationsRequestBodyAdditionalPhoneNumber", "PostAtsJobsJobIDApplicationsRequestBodyAdditionalPhoneNumberType", "PostAtsJobsJobIDApplicationsRequestBodyAdditionalPhoneNumberTypedDict", + "PostAtsJobsJobIDApplicationsRequestBodyAktiv", "PostAtsJobsJobIDApplicationsRequestBodyAnswer", "PostAtsJobsJobIDApplicationsRequestBodyAnswerTypedDict", "PostAtsJobsJobIDApplicationsRequestBodyAnswerUnion", @@ -5213,6 +5217,7 @@ "PostAtsCandidatesRequestBodyAdditionalPhoneNumber": ".postatscandidatesrequestbody", "PostAtsCandidatesRequestBodyAdditionalPhoneNumberType": ".postatscandidatesrequestbody", "PostAtsCandidatesRequestBodyAdditionalPhoneNumberTypedDict": ".postatscandidatesrequestbody", + "PostAtsCandidatesRequestBodyAktiv": ".postatscandidatesrequestbody", "PostAtsCandidatesRequestBodyAnswer": ".postatscandidatesrequestbody", "PostAtsCandidatesRequestBodyAnswerTypedDict": ".postatscandidatesrequestbody", "PostAtsCandidatesRequestBodyAnswerUnion": ".postatscandidatesrequestbody", @@ -5509,6 +5514,7 @@ "PostAtsJobsJobIDApplicationsRequestBodyAdditionalPhoneNumber": ".postatsjobsjobidapplicationsrequestbody", "PostAtsJobsJobIDApplicationsRequestBodyAdditionalPhoneNumberType": ".postatsjobsjobidapplicationsrequestbody", "PostAtsJobsJobIDApplicationsRequestBodyAdditionalPhoneNumberTypedDict": ".postatsjobsjobidapplicationsrequestbody", + "PostAtsJobsJobIDApplicationsRequestBodyAktiv": ".postatsjobsjobidapplicationsrequestbody", "PostAtsJobsJobIDApplicationsRequestBodyAnswer": ".postatsjobsjobidapplicationsrequestbody", "PostAtsJobsJobIDApplicationsRequestBodyAnswerTypedDict": ".postatsjobsjobidapplicationsrequestbody", "PostAtsJobsJobIDApplicationsRequestBodyAnswerUnion": ".postatsjobsjobidapplicationsrequestbody", diff --git a/src/kombo/models/postatscandidatesrequestbody.py b/src/kombo/models/postatscandidatesrequestbody.py index 8b75b53..10c979a 100644 --- a/src/kombo/models/postatscandidatesrequestbody.py +++ b/src/kombo/models/postatscandidatesrequestbody.py @@ -2400,6 +2400,13 @@ def serialize_model(self, handler): return m +PostAtsCandidatesRequestBodyAktiv = Literal[ + "Ja", + "Nein", +] +r"""Whether the candidate is created as active (`Ja`) or inactive (`Nein`) in Coveto. If omitted, Coveto applies its default (active).""" + + class PostAtsCandidatesRequestBodyCovetorestCandidateTypedDict(TypedDict): r"""Additional candidate fields that will be passed to the Coveto candidate creation.""" @@ -2407,6 +2414,8 @@ class PostAtsCandidatesRequestBodyCovetorestCandidateTypedDict(TypedDict): r"""The mandant field for the candidate in Coveto.""" status: NotRequired[int] r"""The numeric status ID to assign to the candidate on creation in Coveto. Refer to your Coveto `/bewerber-status` endpoint for available IDs.""" + aktiv: NotRequired[PostAtsCandidatesRequestBodyAktiv] + r"""Whether the candidate is created as active (`Ja`) or inactive (`Nein`) in Coveto. If omitted, Coveto applies its default (active).""" class PostAtsCandidatesRequestBodyCovetorestCandidate(BaseModel): @@ -2418,9 +2427,12 @@ class PostAtsCandidatesRequestBodyCovetorestCandidate(BaseModel): status: Optional[int] = None r"""The numeric status ID to assign to the candidate on creation in Coveto. Refer to your Coveto `/bewerber-status` endpoint for available IDs.""" + aktiv: Optional[PostAtsCandidatesRequestBodyAktiv] = None + r"""Whether the candidate is created as active (`Ja`) or inactive (`Nein`) in Coveto. If omitted, Coveto applies its default (active).""" + @model_serializer(mode="wrap") def serialize_model(self, handler): - optional_fields = set(["mandant", "status"]) + optional_fields = set(["mandant", "status", "aktiv"]) serialized = handler(self) m = {} diff --git a/src/kombo/models/postatsjobsjobidapplicationsrequestbody.py b/src/kombo/models/postatsjobsjobidapplicationsrequestbody.py index 21542d5..09113ee 100644 --- a/src/kombo/models/postatsjobsjobidapplicationsrequestbody.py +++ b/src/kombo/models/postatsjobsjobidapplicationsrequestbody.py @@ -2249,6 +2249,13 @@ def serialize_model(self, handler): return m +PostAtsJobsJobIDApplicationsRequestBodyAktiv = Literal[ + "Ja", + "Nein", +] +r"""Whether the candidate is created as active (`Ja`) or inactive (`Nein`) in Coveto. If omitted, Coveto applies its default (active).""" + + class PostAtsJobsJobIDApplicationsRequestBodyCovetorestCandidateTypedDict(TypedDict): r"""Additional candidate fields that will be passed to the Coveto candidate creation.""" @@ -2256,6 +2263,8 @@ class PostAtsJobsJobIDApplicationsRequestBodyCovetorestCandidateTypedDict(TypedD r"""The mandant field for the candidate in Coveto.""" status: NotRequired[int] r"""The numeric status ID to assign to the candidate on creation in Coveto. Refer to your Coveto `/bewerber-status` endpoint for available IDs.""" + aktiv: NotRequired[PostAtsJobsJobIDApplicationsRequestBodyAktiv] + r"""Whether the candidate is created as active (`Ja`) or inactive (`Nein`) in Coveto. If omitted, Coveto applies its default (active).""" class PostAtsJobsJobIDApplicationsRequestBodyCovetorestCandidate(BaseModel): @@ -2267,9 +2276,12 @@ class PostAtsJobsJobIDApplicationsRequestBodyCovetorestCandidate(BaseModel): status: Optional[int] = None r"""The numeric status ID to assign to the candidate on creation in Coveto. Refer to your Coveto `/bewerber-status` endpoint for available IDs.""" + aktiv: Optional[PostAtsJobsJobIDApplicationsRequestBodyAktiv] = None + r"""Whether the candidate is created as active (`Ja`) or inactive (`Nein`) in Coveto. If omitted, Coveto applies its default (active).""" + @model_serializer(mode="wrap") def serialize_model(self, handler): - optional_fields = set(["mandant", "status"]) + optional_fields = set(["mandant", "status", "aktiv"]) serialized = handler(self) m = {} diff --git a/src/kombo/models/postconnectcreatelinkrequestbody.py b/src/kombo/models/postconnectcreatelinkrequestbody.py index c0cd102..e0452b9 100644 --- a/src/kombo/models/postconnectcreatelinkrequestbody.py +++ b/src/kombo/models/postconnectcreatelinkrequestbody.py @@ -128,6 +128,7 @@ "logicmelon", "loxo", "kula", + "pageup", "workdaycustomreport", "workdaycustomreportsftp", "ukgprowfm", @@ -209,6 +210,7 @@ "sftpfetch", "360learning", "talentlms", + "docebo", "udemy", "linkedinlearning", "moodle", diff --git a/src/kombo/types/base64fileinput.py b/src/kombo/types/base64fileinput.py index 25fc539..862566f 100644 --- a/src/kombo/types/base64fileinput.py +++ b/src/kombo/types/base64fileinput.py @@ -23,7 +23,11 @@ def encode_base64_file_input(value: Any) -> Any: with open(value, "rb") as fh: binary = fh.read() else: + # Restore position after reading: pydantic may validate the same stream more than once. + position = value.tell() if value.seekable() else None binary = value.read() + if position is not None: + value.seek(position) if isinstance(binary, str): binary = binary.encode() if not isinstance(binary, (bytes, bytearray)): diff --git a/src/kombo/utils/eventstreaming.py b/src/kombo/utils/eventstreaming.py index 3bdcd6d..a8d4fe5 100644 --- a/src/kombo/utils/eventstreaming.py +++ b/src/kombo/utils/eventstreaming.py @@ -7,6 +7,7 @@ Any, Callable, Generic, + List, TypeVar, Optional, Generator, @@ -53,6 +54,9 @@ def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): + self.close() + + def close(self): self._closed = True self.response.close() @@ -92,6 +96,9 @@ async def __aenter__(self): return self async def __aexit__(self, exc_type, exc_val, exc_tb): + await self.close() + + async def close(self): self._closed = True await self.response.aclose() @@ -114,6 +121,7 @@ class ServerEvent: b"\n\r", b"\n\n", ] +MAX_BOUNDARY_LEN = max(len(b) for b in MESSAGE_BOUNDARIES) UTF8_BOM = b"\xef\xbb\xbf" @@ -124,52 +132,56 @@ async def stream_events_async( sentinel: Optional[str] = None, data_required: bool = True, ) -> AsyncGenerator[T, None]: - buffer = bytearray() - position = 0 - event_id: Optional[str] = None - async for chunk in response.aiter_bytes(): - if len(buffer) == 0 and chunk.startswith(UTF8_BOM): - chunk = chunk[len(UTF8_BOM) :] - buffer += chunk - for i in range(position, len(buffer)): - char = buffer[i : i + 1] - seq: Optional[bytes] = None - if char in [b"\r", b"\n"]: - for boundary in MESSAGE_BOUNDARIES: - seq = _peek_sequence(i, buffer, boundary) - if seq is not None: - break - if seq is None: - continue - - block = buffer[position:i] - position = i + len(seq) - event, discard, event_id = _parse_event( - raw=block, - decoder=decoder, - sentinel=sentinel, - event_id=event_id, - data_required=data_required, - ) - if event is not None: - yield event - if discard: - await response.aclose() - return - - if position > 0: - buffer = buffer[position:] - position = 0 - - event, discard, _ = _parse_event( - raw=buffer, - decoder=decoder, - sentinel=sentinel, - event_id=event_id, - data_required=data_required, - ) - if event is not None: - yield event + try: + buffer = bytearray() + position = 0 + event_id: Optional[str] = None + async for chunk in response.aiter_bytes(): + if len(buffer) == 0 and chunk.startswith(UTF8_BOM): + chunk = chunk[len(UTF8_BOM) :] + old_len = len(buffer) + buffer += chunk + search_start = max(position, old_len - MAX_BOUNDARY_LEN + 1) + for i in range(search_start, len(buffer)): + char = buffer[i : i + 1] + seq: Optional[bytes] = None + if char in [b"\r", b"\n"]: + for boundary in MESSAGE_BOUNDARIES: + seq = _peek_sequence(i, buffer, boundary) + if seq is not None: + break + if seq is None: + continue + + block = buffer[position:i] + position = i + len(seq) + event, discard, event_id = _parse_event( + raw=block, + decoder=decoder, + sentinel=sentinel, + event_id=event_id, + data_required=data_required, + ) + if event is not None: + yield event + if discard: + return + + if position > 0: + buffer = buffer[position:] + position = 0 + + event, discard, _ = _parse_event( + raw=buffer, + decoder=decoder, + sentinel=sentinel, + event_id=event_id, + data_required=data_required, + ) + if event is not None: + yield event + finally: + await response.aclose() def stream_events( @@ -178,52 +190,56 @@ def stream_events( sentinel: Optional[str] = None, data_required: bool = True, ) -> Generator[T, None, None]: - buffer = bytearray() - position = 0 - event_id: Optional[str] = None - for chunk in response.iter_bytes(): - if len(buffer) == 0 and chunk.startswith(UTF8_BOM): - chunk = chunk[len(UTF8_BOM) :] - buffer += chunk - for i in range(position, len(buffer)): - char = buffer[i : i + 1] - seq: Optional[bytes] = None - if char in [b"\r", b"\n"]: - for boundary in MESSAGE_BOUNDARIES: - seq = _peek_sequence(i, buffer, boundary) - if seq is not None: - break - if seq is None: - continue - - block = buffer[position:i] - position = i + len(seq) - event, discard, event_id = _parse_event( - raw=block, - decoder=decoder, - sentinel=sentinel, - event_id=event_id, - data_required=data_required, - ) - if event is not None: - yield event - if discard: - response.close() - return - - if position > 0: - buffer = buffer[position:] - position = 0 - - event, discard, _ = _parse_event( - raw=buffer, - decoder=decoder, - sentinel=sentinel, - event_id=event_id, - data_required=data_required, - ) - if event is not None: - yield event + try: + buffer = bytearray() + position = 0 + event_id: Optional[str] = None + for chunk in response.iter_bytes(): + if len(buffer) == 0 and chunk.startswith(UTF8_BOM): + chunk = chunk[len(UTF8_BOM) :] + old_len = len(buffer) + buffer += chunk + search_start = max(position, old_len - MAX_BOUNDARY_LEN + 1) + for i in range(search_start, len(buffer)): + char = buffer[i : i + 1] + seq: Optional[bytes] = None + if char in [b"\r", b"\n"]: + for boundary in MESSAGE_BOUNDARIES: + seq = _peek_sequence(i, buffer, boundary) + if seq is not None: + break + if seq is None: + continue + + block = buffer[position:i] + position = i + len(seq) + event, discard, event_id = _parse_event( + raw=block, + decoder=decoder, + sentinel=sentinel, + event_id=event_id, + data_required=data_required, + ) + if event is not None: + yield event + if discard: + return + + if position > 0: + buffer = buffer[position:] + position = 0 + + event, discard, _ = _parse_event( + raw=buffer, + decoder=decoder, + sentinel=sentinel, + event_id=event_id, + data_required=data_required, + ) + if event is not None: + yield event + finally: + response.close() def _parse_event( @@ -238,7 +254,7 @@ def _parse_event( lines = re.split(r"\r?\n|\r", block) publish = False event = ServerEvent() - data = "" + data_parts: List[str] = [] for line in lines: if not line: continue @@ -259,7 +275,7 @@ def _parse_event( event.event = value publish = True elif field == "data": - data += value + "\n" + data_parts.append(value) publish = True elif field == "id": publish = True @@ -271,16 +287,17 @@ def _parse_event( publish = True event.id = event_id + has_data = bool(data_parts) + data = "\n".join(data_parts) - if sentinel and data == f"{sentinel}\n": + if sentinel and has_data and data == sentinel: return None, True, event_id # Skip data-less events when data is required - if not data and publish and data_required: + if not has_data and publish and data_required: return None, False, event_id - if data: - data = data[:-1] + if has_data: try: event.data = json.loads(data) except json.JSONDecodeError: @@ -291,7 +308,7 @@ def _parse_event( out_dict = { k: v for k, v in asdict(event).items() - if v is not None or (k == "data" and data) + if v is not None or (k == "data" and has_data) } out = decoder(json.dumps(out_dict)) diff --git a/src/kombo/utils/forms.py b/src/kombo/utils/forms.py index f961e76..fdf0dc9 100644 --- a/src/kombo/utils/forms.py +++ b/src/kombo/utils/forms.py @@ -1,5 +1,6 @@ """Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" +import io from typing import ( Any, Dict, @@ -103,6 +104,10 @@ def _extract_file_properties(file_obj: Any) -> Tuple[str, Any, Any]: if file_metadata.content: content = getattr(file_obj, file_field_name, None) + if isinstance(content, io.TextIOBase): + content = content.read().encode( + getattr(content, "encoding", None) or "utf-8" + ) elif file_field_name == "content_type": content_type = getattr(file_obj, file_field_name, None) else: diff --git a/src/kombo/utils/retries.py b/src/kombo/utils/retries.py index af07d4e..ca7b59e 100644 --- a/src/kombo/utils/retries.py +++ b/src/kombo/utils/retries.py @@ -11,10 +11,13 @@ class BackoffStrategy: + """Exponential backoff strategy configuration.""" + initial_interval: int max_interval: int exponent: float max_elapsed_time: int + jitter_ms: Optional[int] def __init__( self, @@ -22,24 +25,63 @@ def __init__( max_interval: int, exponent: float, max_elapsed_time: int, + jitter_ms: Optional[int] = None, ): + """Initialize a backoff strategy. + + Args: + initial_interval: Initial retry interval in milliseconds. + max_interval: Maximum retry interval in milliseconds. + exponent: Base of the exponential backoff; the interval grows as + ``initial_interval * exponent ** retries``. + max_elapsed_time: Maximum total elapsed time in milliseconds. + jitter_ms: Additive jitter bound in milliseconds. When set, adds a random + value in ``[0, jitter_ms]`` to each computed backoff interval (default + ``+[0, 1s]``). + + Note: + When a response carries a ``Retry-After`` or ``retry-after-ms`` header, + that delay is used as-is and the sleep-shaping parameters + (``initial_interval``, ``max_interval``, ``exponent``, ``jitter_ms``) are + ignored for that attempt. + """ + if jitter_ms is not None and jitter_ms < 0: + raise ValueError("jitter_ms must be >= 0") self.initial_interval = initial_interval self.max_interval = max_interval self.exponent = exponent self.max_elapsed_time = max_elapsed_time + self.jitter_ms = jitter_ms class RetryConfig: + """Runtime retry configuration.""" + strategy: str backoff: BackoffStrategy retry_connection_errors: bool + status_codes_override: Optional[List[str]] def __init__( - self, strategy: str, backoff: BackoffStrategy, retry_connection_errors: bool + self, + strategy: str, + backoff: BackoffStrategy, + retry_connection_errors: bool, + status_codes_override: Optional[List[str]] = None, ): + """Initialize a retry configuration. + + Args: + strategy: Retry strategy: ``"none"`` or ``"backoff"``. + backoff: Backoff parameters. + retry_connection_errors: Whether to also retry transport-level connection errors. + status_codes_override: Retryable HTTP status codes that take precedence over the + per-operation defaults when non-empty. + """ self.strategy = strategy self.backoff = backoff self.retry_connection_errors = retry_connection_errors + self.status_codes_override = status_codes_override class Retries: @@ -48,7 +90,7 @@ class Retries: def __init__(self, config: RetryConfig, status_codes: List[str]): self.config = config - self.status_codes = status_codes + self.status_codes = config.status_codes_override or status_codes class TemporaryError(Exception): @@ -93,12 +135,28 @@ def _parse_retry_after_header(response: httpx.Response) -> Optional[int]: return None +def _parse_retry_after_ms_header(response: httpx.Response) -> Optional[int]: + retry_after_ms_header = response.headers.get("retry-after-ms") + if not retry_after_ms_header: + return None + + try: + milliseconds = float(retry_after_ms_header) + if milliseconds >= 0: + return round(milliseconds) + except (OverflowError, ValueError): + pass + + return None + + def _get_sleep_interval( exception: Exception, initial_interval: int, max_interval: int, exponent: float, retries: int, + jitter_ms: Optional[int] = None, ) -> float: """Get sleep interval for retry with exponential backoff. @@ -108,6 +166,7 @@ def _get_sleep_interval( max_interval: Maximum retry interval in milliseconds. exponent: Base for exponential backoff calculation. retries: Current retry attempt count. + jitter_ms: Additive jitter bound in ms; see ``BackoffStrategy.jitter_ms``. Returns: Sleep interval in seconds. @@ -119,7 +178,11 @@ def _get_sleep_interval( ): return exception.retry_after / 1000 - sleep = (initial_interval / 1000) * exponent**retries + random.uniform(0, 1) + sleep = (initial_interval / 1000) * exponent**retries + if jitter_ms is not None: + sleep += random.uniform(0, jitter_ms / 1000) + else: + sleep += random.uniform(0, 1) return min(sleep, max_interval / 1000) @@ -162,6 +225,7 @@ def do_request() -> httpx.Response: retries.config.backoff.max_interval, retries.config.backoff.exponent, retries.config.backoff.max_elapsed_time, + retries.config.backoff.jitter_ms, ) return func() @@ -206,6 +270,7 @@ async def do_request() -> httpx.Response: retries.config.backoff.max_interval, retries.config.backoff.exponent, retries.config.backoff.max_elapsed_time, + retries.config.backoff.jitter_ms, ) return await func() @@ -217,6 +282,7 @@ def retry_with_backoff( max_interval=60000, exponent=1.5, max_elapsed_time=3600000, + jitter_ms=None, ): start = round(time.time() * 1000) retries = 0 @@ -234,8 +300,17 @@ def retry_with_backoff( raise + if isinstance(exception, TemporaryError): + retry_after_ms = _parse_retry_after_ms_header(exception.response) + if retry_after_ms is not None: + exception.retry_after = retry_after_ms sleep = _get_sleep_interval( - exception, initial_interval, max_interval, exponent, retries + exception, + initial_interval, + max_interval, + exponent, + retries, + jitter_ms=jitter_ms, ) time.sleep(sleep) retries += 1 @@ -247,6 +322,7 @@ async def retry_with_backoff_async( max_interval=60000, exponent=1.5, max_elapsed_time=3600000, + jitter_ms=None, ): start = round(time.time() * 1000) retries = 0 @@ -264,8 +340,17 @@ async def retry_with_backoff_async( raise + if isinstance(exception, TemporaryError): + retry_after_ms = _parse_retry_after_ms_header(exception.response) + if retry_after_ms is not None: + exception.retry_after = retry_after_ms sleep = _get_sleep_interval( - exception, initial_interval, max_interval, exponent, retries + exception, + initial_interval, + max_interval, + exponent, + retries, + jitter_ms=jitter_ms, ) await asyncio.sleep(sleep) retries += 1 diff --git a/src/kombo/utils/serializers.py b/src/kombo/utils/serializers.py index d2149f8..1031ed9 100644 --- a/src/kombo/utils/serializers.py +++ b/src/kombo/utils/serializers.py @@ -4,7 +4,7 @@ import functools import json import typing -from typing import Any, Dict, List, Tuple, Union, get_args +from typing import Any, Dict, Iterable, List, Mapping, Tuple, Union, get_args import typing_extensions from typing_extensions import get_origin @@ -113,10 +113,12 @@ def validate(c): def unmarshal_json(raw, typ: Any) -> Any: - return unmarshal(from_json(raw), typ) + return unmarshal(from_json(raw), typ, coerce_iterables=False) -def unmarshal(val, typ: Any) -> Any: +def unmarshal(val, typ: Any, coerce_iterables: bool = True) -> Any: + if coerce_iterables: + val = _coerce_iterables_for_type(val, typ) unmarshaller = create_model( "Unmarshaller", body=(typ, ...), @@ -193,9 +195,88 @@ def get_pydantic_model(data: Any, typ: Any) -> Any: if not _contains_pydantic_model(data): return unmarshal(data, typ) + return _coerce_iterables_for_type(data, typ) + + +def _coerce_iterables_for_type(data: Any, typ: Any) -> Any: + if data is None or isinstance(data, (BaseModel, Unset)): + return data + + typ = _resolve_type_alias(typ) + origin = get_origin(typ) + + if _is_annotated_type(origin): + args = get_args(typ) + return _coerce_iterables_for_type(data, args[0]) if args else data + + if is_union(origin): + for arg in (arg for arg in get_args(typ) if arg is not type(None)): + coerced = _coerce_iterables_for_type(data, arg) + if coerced is not data: + return coerced + return data + + if _is_list_type(typ): + item_type = get_args(typ)[0] if get_args(typ) else Any + if isinstance(data, (str, bytes, bytearray, Mapping)): + return data + if isinstance(data, Iterable): + return [_coerce_iterables_for_type(item, item_type) for item in data] + return data + + if _is_mapping_type(typ): + value_type = get_args(typ)[1] if len(get_args(typ)) > 1 else Any + if isinstance(data, Mapping): + return { + key: _coerce_iterables_for_type(value, value_type) + for key, value in data.items() + } + return data + + if _is_pydantic_model_type(typ) and isinstance(data, Mapping): + coerced = None + for field_name, field in typ.model_fields.items(): + field_type = field.annotation + for key in (field_name, field.alias): + if key is not None and key in data: + value = data[key] if coerced is None else coerced[key] + coerced_value = _coerce_iterables_for_type(value, field_type) + if coerced_value is not value: + if coerced is None: + coerced = dict(data) + coerced[key] = coerced_value + return coerced if coerced is not None else data + return data +def _resolve_type_alias(typ: Any) -> Any: + return getattr(typ, "__value__", typ) + + +def _is_annotated_type(origin: Any) -> bool: + return any( + origin is typing_obj + for typing_obj in _get_typing_objects_by_name_of("Annotated") + ) + + +def _is_list_type(typ: Any) -> bool: + typ = _resolve_type_alias(typ) + return typ is list or get_origin(typ) is list + + +def _is_mapping_type(typ: Any) -> bool: + typ = _resolve_type_alias(typ) + origin = get_origin(typ) + mapping_origin = get_origin(Mapping[Any, Any]) + return typ in (dict, Dict, Mapping) or origin in (dict, Mapping, mapping_origin) + + +def _is_pydantic_model_type(typ: Any) -> bool: + return isinstance(typ, type) and issubclass(typ, BaseModel) + + def _contains_pydantic_model(data: Any) -> bool: if isinstance(data, BaseModel): return True diff --git a/uv.lock b/uv.lock index 2f5a745..5204ce5 100644 --- a/uv.lock +++ b/uv.lock @@ -191,7 +191,7 @@ wheels = [ [[package]] name = "kombo" -version = "1.2.0" +version = "1.3.0" source = { editable = "." } dependencies = [ { name = "httpcore" },