@@ -120,15 +120,10 @@ PyObject *aws_py_credentials_session_token(PyObject *self, PyObject *args) {
120120 */
121121struct credentials_provider_binding {
122122 struct aws_credentials_provider * native ;
123-
124- /* Dependencies that must outlive this.
125- * Note that different types of providers have different dependencies */
126- PyObject * bootstrap ;
127123};
128124
129125/* Finally clean up binding (after capsule destructor runs and credentials provider shutdown completes) */
130126static void s_credentials_provider_binding_clean_up (struct credentials_provider_binding * binding ) {
131- Py_XDECREF (binding -> bootstrap );
132127 aws_mem_release (aws_py_get_allocator (), binding );
133128}
134129
@@ -273,9 +268,6 @@ PyObject *aws_py_credentials_provider_new_chain_default(PyObject *self, PyObject
273268 /* From hereon, we need to clean up if errors occur.
274269 * Fortunately, the capsule destructor will clean up anything stored inside the binding */
275270
276- binding -> bootstrap = bootstrap_py ;
277- Py_INCREF (binding -> bootstrap );
278-
279271 struct aws_credentials_provider_chain_default_options options = {
280272 .bootstrap = bootstrap ,
281273 .shutdown_options = {s_credentials_provider_shutdown_complete , binding },
@@ -340,3 +332,215 @@ PyObject *aws_py_credentials_provider_new_static(PyObject *self, PyObject *args)
340332 Py_DECREF (capsule );
341333 return NULL ;
342334}
335+
336+ PyObject * aws_py_credentials_provider_new_profile (PyObject * self , PyObject * args ) {
337+ (void )self ;
338+ struct aws_allocator * allocator = aws_py_get_allocator ();
339+
340+ PyObject * bootstrap_py ;
341+ struct aws_byte_cursor profile_name ;
342+ struct aws_byte_cursor config_file_name ;
343+ struct aws_byte_cursor credentials_file_name ;
344+
345+ if (!PyArg_ParseTuple (
346+ args ,
347+ "Oz#z#z#" ,
348+ & bootstrap_py ,
349+ & profile_name .ptr ,
350+ & profile_name .len ,
351+ & config_file_name .ptr ,
352+ & config_file_name .len ,
353+ & credentials_file_name .ptr ,
354+ & credentials_file_name .len )) {
355+ return NULL ;
356+ }
357+
358+ struct aws_client_bootstrap * bootstrap = aws_py_get_client_bootstrap (bootstrap_py );
359+ if (!bootstrap ) {
360+ return NULL ;
361+ }
362+
363+ struct credentials_provider_binding * binding ;
364+ PyObject * capsule = s_new_credentials_provider_binding_and_capsule (& binding );
365+ if (!capsule ) {
366+ return NULL ;
367+ }
368+
369+ /* From hereon, we need to clean up if errors occur.
370+ * Fortunately, the capsule destructor will clean up anything stored inside the binding */
371+
372+ struct aws_credentials_provider_profile_options options = {
373+ .bootstrap = bootstrap ,
374+ .profile_name_override = profile_name ,
375+ .config_file_name_override = config_file_name ,
376+ .credentials_file_name_override = credentials_file_name ,
377+ .shutdown_options =
378+ {
379+ .shutdown_callback = s_credentials_provider_shutdown_complete ,
380+ .shutdown_user_data = binding ,
381+ },
382+ };
383+
384+ binding -> native = aws_credentials_provider_new_profile (allocator , & options );
385+ if (!binding -> native ) {
386+ PyErr_SetAwsLastError ();
387+ goto error ;
388+ }
389+
390+ return capsule ;
391+ error :
392+ Py_DECREF (capsule );
393+ return NULL ;
394+ }
395+
396+ PyObject * aws_py_credentials_provider_new_process (PyObject * self , PyObject * args ) {
397+ (void )self ;
398+ struct aws_allocator * allocator = aws_py_get_allocator ();
399+
400+ struct aws_byte_cursor profile_to_use ;
401+
402+ if (!PyArg_ParseTuple (args , "z#" , & profile_to_use .ptr , & profile_to_use .len )) {
403+ return NULL ;
404+ }
405+
406+ struct credentials_provider_binding * binding ;
407+ PyObject * capsule = s_new_credentials_provider_binding_and_capsule (& binding );
408+ if (!capsule ) {
409+ return NULL ;
410+ }
411+
412+ /* From hereon, we need to clean up if errors occur.
413+ * Fortunately, the capsule destructor will clean up anything stored inside the binding */
414+
415+ struct aws_credentials_provider_process_options options = {
416+ .profile_to_use = profile_to_use ,
417+ .shutdown_options =
418+ {
419+ .shutdown_callback = s_credentials_provider_shutdown_complete ,
420+ .shutdown_user_data = binding ,
421+ },
422+ };
423+
424+ binding -> native = aws_credentials_provider_new_process (allocator , & options );
425+ if (!binding -> native ) {
426+ PyErr_SetAwsLastError ();
427+ goto error ;
428+ }
429+
430+ return capsule ;
431+ error :
432+ Py_DECREF (capsule );
433+ return NULL ;
434+ }
435+
436+ PyObject * aws_py_credentials_provider_new_environment (PyObject * self , PyObject * args ) {
437+ (void )self ;
438+ (void )args ;
439+ struct aws_allocator * allocator = aws_py_get_allocator ();
440+
441+ struct credentials_provider_binding * binding ;
442+ PyObject * capsule = s_new_credentials_provider_binding_and_capsule (& binding );
443+ if (!capsule ) {
444+ return NULL ;
445+ }
446+
447+ /* From hereon, we need to clean up if errors occur.
448+ * Fortunately, the capsule destructor will clean up anything stored inside the binding */
449+
450+ struct aws_credentials_provider_environment_options options = {
451+ .shutdown_options =
452+ {
453+ .shutdown_callback = s_credentials_provider_shutdown_complete ,
454+ .shutdown_user_data = binding ,
455+ },
456+ };
457+
458+ binding -> native = aws_credentials_provider_new_environment (allocator , & options );
459+ if (!binding -> native ) {
460+ PyErr_SetAwsLastError ();
461+ goto error ;
462+ }
463+
464+ return capsule ;
465+ error :
466+ Py_DECREF (capsule );
467+ return NULL ;
468+ }
469+
470+ PyObject * aws_py_credentials_provider_new_chain (PyObject * self , PyObject * args ) {
471+ (void )self ;
472+ struct aws_allocator * allocator = aws_py_get_allocator ();
473+
474+ PyObject * providers_arg ;
475+
476+ if (!PyArg_ParseTuple (args , "O" , & providers_arg )) {
477+ return NULL ;
478+ }
479+
480+ /* From hereon, we need to clean up if errors occur.
481+ * Fortunately, the capsule destructor will clean up anything stored inside the binding */
482+ bool success = false;
483+ PyObject * providers_pyseq = NULL ;
484+ struct aws_credentials_provider * * providers_carray = NULL ;
485+ PyObject * capsule = NULL ;
486+
487+ /* Need temporary C-array of pointers to underlying aws_credentials_provider structs */
488+ providers_pyseq = PySequence_Fast (providers_arg , "Expected sequence of AwsCredentialsProviders" );
489+ if (!providers_pyseq ) {
490+ goto done ;
491+ }
492+ size_t provider_count = (size_t )PySequence_Fast_GET_SIZE (providers_pyseq );
493+ if (provider_count == 0 ) {
494+ PyErr_SetString (PyExc_ValueError , "Must supply at least one AwsCredentialsProvider." );
495+ goto done ;
496+ }
497+
498+ providers_carray = aws_mem_calloc (allocator , provider_count , sizeof (void * ));
499+ if (!providers_carray ) {
500+ PyErr_SetAwsLastError ();
501+ goto done ;
502+ }
503+
504+ for (size_t i = 0 ; i < provider_count ; ++ i ) {
505+ PyObject * provider_py = PySequence_Fast_GET_ITEM (providers_pyseq , i );
506+ providers_carray [i ] = aws_py_get_credentials_provider (provider_py );
507+ if (!providers_carray [i ]) {
508+ goto done ;
509+ }
510+ }
511+
512+ struct credentials_provider_binding * binding ;
513+ capsule = s_new_credentials_provider_binding_and_capsule (& binding );
514+ if (!capsule ) {
515+ goto done ;
516+ }
517+
518+ struct aws_credentials_provider_chain_options options = {
519+ .provider_count = provider_count ,
520+ .providers = providers_carray ,
521+ .shutdown_options =
522+ {
523+ .shutdown_callback = s_credentials_provider_shutdown_complete ,
524+ .shutdown_user_data = binding ,
525+ },
526+ };
527+
528+ binding -> native = aws_credentials_provider_new_chain (allocator , & options );
529+ if (!binding -> native ) {
530+ PyErr_SetAwsLastError ();
531+ goto done ;
532+ }
533+
534+ success = true;
535+
536+ done :
537+ Py_XDECREF (providers_pyseq );
538+ aws_mem_release (allocator , providers_carray );
539+
540+ if (success ) {
541+ return capsule ;
542+ }
543+
544+ Py_XDECREF (capsule );
545+ return NULL ;
546+ }
0 commit comments