CINXE.COM
peps/peps/pep-0667.rst at main · python/peps · GitHub
<!DOCTYPE html> <html lang="en" data-color-mode="auto" data-light-theme="light" data-dark-theme="dark" data-a11y-animated-images="system" data-a11y-link-underlines="true" > <head> <meta charset="utf-8"> <link rel="dns-prefetch" href="https://github.githubassets.com"> <link rel="dns-prefetch" href="https://avatars.githubusercontent.com"> <link rel="dns-prefetch" href="https://github-cloud.s3.amazonaws.com"> <link rel="dns-prefetch" href="https://user-images.githubusercontent.com/"> <link rel="preconnect" href="https://github.githubassets.com" crossorigin> <link rel="preconnect" href="https://avatars.githubusercontent.com"> <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/light-7aa84bb7e11e.css" /><link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/dark-f65db3e8d171.css" /><link data-color-theme="dark_dimmed" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_dimmed-a8258e3c6dda.css" /><link data-color-theme="dark_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_high_contrast-7e97d834719c.css" /><link data-color-theme="dark_colorblind" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_colorblind-01d869f460be.css" /><link data-color-theme="light_colorblind" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/light_colorblind-534f3e971240.css" /><link data-color-theme="light_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/light_high_contrast-a8cc7d138001.css" /><link data-color-theme="light_tritanopia" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/light_tritanopia-35e9dfdc4f9f.css" /><link data-color-theme="dark_tritanopia" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_tritanopia-cf4cc5f62dfe.css" /> <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-primitives-d9abecd14f1e.css" /> <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-93aded0ee8a1.css" /> <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/global-8bed0685a4b5.css" /> <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/github-a954a02d9269.css" /> <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/repository-4fce88777fa8.css" /> <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/code-0210be90f4d3.css" /> <script type="application/json" id="client-env">{"locale":"en","featureFlags":["bypass_copilot_indexing_quota","copilot_immersive_file_preview","copilot_new_references_ui","copilot_bing_skill_ga","copilot_attach_folder_reference","copilot_personal_instructions","copilot_personal_instructions_templates","copilot_chat_repo_custom_instructions_preview","copilot_chat_retry_on_error","copilot_chat_persist_submitted_input","copilot_conversational_ux_history_refs","copilot_chat_shared_chat_input","copilot_chat_shared_topic_indicator","copilot_chat_shared_repo_sso_banner","copilot_editor_upsells","copilot_dotcom_chat_reduce_telemetry","copilot_implicit_context","copilot_no_floating_button","copilot_smell_icebreaker_ux","copilot_read_shared_conversation","dotcom_chat_client_side_skills","copilot_new_markdown_renderer","experimentation_azure_variant_endpoint","failbot_handle_non_errors","geojson_azure_maps","ghost_pilot_confidence_truncation_25","ghost_pilot_confidence_truncation_40","github_models_o3_mini_streaming","hovercard_accessibility","issues_react_remove_placeholders","issues_react_blur_item_picker_on_close","issues_react_include_bots_in_pickers","marketing_pages_search_explore_provider","remove_child_patch","sample_network_conn_type","swp_enterprise_contact_form","site_copilot_vscode_link_update","site_proxima_australia_update","issues_react_create_milestone","issues_react_cache_fix_workaround","lifecycle_label_name_updates"]}</script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/wp-runtime-890f3c3d3caa.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_oddbird_popover-polyfill_dist_popover_js-9da652f58479.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_github_arianotify-polyfill_ariaNotify-polyfill_js-node_modules_github_mi-3abb8f-d7e6bc799724.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/ui_packages_failbot_failbot_ts-4600dbf2d60a.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/environment-f04cb2a9fc8c.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_primer_behaviors_dist_esm_index_mjs-0dbb79f97f8f.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_github_selector-observer_dist_index_esm_js-f690fd9ae3d5.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_github_relative-time-element_dist_index_js-f6da4b3fa34c.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_github_auto-complete-element_dist_index_js-node_modules_github_catalyst_-8e9f78-a74b4e0a8a6b.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_github_text-expander-element_dist_index_js-78748950cb0c.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_github_filter-input-element_dist_index_js-node_modules_github_remote-inp-b5f1d7-a1760ffda83d.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_github_markdown-toolbar-element_dist_index_js-ceef33f593fa.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_github_file-attachment-element_dist_index_js-node_modules_primer_view-co-c44a69-f0c8a795d1fd.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/github-elements-44d18ad044b3.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/element-registry-b7096f9a808d.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_braintree_browser-detection_dist_browser-detection_js-node_modules_githu-2906d7-2a07a295af40.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_lit-html_lit-html_js-be8cb88f481b.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_github_mini-throttle_dist_index_js-node_modules_morphdom_dist_morphdom-e-7c534c-a4a1922eb55f.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_github_turbo_dist_turbo_es2017-esm_js-e3cbe28f1638.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_github_remote-form_dist_index_js-node_modules_delegated-events_dist_inde-893f9f-6cf3320416b8.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_color-convert_index_js-e3180fe3bcb3.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_github_quote-selection_dist_index_js-node_modules_github_session-resume_-947061-205cd97df772.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/ui_packages_updatable-content_updatable-content_ts-a1563f62660e.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/app_assets_modules_github_behaviors_task-list_ts-app_assets_modules_github_sso_ts-ui_packages-900dde-f48a418a99d4.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/app_assets_modules_github_sticky-scroll-into-view_ts-8fa27fd7fbb6.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/app_assets_modules_github_behaviors_ajax-error_ts-app_assets_modules_github_behaviors_include-87a4ae-e2caa5390f5a.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/app_assets_modules_github_behaviors_commenting_edit_ts-app_assets_modules_github_behaviors_ht-83c235-783fc7e142e5.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/behaviors-854fa1987fb5.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_delegated-events_dist_index_js-node_modules_github_catalyst_lib_index_js-f6223d90c7ba.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/notifications-global-e12489347ccf.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_github_mini-throttle_dist_index_js-node_modules_github_catalyst_lib_inde-dbbea9-26cce2010167.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/code-menu-6a5f60eab447.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/primer-react-8e38c0ecf8b7.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/react-core-218ef2d63cca.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/react-lib-f1bca44e0926.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/octicons-react-611691cca2f6.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_emotion_is-prop-valid_dist_emotion-is-prop-valid_esm_js-node_modules_emo-62da9f-2df2f32ec596.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_github_mini-throttle_dist_index_js-node_modules_stacktrace-parser_dist_s-e7dcdd-f7cc96ebae76.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_oddbird_popover-polyfill_dist_popover-fn_js-55fea94174bf.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_dompurify_dist_purify_js-b89b98661809.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_lodash-es__Stack_js-node_modules_lodash-es__Uint8Array_js-node_modules_l-4faaa6-4a736fde5c2f.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_lodash-es__baseIsEqual_js-8929eb9718d5.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_github_hydro-analytics-client_dist_analytics-client_js-node_modules_gith-853b24-f2006d2a5b98.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_focus-visible_dist_focus-visible_js-node_modules_fzy_js_index_js-node_mo-35e85b-b2842e98946f.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/ui_packages_aria-live_aria-live_ts-ui_packages_promise-with-resolvers-polyfill_promise-with-r-17c672-d6b5ea82572a.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/ui_packages_paths_index_ts-9c4436ef49de.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/ui_packages_ref-selector_RefSelector_tsx-2cce17df147b.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/ui_packages_code-view-shared_utilities_web-worker_ts-ui_packages_code-view-shared_worker-jobs-a69584-34e5b559ff45.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/ui_packages_code-view-shared_hooks_use-canonical-object_ts-ui_packages_code-view-shared_hooks-a6859a-09c7f754ea79.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/ui_packages_repos-file-tree-view_repos-file-tree-view_ts-ui_packages_feature-request_FeatureR-648c3b-e2701dc83e0b.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/app_assets_modules_github_blob-anchor_ts-ui_packages_code-nav_code-nav_ts-ui_packages_filter--8253c1-91468a3354f9.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/react-code-view-684bc66bc078.js"></script> <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react.5a0ffaf77c0db0d0dac2.module.css" /> <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/react-code-view.ab7d8fac328c00e5e0cc.module.css" /> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/notifications-subscriptions-menu-eff84ecbf2b6.js"></script> <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react.5a0ffaf77c0db0d0dac2.module.css" /> <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/notifications-subscriptions-menu.1bcff9205c241e99cff2.module.css" /> <title>peps/peps/pep-0667.rst at main · python/peps · GitHub</title> <meta name="route-pattern" content="/:user_id/:repository/blob/*name(/*path)" data-turbo-transient> <meta name="route-controller" content="blob" data-turbo-transient> <meta name="route-action" content="show" data-turbo-transient> <meta name="current-catalog-service-hash" content="f3abb0cc802f3d7b95fc8762b94bdcb13bf39634c40c357301c4aa1d67a256fb"> <meta name="request-id" content="9202:26763E:8A446:A8C10:67B39A6D" data-pjax-transient="true"/><meta name="html-safe-nonce" content="47643cf60de905cd601972a80548705ac60fc4fb5f34befad134d20b947e95f7" data-pjax-transient="true"/><meta name="visitor-payload" content="eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiI5MjAyOjI2NzYzRTo4QTQ0NjpBOEMxMDo2N0IzOUE2RCIsInZpc2l0b3JfaWQiOiIxODgxNzQ0NzcxNzc2NzQ4MTQxIiwicmVnaW9uX2VkZ2UiOiJzb3V0aGVhc3Rhc2lhIiwicmVnaW9uX3JlbmRlciI6InNvdXRoZWFzdGFzaWEifQ==" data-pjax-transient="true"/><meta name="visitor-hmac" content="67bb029c2367c21e3760753c9be44d1fb5b352dffaa959e8e53c2a566641f6a3" data-pjax-transient="true"/> <meta name="hovercard-subject-tag" content="repository:13414105" data-turbo-transient> <meta name="github-keyboard-shortcuts" content="repository,source-code,file-tree,copilot" data-turbo-transient="true" /> <meta name="selected-link" value="repo_source" data-turbo-transient> <link rel="assets" href="https://github.githubassets.com/"> <meta name="google-site-verification" content="Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I"> <meta name="octolytics-url" content="https://collector.github.com/github/collect" /> <meta name="analytics-location" content="/<user-name>/<repo-name>/blob/show" data-turbo-transient="true" /> <meta name="user-login" content=""> <meta name="viewport" content="width=device-width"> <meta name="description" content="Python Enhancement Proposals. Contribute to python/peps development by creating an account on GitHub."> <link rel="search" type="application/opensearchdescription+xml" href="/opensearch.xml" title="GitHub"> <link rel="fluid-icon" href="https://github.com/fluidicon.png" title="GitHub"> <meta property="fb:app_id" content="1401488693436528"> <meta name="apple-itunes-app" content="app-id=1477376905, app-argument=https://github.com/python/peps/blob/main/peps/pep-0667.rst" /> <meta name="twitter:image" content="https://opengraph.githubassets.com/1eac80e2a5b5e4816a2a63ad8bb431b4be7530d33b6b554994687251d8468bc5/python/peps" /><meta name="twitter:site" content="@github" /><meta name="twitter:card" content="summary_large_image" /><meta name="twitter:title" content="peps/peps/pep-0667.rst at main · python/peps" /><meta name="twitter:description" content="Python Enhancement Proposals. Contribute to python/peps development by creating an account on GitHub." /> <meta property="og:image" content="https://opengraph.githubassets.com/1eac80e2a5b5e4816a2a63ad8bb431b4be7530d33b6b554994687251d8468bc5/python/peps" /><meta property="og:image:alt" content="Python Enhancement Proposals. Contribute to python/peps development by creating an account on GitHub." /><meta property="og:image:width" content="1200" /><meta property="og:image:height" content="600" /><meta property="og:site_name" content="GitHub" /><meta property="og:type" content="object" /><meta property="og:title" content="peps/peps/pep-0667.rst at main · python/peps" /><meta property="og:url" content="https://github.com/python/peps/blob/main/peps/pep-0667.rst" /><meta property="og:description" content="Python Enhancement Proposals. Contribute to python/peps development by creating an account on GitHub." /> <meta name="hostname" content="github.com"> <meta name="expected-hostname" content="github.com"> <meta http-equiv="x-pjax-version" content="0f265ef8396cd1962dba2eda868f105296f51594cc2ff5b653c6553989093b61" data-turbo-track="reload"> <meta http-equiv="x-pjax-csp-version" content="ace39c3b6632770952207593607e6e0be0db363435a8b877b1f96abe6430f345" data-turbo-track="reload"> <meta http-equiv="x-pjax-css-version" content="1c71206221e00a0a8e77d94d48d954f34ddbd711c4a0ced954fd49cd786cfa61" data-turbo-track="reload"> <meta http-equiv="x-pjax-js-version" content="12a8aded86f558a96e1c8427138fa449b829e611fbd8701cad0d49ba051978b0" data-turbo-track="reload"> <meta name="turbo-cache-control" content="no-preview" data-turbo-transient=""> <meta name="turbo-cache-control" content="no-cache" data-turbo-transient> <meta data-hydrostats="publish"> <meta name="go-import" content="github.com/python/peps git https://github.com/python/peps.git"> <meta name="octolytics-dimension-user_id" content="1525981" /><meta name="octolytics-dimension-user_login" content="python" /><meta name="octolytics-dimension-repository_id" content="13414105" /><meta name="octolytics-dimension-repository_nwo" content="python/peps" /><meta name="octolytics-dimension-repository_public" content="true" /><meta name="octolytics-dimension-repository_is_fork" content="false" /><meta name="octolytics-dimension-repository_network_root_id" content="13414105" /><meta name="octolytics-dimension-repository_network_root_nwo" content="python/peps" /> <meta name="turbo-body-classes" content="logged-out env-production page-responsive"> <meta name="browser-stats-url" content="https://api.github.com/_private/browser/stats"> <meta name="browser-errors-url" content="https://api.github.com/_private/browser/errors"> <link rel="mask-icon" href="https://github.githubassets.com/assets/pinned-octocat-093da3e6fa40.svg" color="#000000"> <link rel="alternate icon" class="js-site-favicon" type="image/png" href="https://github.githubassets.com/favicons/favicon.png"> <link rel="icon" class="js-site-favicon" type="image/svg+xml" href="https://github.githubassets.com/favicons/favicon.svg" data-base-href="https://github.githubassets.com/favicons/favicon"> <meta name="theme-color" content="#1e2327"> <meta name="color-scheme" content="light dark" /> <link rel="manifest" href="/manifest.json" crossOrigin="use-credentials"> </head> <body class="logged-out env-production page-responsive" style="word-wrap: break-word;"> <div data-turbo-body class="logged-out env-production page-responsive" style="word-wrap: break-word;"> <div class="position-relative header-wrapper js-header-wrapper "> <a href="#start-of-content" data-skip-target-assigned="false" class="px-2 py-4 color-bg-accent-emphasis color-fg-on-emphasis show-on-focus js-skip-to-content">Skip to content</a> <span data-view-component="true" class="progress-pjax-loader Progress position-fixed width-full"> <span style="width: 0%;" data-view-component="true" class="Progress-item progress-pjax-loader-bar left-0 top-0 color-bg-accent-emphasis"></span> </span> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/ui_packages_ui-commands_ui-commands_ts-e571874765ef.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/keyboard-shortcuts-dialog-765cf28766da.js"></script> <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react.5a0ffaf77c0db0d0dac2.module.css" /> <react-partial partial-name="keyboard-shortcuts-dialog" data-ssr="false" data-attempted-ssr="false" > <script type="application/json" data-target="react-partial.embeddedData">{"props":{"docsUrl":"https://docs.github.com/get-started/accessibility/keyboard-shortcuts"}}</script> <div data-target="react-partial.reactRoot"></div> </react-partial> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_github_remote-form_dist_index_js-node_modules_delegated-events_dist_inde-94fd67-73b675cf164a.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/sessions-2d195d11c56b.js"></script> <header class="HeaderMktg header-logged-out js-details-container js-header Details f4 py-3" role="banner" data-is-top="true" data-color-mode=light data-light-theme=light data-dark-theme=dark> <h2 class="sr-only">Navigation Menu</h2> <button type="button" class="HeaderMktg-backdrop d-lg-none border-0 position-fixed top-0 left-0 width-full height-full js-details-target" aria-label="Toggle navigation"> <span class="d-none">Toggle navigation</span> </button> <div class="d-flex flex-column flex-lg-row flex-items-center px-3 px-md-4 px-lg-5 height-full position-relative z-1"> <div class="d-flex flex-justify-between flex-items-center width-full width-lg-auto"> <div class="flex-1"> <button aria-label="Toggle navigation" aria-expanded="false" type="button" data-view-component="true" class="js-details-target js-nav-padding-recalculate js-header-menu-toggle Button--link Button--medium Button d-lg-none color-fg-inherit p-1"> <span class="Button-content"> <span class="Button-label"><div class="HeaderMenu-toggle-bar rounded my-1"></div> <div class="HeaderMenu-toggle-bar rounded my-1"></div> <div class="HeaderMenu-toggle-bar rounded my-1"></div></span> </span> </button> </div> <a class="mr-lg-3 color-fg-inherit flex-order-2 js-prevent-focus-on-mobile-nav" href="/" aria-label="Homepage" data-analytics-event="{"category":"Marketing nav","action":"click to go to homepage","label":"ref_page:Marketing;ref_cta:Logomark;ref_loc:Header"}"> <svg height="32" aria-hidden="true" viewBox="0 0 24 24" version="1.1" width="32" data-view-component="true" class="octicon octicon-mark-github"> <path d="M12.5.75C6.146.75 1 5.896 1 12.25c0 5.089 3.292 9.387 7.863 10.91.575.101.79-.244.79-.546 0-.273-.014-1.178-.014-2.142-2.889.532-3.636-.704-3.866-1.35-.13-.331-.69-1.352-1.18-1.625-.402-.216-.977-.748-.014-.762.906-.014 1.553.834 1.769 1.179 1.035 1.74 2.688 1.25 3.349.948.1-.747.402-1.25.733-1.538-2.559-.287-5.232-1.279-5.232-5.678 0-1.25.445-2.285 1.178-3.09-.115-.288-.517-1.467.115-3.048 0 0 .963-.302 3.163 1.179.92-.259 1.897-.388 2.875-.388.977 0 1.955.13 2.875.388 2.2-1.495 3.162-1.179 3.162-1.179.633 1.581.23 2.76.115 3.048.733.805 1.179 1.825 1.179 3.09 0 4.413-2.688 5.39-5.247 5.678.417.36.776 1.05.776 2.128 0 1.538-.014 2.774-.014 3.162 0 .302.216.662.79.547C20.709 21.637 24 17.324 24 12.25 24 5.896 18.854.75 12.5.75Z"></path> </svg> </a> <div class="flex-1 flex-order-2 text-right"> <a href="/login?return_to=https%3A%2F%2Fgithub.com%2Fpython%2Fpeps%2Fblob%2Fmain%2Fpeps%2Fpep-0667.rst" class="HeaderMenu-link HeaderMenu-button d-inline-flex d-lg-none flex-order-1 f5 no-underline border color-border-default rounded-2 px-2 py-1 color-fg-inherit js-prevent-focus-on-mobile-nav" data-hydro-click="{"event_type":"authentication.click","payload":{"location_in_page":"site header menu","repository_id":null,"auth_type":"SIGN_UP","originating_url":"https://github.com/python/peps/blob/main/peps/pep-0667.rst","user_id":null}}" data-hydro-click-hmac="e5178f01dfdf459929017c3f24bcd4c68f76f11c4196fead833dbd5ef9a7a272" data-analytics-event="{"category":"Marketing nav","action":"click to Sign in","label":"ref_page:Marketing;ref_cta:Sign in;ref_loc:Header"}" > Sign in </a> </div> </div> <div class="HeaderMenu js-header-menu height-fit position-lg-relative d-lg-flex flex-column flex-auto top-0"> <div class="HeaderMenu-wrapper d-flex flex-column flex-self-start flex-lg-row flex-auto rounded rounded-lg-0"> <nav class="HeaderMenu-nav" aria-label="Global"> <ul class="d-lg-flex list-style-none"> <li class="HeaderMenu-item position-relative flex-wrap flex-justify-between flex-items-center d-block d-lg-flex flex-lg-nowrap flex-lg-items-center js-details-container js-header-menu-item"> <button type="button" class="HeaderMenu-link border-0 width-full width-lg-auto px-0 px-lg-2 py-lg-2 no-wrap d-flex flex-items-center flex-justify-between js-details-target" aria-expanded="false"> Product <svg opacity="0.5" aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-chevron-down HeaderMenu-icon ml-1"> <path d="M12.78 5.22a.749.749 0 0 1 0 1.06l-4.25 4.25a.749.749 0 0 1-1.06 0L3.22 6.28a.749.749 0 1 1 1.06-1.06L8 8.939l3.72-3.719a.749.749 0 0 1 1.06 0Z"></path> </svg> </button> <div class="HeaderMenu-dropdown dropdown-menu rounded m-0 p-0 pt-2 pt-lg-4 position-relative position-lg-absolute left-0 left-lg-n3 pb-2 pb-lg-4 d-lg-flex flex-wrap dropdown-menu-wide"> <div class="HeaderMenu-column px-lg-4 border-lg-right mb-4 mb-lg-0 pr-lg-7"> <div class="border-bottom pb-3 pb-lg-0 border-lg-bottom-0"> <ul class="list-style-none f5" > <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary d-flex flex-items-center Link--has-description pb-lg-3" data-analytics-event="{"location":"navbar","action":"github_copilot","context":"product","tag":"link","label":"github_copilot_link_product_navbar"}" href="https://github.com/features/copilot"> <svg aria-hidden="true" height="24" viewBox="0 0 24 24" version="1.1" width="24" data-view-component="true" class="octicon octicon-copilot color-fg-subtle mr-3"> <path d="M23.922 16.992c-.861 1.495-5.859 5.023-11.922 5.023-6.063 0-11.061-3.528-11.922-5.023A.641.641 0 0 1 0 16.736v-2.869a.841.841 0 0 1 .053-.22c.372-.935 1.347-2.292 2.605-2.656.167-.429.414-1.055.644-1.517a10.195 10.195 0 0 1-.052-1.086c0-1.331.282-2.499 1.132-3.368.397-.406.89-.717 1.474-.952 1.399-1.136 3.392-2.093 6.122-2.093 2.731 0 4.767.957 6.166 2.093.584.235 1.077.546 1.474.952.85.869 1.132 2.037 1.132 3.368 0 .368-.014.733-.052 1.086.23.462.477 1.088.644 1.517 1.258.364 2.233 1.721 2.605 2.656a.832.832 0 0 1 .053.22v2.869a.641.641 0 0 1-.078.256ZM12.172 11h-.344a4.323 4.323 0 0 1-.355.508C10.703 12.455 9.555 13 7.965 13c-1.725 0-2.989-.359-3.782-1.259a2.005 2.005 0 0 1-.085-.104L4 11.741v6.585c1.435.779 4.514 2.179 8 2.179 3.486 0 6.565-1.4 8-2.179v-6.585l-.098-.104s-.033.045-.085.104c-.793.9-2.057 1.259-3.782 1.259-1.59 0-2.738-.545-3.508-1.492a4.323 4.323 0 0 1-.355-.508h-.016.016Zm.641-2.935c.136 1.057.403 1.913.878 2.497.442.544 1.134.938 2.344.938 1.573 0 2.292-.337 2.657-.751.384-.435.558-1.15.558-2.361 0-1.14-.243-1.847-.705-2.319-.477-.488-1.319-.862-2.824-1.025-1.487-.161-2.192.138-2.533.529-.269.307-.437.808-.438 1.578v.021c0 .265.021.562.063.893Zm-1.626 0c.042-.331.063-.628.063-.894v-.02c-.001-.77-.169-1.271-.438-1.578-.341-.391-1.046-.69-2.533-.529-1.505.163-2.347.537-2.824 1.025-.462.472-.705 1.179-.705 2.319 0 1.211.175 1.926.558 2.361.365.414 1.084.751 2.657.751 1.21 0 1.902-.394 2.344-.938.475-.584.742-1.44.878-2.497Z"></path><path d="M14.5 14.25a1 1 0 0 1 1 1v2a1 1 0 0 1-2 0v-2a1 1 0 0 1 1-1Zm-5 0a1 1 0 0 1 1 1v2a1 1 0 0 1-2 0v-2a1 1 0 0 1 1-1Z"></path> </svg> <div> <div class="color-fg-default h4">GitHub Copilot</div> Write better code with AI </div> </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary d-flex flex-items-center Link--has-description pb-lg-3" data-analytics-event="{"location":"navbar","action":"security","context":"product","tag":"link","label":"security_link_product_navbar"}" href="https://github.com/features/security"> <svg aria-hidden="true" height="24" viewBox="0 0 24 24" version="1.1" width="24" data-view-component="true" class="octicon octicon-shield-check color-fg-subtle mr-3"> <path d="M16.53 9.78a.75.75 0 0 0-1.06-1.06L11 13.19l-1.97-1.97a.75.75 0 0 0-1.06 1.06l2.5 2.5a.75.75 0 0 0 1.06 0l5-5Z"></path><path d="m12.54.637 8.25 2.675A1.75 1.75 0 0 1 22 4.976V10c0 6.19-3.771 10.704-9.401 12.83a1.704 1.704 0 0 1-1.198 0C5.77 20.705 2 16.19 2 10V4.976c0-.758.489-1.43 1.21-1.664L11.46.637a1.748 1.748 0 0 1 1.08 0Zm-.617 1.426-8.25 2.676a.249.249 0 0 0-.173.237V10c0 5.46 3.28 9.483 8.43 11.426a.199.199 0 0 0 .14 0C17.22 19.483 20.5 15.461 20.5 10V4.976a.25.25 0 0 0-.173-.237l-8.25-2.676a.253.253 0 0 0-.154 0Z"></path> </svg> <div> <div class="color-fg-default h4">Security</div> Find and fix vulnerabilities </div> </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary d-flex flex-items-center Link--has-description pb-lg-3" data-analytics-event="{"location":"navbar","action":"actions","context":"product","tag":"link","label":"actions_link_product_navbar"}" href="https://github.com/features/actions"> <svg aria-hidden="true" height="24" viewBox="0 0 24 24" version="1.1" width="24" data-view-component="true" class="octicon octicon-workflow color-fg-subtle mr-3"> <path d="M1 3a2 2 0 0 1 2-2h6.5a2 2 0 0 1 2 2v6.5a2 2 0 0 1-2 2H7v4.063C7 16.355 7.644 17 8.438 17H12.5v-2.5a2 2 0 0 1 2-2H21a2 2 0 0 1 2 2V21a2 2 0 0 1-2 2h-6.5a2 2 0 0 1-2-2v-2.5H8.437A2.939 2.939 0 0 1 5.5 15.562V11.5H3a2 2 0 0 1-2-2Zm2-.5a.5.5 0 0 0-.5.5v6.5a.5.5 0 0 0 .5.5h6.5a.5.5 0 0 0 .5-.5V3a.5.5 0 0 0-.5-.5ZM14.5 14a.5.5 0 0 0-.5.5V21a.5.5 0 0 0 .5.5H21a.5.5 0 0 0 .5-.5v-6.5a.5.5 0 0 0-.5-.5Z"></path> </svg> <div> <div class="color-fg-default h4">Actions</div> Automate any workflow </div> </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary d-flex flex-items-center Link--has-description pb-lg-3" data-analytics-event="{"location":"navbar","action":"codespaces","context":"product","tag":"link","label":"codespaces_link_product_navbar"}" href="https://github.com/features/codespaces"> <svg aria-hidden="true" height="24" viewBox="0 0 24 24" version="1.1" width="24" data-view-component="true" class="octicon octicon-codespaces color-fg-subtle mr-3"> <path d="M3.5 3.75C3.5 2.784 4.284 2 5.25 2h13.5c.966 0 1.75.784 1.75 1.75v7.5A1.75 1.75 0 0 1 18.75 13H5.25a1.75 1.75 0 0 1-1.75-1.75Zm-2 12c0-.966.784-1.75 1.75-1.75h17.5c.966 0 1.75.784 1.75 1.75v4a1.75 1.75 0 0 1-1.75 1.75H3.25a1.75 1.75 0 0 1-1.75-1.75ZM5.25 3.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h13.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Zm-2 12a.25.25 0 0 0-.25.25v4c0 .138.112.25.25.25h17.5a.25.25 0 0 0 .25-.25v-4a.25.25 0 0 0-.25-.25Z"></path><path d="M10 17.75a.75.75 0 0 1 .75-.75h6.5a.75.75 0 0 1 0 1.5h-6.5a.75.75 0 0 1-.75-.75Zm-4 0a.75.75 0 0 1 .75-.75h.5a.75.75 0 0 1 0 1.5h-.5a.75.75 0 0 1-.75-.75Z"></path> </svg> <div> <div class="color-fg-default h4">Codespaces</div> Instant dev environments </div> </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary d-flex flex-items-center Link--has-description pb-lg-3" data-analytics-event="{"location":"navbar","action":"issues","context":"product","tag":"link","label":"issues_link_product_navbar"}" href="https://github.com/features/issues"> <svg aria-hidden="true" height="24" viewBox="0 0 24 24" version="1.1" width="24" data-view-component="true" class="octicon octicon-issue-opened color-fg-subtle mr-3"> <path d="M12 1c6.075 0 11 4.925 11 11s-4.925 11-11 11S1 18.075 1 12 5.925 1 12 1ZM2.5 12a9.5 9.5 0 0 0 9.5 9.5 9.5 9.5 0 0 0 9.5-9.5A9.5 9.5 0 0 0 12 2.5 9.5 9.5 0 0 0 2.5 12Zm9.5 2a2 2 0 1 1-.001-3.999A2 2 0 0 1 12 14Z"></path> </svg> <div> <div class="color-fg-default h4">Issues</div> Plan and track work </div> </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary d-flex flex-items-center Link--has-description pb-lg-3" data-analytics-event="{"location":"navbar","action":"code_review","context":"product","tag":"link","label":"code_review_link_product_navbar"}" href="https://github.com/features/code-review"> <svg aria-hidden="true" height="24" viewBox="0 0 24 24" version="1.1" width="24" data-view-component="true" class="octicon octicon-code-review color-fg-subtle mr-3"> <path d="M10.3 6.74a.75.75 0 0 1-.04 1.06l-2.908 2.7 2.908 2.7a.75.75 0 1 1-1.02 1.1l-3.5-3.25a.75.75 0 0 1 0-1.1l3.5-3.25a.75.75 0 0 1 1.06.04Zm3.44 1.06a.75.75 0 1 1 1.02-1.1l3.5 3.25a.75.75 0 0 1 0 1.1l-3.5 3.25a.75.75 0 1 1-1.02-1.1l2.908-2.7-2.908-2.7Z"></path><path d="M1.5 4.25c0-.966.784-1.75 1.75-1.75h17.5c.966 0 1.75.784 1.75 1.75v12.5a1.75 1.75 0 0 1-1.75 1.75h-9.69l-3.573 3.573A1.458 1.458 0 0 1 5 21.043V18.5H3.25a1.75 1.75 0 0 1-1.75-1.75ZM3.25 4a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h2.5a.75.75 0 0 1 .75.75v3.19l3.72-3.72a.749.749 0 0 1 .53-.22h10a.25.25 0 0 0 .25-.25V4.25a.25.25 0 0 0-.25-.25Z"></path> </svg> <div> <div class="color-fg-default h4">Code Review</div> Manage code changes </div> </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary d-flex flex-items-center Link--has-description pb-lg-3" data-analytics-event="{"location":"navbar","action":"discussions","context":"product","tag":"link","label":"discussions_link_product_navbar"}" href="https://github.com/features/discussions"> <svg aria-hidden="true" height="24" viewBox="0 0 24 24" version="1.1" width="24" data-view-component="true" class="octicon octicon-comment-discussion color-fg-subtle mr-3"> <path d="M1.75 1h12.5c.966 0 1.75.784 1.75 1.75v9.5A1.75 1.75 0 0 1 14.25 14H8.061l-2.574 2.573A1.458 1.458 0 0 1 3 15.543V14H1.75A1.75 1.75 0 0 1 0 12.25v-9.5C0 1.784.784 1 1.75 1ZM1.5 2.75v9.5c0 .138.112.25.25.25h2a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h6.5a.25.25 0 0 0 .25-.25v-9.5a.25.25 0 0 0-.25-.25H1.75a.25.25 0 0 0-.25.25Z"></path><path d="M22.5 8.75a.25.25 0 0 0-.25-.25h-3.5a.75.75 0 0 1 0-1.5h3.5c.966 0 1.75.784 1.75 1.75v9.5A1.75 1.75 0 0 1 22.25 20H21v1.543a1.457 1.457 0 0 1-2.487 1.03L15.939 20H10.75A1.75 1.75 0 0 1 9 18.25v-1.465a.75.75 0 0 1 1.5 0v1.465c0 .138.112.25.25.25h5.5a.75.75 0 0 1 .53.22l2.72 2.72v-2.19a.75.75 0 0 1 .75-.75h2a.25.25 0 0 0 .25-.25v-9.5Z"></path> </svg> <div> <div class="color-fg-default h4">Discussions</div> Collaborate outside of code </div> </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary d-flex flex-items-center Link--has-description" data-analytics-event="{"location":"navbar","action":"code_search","context":"product","tag":"link","label":"code_search_link_product_navbar"}" href="https://github.com/features/code-search"> <svg aria-hidden="true" height="24" viewBox="0 0 24 24" version="1.1" width="24" data-view-component="true" class="octicon octicon-code-square color-fg-subtle mr-3"> <path d="M10.3 8.24a.75.75 0 0 1-.04 1.06L7.352 12l2.908 2.7a.75.75 0 1 1-1.02 1.1l-3.5-3.25a.75.75 0 0 1 0-1.1l3.5-3.25a.75.75 0 0 1 1.06.04Zm3.44 1.06a.75.75 0 1 1 1.02-1.1l3.5 3.25a.75.75 0 0 1 0 1.1l-3.5 3.25a.75.75 0 1 1-1.02-1.1l2.908-2.7-2.908-2.7Z"></path><path d="M2 3.75C2 2.784 2.784 2 3.75 2h16.5c.966 0 1.75.784 1.75 1.75v16.5A1.75 1.75 0 0 1 20.25 22H3.75A1.75 1.75 0 0 1 2 20.25Zm1.75-.25a.25.25 0 0 0-.25.25v16.5c0 .138.112.25.25.25h16.5a.25.25 0 0 0 .25-.25V3.75a.25.25 0 0 0-.25-.25Z"></path> </svg> <div> <div class="color-fg-default h4">Code Search</div> Find more, search less </div> </a></li> </ul> </div> </div> <div class="HeaderMenu-column px-lg-4"> <div class="border-bottom pb-3 pb-lg-0 border-lg-bottom-0 border-bottom-0"> <span class="d-block h4 color-fg-default my-1" id="product-explore-heading">Explore</span> <ul class="list-style-none f5" aria-labelledby="product-explore-heading"> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{"location":"navbar","action":"all_features","context":"product","tag":"link","label":"all_features_link_product_navbar"}" href="https://github.com/features"> All features </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary Link--external" target="_blank" data-analytics-event="{"location":"navbar","action":"documentation","context":"product","tag":"link","label":"documentation_link_product_navbar"}" href="https://docs.github.com"> Documentation <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-link-external HeaderMenu-external-icon color-fg-subtle"> <path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path> </svg> </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary Link--external" target="_blank" data-analytics-event="{"location":"navbar","action":"github_skills","context":"product","tag":"link","label":"github_skills_link_product_navbar"}" href="https://skills.github.com"> GitHub Skills <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-link-external HeaderMenu-external-icon color-fg-subtle"> <path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path> </svg> </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary Link--external" target="_blank" data-analytics-event="{"location":"navbar","action":"blog","context":"product","tag":"link","label":"blog_link_product_navbar"}" href="https://github.blog"> Blog <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-link-external HeaderMenu-external-icon color-fg-subtle"> <path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path> </svg> </a></li> </ul> </div> </div> </div> </li> <li class="HeaderMenu-item position-relative flex-wrap flex-justify-between flex-items-center d-block d-lg-flex flex-lg-nowrap flex-lg-items-center js-details-container js-header-menu-item"> <button type="button" class="HeaderMenu-link border-0 width-full width-lg-auto px-0 px-lg-2 py-lg-2 no-wrap d-flex flex-items-center flex-justify-between js-details-target" aria-expanded="false"> Solutions <svg opacity="0.5" aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-chevron-down HeaderMenu-icon ml-1"> <path d="M12.78 5.22a.749.749 0 0 1 0 1.06l-4.25 4.25a.749.749 0 0 1-1.06 0L3.22 6.28a.749.749 0 1 1 1.06-1.06L8 8.939l3.72-3.719a.749.749 0 0 1 1.06 0Z"></path> </svg> </button> <div class="HeaderMenu-dropdown dropdown-menu rounded m-0 p-0 pt-2 pt-lg-4 position-relative position-lg-absolute left-0 left-lg-n3 d-lg-flex flex-wrap dropdown-menu-wide"> <div class="HeaderMenu-column px-lg-4 border-lg-right mb-4 mb-lg-0 pr-lg-7"> <div class="border-bottom pb-3 pb-lg-0 border-lg-bottom-0 pb-lg-3 mb-3 mb-lg-0"> <span class="d-block h4 color-fg-default my-1" id="solutions-by-company-size-heading">By company size</span> <ul class="list-style-none f5" aria-labelledby="solutions-by-company-size-heading"> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{"location":"navbar","action":"enterprises","context":"solutions","tag":"link","label":"enterprises_link_solutions_navbar"}" href="https://github.com/enterprise"> Enterprises </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{"location":"navbar","action":"small_and_medium_teams","context":"solutions","tag":"link","label":"small_and_medium_teams_link_solutions_navbar"}" href="https://github.com/team"> Small and medium teams </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{"location":"navbar","action":"startups","context":"solutions","tag":"link","label":"startups_link_solutions_navbar"}" href="https://github.com/enterprise/startups"> Startups </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{"location":"navbar","action":"nonprofits","context":"solutions","tag":"link","label":"nonprofits_link_solutions_navbar"}" href="/solutions/industry/nonprofits"> Nonprofits </a></li> </ul> </div> <div class="border-bottom pb-3 pb-lg-0 border-lg-bottom-0"> <span class="d-block h4 color-fg-default my-1" id="solutions-by-use-case-heading">By use case</span> <ul class="list-style-none f5" aria-labelledby="solutions-by-use-case-heading"> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{"location":"navbar","action":"devsecops","context":"solutions","tag":"link","label":"devsecops_link_solutions_navbar"}" href="/solutions/use-case/devsecops"> DevSecOps </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{"location":"navbar","action":"devops","context":"solutions","tag":"link","label":"devops_link_solutions_navbar"}" href="/solutions/use-case/devops"> DevOps </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{"location":"navbar","action":"ci_cd","context":"solutions","tag":"link","label":"ci_cd_link_solutions_navbar"}" href="/solutions/use-case/ci-cd"> CI/CD </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{"location":"navbar","action":"view_all_use_cases","context":"solutions","tag":"link","label":"view_all_use_cases_link_solutions_navbar"}" href="/solutions/use-case"> View all use cases </a></li> </ul> </div> </div> <div class="HeaderMenu-column px-lg-4"> <div class="border-bottom pb-3 pb-lg-0 border-lg-bottom-0"> <span class="d-block h4 color-fg-default my-1" id="solutions-by-industry-heading">By industry</span> <ul class="list-style-none f5" aria-labelledby="solutions-by-industry-heading"> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{"location":"navbar","action":"healthcare","context":"solutions","tag":"link","label":"healthcare_link_solutions_navbar"}" href="/solutions/industry/healthcare"> Healthcare </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{"location":"navbar","action":"financial_services","context":"solutions","tag":"link","label":"financial_services_link_solutions_navbar"}" href="/solutions/industry/financial-services"> Financial services </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{"location":"navbar","action":"manufacturing","context":"solutions","tag":"link","label":"manufacturing_link_solutions_navbar"}" href="/solutions/industry/manufacturing"> Manufacturing </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{"location":"navbar","action":"government","context":"solutions","tag":"link","label":"government_link_solutions_navbar"}" href="/solutions/industry/government"> Government </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{"location":"navbar","action":"view_all_industries","context":"solutions","tag":"link","label":"view_all_industries_link_solutions_navbar"}" href="/solutions/industry"> View all industries </a></li> </ul> </div> </div> <div class="HeaderMenu-trailing-link rounded-bottom-2 flex-shrink-0 mt-lg-4 px-lg-4 py-4 py-lg-3 f5 text-semibold"> <a href="/solutions"> View all solutions <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-chevron-right HeaderMenu-trailing-link-icon"> <path d="M6.22 3.22a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L9.94 8 6.22 4.28a.75.75 0 0 1 0-1.06Z"></path> </svg> </a> </div> </div> </li> <li class="HeaderMenu-item position-relative flex-wrap flex-justify-between flex-items-center d-block d-lg-flex flex-lg-nowrap flex-lg-items-center js-details-container js-header-menu-item"> <button type="button" class="HeaderMenu-link border-0 width-full width-lg-auto px-0 px-lg-2 py-lg-2 no-wrap d-flex flex-items-center flex-justify-between js-details-target" aria-expanded="false"> Resources <svg opacity="0.5" aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-chevron-down HeaderMenu-icon ml-1"> <path d="M12.78 5.22a.749.749 0 0 1 0 1.06l-4.25 4.25a.749.749 0 0 1-1.06 0L3.22 6.28a.749.749 0 1 1 1.06-1.06L8 8.939l3.72-3.719a.749.749 0 0 1 1.06 0Z"></path> </svg> </button> <div class="HeaderMenu-dropdown dropdown-menu rounded m-0 p-0 pt-2 pt-lg-4 position-relative position-lg-absolute left-0 left-lg-n3 pb-2 pb-lg-4 d-lg-flex flex-wrap dropdown-menu-wide"> <div class="HeaderMenu-column px-lg-4 border-lg-right mb-4 mb-lg-0 pr-lg-7"> <div class="border-bottom pb-3 pb-lg-0 border-lg-bottom-0"> <span class="d-block h4 color-fg-default my-1" id="resources-topics-heading">Topics</span> <ul class="list-style-none f5" aria-labelledby="resources-topics-heading"> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{"location":"navbar","action":"ai","context":"resources","tag":"link","label":"ai_link_resources_navbar"}" href="/resources/articles/ai"> AI </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{"location":"navbar","action":"devops","context":"resources","tag":"link","label":"devops_link_resources_navbar"}" href="/resources/articles/devops"> DevOps </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{"location":"navbar","action":"security","context":"resources","tag":"link","label":"security_link_resources_navbar"}" href="/resources/articles/security"> Security </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{"location":"navbar","action":"software_development","context":"resources","tag":"link","label":"software_development_link_resources_navbar"}" href="/resources/articles/software-development"> Software Development </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{"location":"navbar","action":"view_all","context":"resources","tag":"link","label":"view_all_link_resources_navbar"}" href="/resources/articles"> View all </a></li> </ul> </div> </div> <div class="HeaderMenu-column px-lg-4"> <div class="border-bottom pb-3 pb-lg-0 border-lg-bottom-0 border-bottom-0"> <span class="d-block h4 color-fg-default my-1" id="resources-explore-heading">Explore</span> <ul class="list-style-none f5" aria-labelledby="resources-explore-heading"> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary Link--external" target="_blank" data-analytics-event="{"location":"navbar","action":"learning_pathways","context":"resources","tag":"link","label":"learning_pathways_link_resources_navbar"}" href="https://resources.github.com/learn/pathways"> Learning Pathways <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-link-external HeaderMenu-external-icon color-fg-subtle"> <path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path> </svg> </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary Link--external" target="_blank" data-analytics-event="{"location":"navbar","action":"white_papers_ebooks_webinars","context":"resources","tag":"link","label":"white_papers_ebooks_webinars_link_resources_navbar"}" href="https://resources.github.com"> White papers, Ebooks, Webinars <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-link-external HeaderMenu-external-icon color-fg-subtle"> <path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path> </svg> </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{"location":"navbar","action":"customer_stories","context":"resources","tag":"link","label":"customer_stories_link_resources_navbar"}" href="https://github.com/customer-stories"> Customer Stories </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary Link--external" target="_blank" data-analytics-event="{"location":"navbar","action":"partners","context":"resources","tag":"link","label":"partners_link_resources_navbar"}" href="https://partner.github.com"> Partners <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-link-external HeaderMenu-external-icon color-fg-subtle"> <path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path> </svg> </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{"location":"navbar","action":"executive_insights","context":"resources","tag":"link","label":"executive_insights_link_resources_navbar"}" href="https://github.com/solutions/executive-insights"> Executive Insights </a></li> </ul> </div> </div> </div> </li> <li class="HeaderMenu-item position-relative flex-wrap flex-justify-between flex-items-center d-block d-lg-flex flex-lg-nowrap flex-lg-items-center js-details-container js-header-menu-item"> <button type="button" class="HeaderMenu-link border-0 width-full width-lg-auto px-0 px-lg-2 py-lg-2 no-wrap d-flex flex-items-center flex-justify-between js-details-target" aria-expanded="false"> Open Source <svg opacity="0.5" aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-chevron-down HeaderMenu-icon ml-1"> <path d="M12.78 5.22a.749.749 0 0 1 0 1.06l-4.25 4.25a.749.749 0 0 1-1.06 0L3.22 6.28a.749.749 0 1 1 1.06-1.06L8 8.939l3.72-3.719a.749.749 0 0 1 1.06 0Z"></path> </svg> </button> <div class="HeaderMenu-dropdown dropdown-menu rounded m-0 p-0 pt-2 pt-lg-4 position-relative position-lg-absolute left-0 left-lg-n3 pb-2 pb-lg-4 px-lg-4"> <div class="HeaderMenu-column"> <div class="border-bottom pb-3 pb-lg-0 pb-lg-3 mb-3 mb-lg-0 mb-lg-3"> <ul class="list-style-none f5" > <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary d-flex flex-items-center Link--has-description" data-analytics-event="{"location":"navbar","action":"github_sponsors","context":"open_source","tag":"link","label":"github_sponsors_link_open_source_navbar"}" href="/sponsors"> <div> <div class="color-fg-default h4">GitHub Sponsors</div> Fund open source developers </div> </a></li> </ul> </div> <div class="border-bottom pb-3 pb-lg-0 pb-lg-3 mb-3 mb-lg-0 mb-lg-3"> <ul class="list-style-none f5" > <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary d-flex flex-items-center Link--has-description" data-analytics-event="{"location":"navbar","action":"the_readme_project","context":"open_source","tag":"link","label":"the_readme_project_link_open_source_navbar"}" href="https://github.com/readme"> <div> <div class="color-fg-default h4">The ReadME Project</div> GitHub community articles </div> </a></li> </ul> </div> <div class="border-bottom pb-3 pb-lg-0 border-bottom-0"> <span class="d-block h4 color-fg-default my-1" id="open-source-repositories-heading">Repositories</span> <ul class="list-style-none f5" aria-labelledby="open-source-repositories-heading"> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{"location":"navbar","action":"topics","context":"open_source","tag":"link","label":"topics_link_open_source_navbar"}" href="https://github.com/topics"> Topics </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{"location":"navbar","action":"trending","context":"open_source","tag":"link","label":"trending_link_open_source_navbar"}" href="https://github.com/trending"> Trending </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{"location":"navbar","action":"collections","context":"open_source","tag":"link","label":"collections_link_open_source_navbar"}" href="https://github.com/collections"> Collections </a></li> </ul> </div> </div> </div> </li> <li class="HeaderMenu-item position-relative flex-wrap flex-justify-between flex-items-center d-block d-lg-flex flex-lg-nowrap flex-lg-items-center js-details-container js-header-menu-item"> <button type="button" class="HeaderMenu-link border-0 width-full width-lg-auto px-0 px-lg-2 py-lg-2 no-wrap d-flex flex-items-center flex-justify-between js-details-target" aria-expanded="false"> Enterprise <svg opacity="0.5" aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-chevron-down HeaderMenu-icon ml-1"> <path d="M12.78 5.22a.749.749 0 0 1 0 1.06l-4.25 4.25a.749.749 0 0 1-1.06 0L3.22 6.28a.749.749 0 1 1 1.06-1.06L8 8.939l3.72-3.719a.749.749 0 0 1 1.06 0Z"></path> </svg> </button> <div class="HeaderMenu-dropdown dropdown-menu rounded m-0 p-0 pt-2 pt-lg-4 position-relative position-lg-absolute left-0 left-lg-n3 pb-2 pb-lg-4 px-lg-4"> <div class="HeaderMenu-column"> <div class="border-bottom pb-3 pb-lg-0 pb-lg-3 mb-3 mb-lg-0 mb-lg-3"> <ul class="list-style-none f5" > <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary d-flex flex-items-center Link--has-description" data-analytics-event="{"location":"navbar","action":"enterprise_platform","context":"enterprise","tag":"link","label":"enterprise_platform_link_enterprise_navbar"}" href="/enterprise"> <svg aria-hidden="true" height="24" viewBox="0 0 24 24" version="1.1" width="24" data-view-component="true" class="octicon octicon-stack color-fg-subtle mr-3"> <path d="M11.063 1.456a1.749 1.749 0 0 1 1.874 0l8.383 5.316a1.751 1.751 0 0 1 0 2.956l-8.383 5.316a1.749 1.749 0 0 1-1.874 0L2.68 9.728a1.751 1.751 0 0 1 0-2.956Zm1.071 1.267a.25.25 0 0 0-.268 0L3.483 8.039a.25.25 0 0 0 0 .422l8.383 5.316a.25.25 0 0 0 .268 0l8.383-5.316a.25.25 0 0 0 0-.422Z"></path><path d="M1.867 12.324a.75.75 0 0 1 1.035-.232l8.964 5.685a.25.25 0 0 0 .268 0l8.964-5.685a.75.75 0 0 1 .804 1.267l-8.965 5.685a1.749 1.749 0 0 1-1.874 0l-8.965-5.685a.75.75 0 0 1-.231-1.035Z"></path><path d="M1.867 16.324a.75.75 0 0 1 1.035-.232l8.964 5.685a.25.25 0 0 0 .268 0l8.964-5.685a.75.75 0 0 1 .804 1.267l-8.965 5.685a1.749 1.749 0 0 1-1.874 0l-8.965-5.685a.75.75 0 0 1-.231-1.035Z"></path> </svg> <div> <div class="color-fg-default h4">Enterprise platform</div> AI-powered developer platform </div> </a></li> </ul> </div> <div class="border-bottom pb-3 pb-lg-0 border-bottom-0"> <span class="d-block h4 color-fg-default my-1" id="enterprise-available-add-ons-heading">Available add-ons</span> <ul class="list-style-none f5" aria-labelledby="enterprise-available-add-ons-heading"> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary d-flex flex-items-center Link--has-description pb-lg-3" data-analytics-event="{"location":"navbar","action":"advanced_security","context":"enterprise","tag":"link","label":"advanced_security_link_enterprise_navbar"}" href="https://github.com/enterprise/advanced-security"> <svg aria-hidden="true" height="24" viewBox="0 0 24 24" version="1.1" width="24" data-view-component="true" class="octicon octicon-shield-check color-fg-subtle mr-3"> <path d="M16.53 9.78a.75.75 0 0 0-1.06-1.06L11 13.19l-1.97-1.97a.75.75 0 0 0-1.06 1.06l2.5 2.5a.75.75 0 0 0 1.06 0l5-5Z"></path><path d="m12.54.637 8.25 2.675A1.75 1.75 0 0 1 22 4.976V10c0 6.19-3.771 10.704-9.401 12.83a1.704 1.704 0 0 1-1.198 0C5.77 20.705 2 16.19 2 10V4.976c0-.758.489-1.43 1.21-1.664L11.46.637a1.748 1.748 0 0 1 1.08 0Zm-.617 1.426-8.25 2.676a.249.249 0 0 0-.173.237V10c0 5.46 3.28 9.483 8.43 11.426a.199.199 0 0 0 .14 0C17.22 19.483 20.5 15.461 20.5 10V4.976a.25.25 0 0 0-.173-.237l-8.25-2.676a.253.253 0 0 0-.154 0Z"></path> </svg> <div> <div class="color-fg-default h4">Advanced Security</div> Enterprise-grade security features </div> </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary d-flex flex-items-center Link--has-description pb-lg-3" data-analytics-event="{"location":"navbar","action":"github_copilot","context":"enterprise","tag":"link","label":"github_copilot_link_enterprise_navbar"}" href="/features/copilot#enterprise"> <svg aria-hidden="true" height="24" viewBox="0 0 24 24" version="1.1" width="24" data-view-component="true" class="octicon octicon-copilot color-fg-subtle mr-3"> <path d="M23.922 16.992c-.861 1.495-5.859 5.023-11.922 5.023-6.063 0-11.061-3.528-11.922-5.023A.641.641 0 0 1 0 16.736v-2.869a.841.841 0 0 1 .053-.22c.372-.935 1.347-2.292 2.605-2.656.167-.429.414-1.055.644-1.517a10.195 10.195 0 0 1-.052-1.086c0-1.331.282-2.499 1.132-3.368.397-.406.89-.717 1.474-.952 1.399-1.136 3.392-2.093 6.122-2.093 2.731 0 4.767.957 6.166 2.093.584.235 1.077.546 1.474.952.85.869 1.132 2.037 1.132 3.368 0 .368-.014.733-.052 1.086.23.462.477 1.088.644 1.517 1.258.364 2.233 1.721 2.605 2.656a.832.832 0 0 1 .053.22v2.869a.641.641 0 0 1-.078.256ZM12.172 11h-.344a4.323 4.323 0 0 1-.355.508C10.703 12.455 9.555 13 7.965 13c-1.725 0-2.989-.359-3.782-1.259a2.005 2.005 0 0 1-.085-.104L4 11.741v6.585c1.435.779 4.514 2.179 8 2.179 3.486 0 6.565-1.4 8-2.179v-6.585l-.098-.104s-.033.045-.085.104c-.793.9-2.057 1.259-3.782 1.259-1.59 0-2.738-.545-3.508-1.492a4.323 4.323 0 0 1-.355-.508h-.016.016Zm.641-2.935c.136 1.057.403 1.913.878 2.497.442.544 1.134.938 2.344.938 1.573 0 2.292-.337 2.657-.751.384-.435.558-1.15.558-2.361 0-1.14-.243-1.847-.705-2.319-.477-.488-1.319-.862-2.824-1.025-1.487-.161-2.192.138-2.533.529-.269.307-.437.808-.438 1.578v.021c0 .265.021.562.063.893Zm-1.626 0c.042-.331.063-.628.063-.894v-.02c-.001-.77-.169-1.271-.438-1.578-.341-.391-1.046-.69-2.533-.529-1.505.163-2.347.537-2.824 1.025-.462.472-.705 1.179-.705 2.319 0 1.211.175 1.926.558 2.361.365.414 1.084.751 2.657.751 1.21 0 1.902-.394 2.344-.938.475-.584.742-1.44.878-2.497Z"></path><path d="M14.5 14.25a1 1 0 0 1 1 1v2a1 1 0 0 1-2 0v-2a1 1 0 0 1 1-1Zm-5 0a1 1 0 0 1 1 1v2a1 1 0 0 1-2 0v-2a1 1 0 0 1 1-1Z"></path> </svg> <div> <div class="color-fg-default h4">GitHub Copilot</div> Enterprise-grade AI features </div> </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary d-flex flex-items-center Link--has-description" data-analytics-event="{"location":"navbar","action":"premium_support","context":"enterprise","tag":"link","label":"premium_support_link_enterprise_navbar"}" href="/premium-support"> <svg aria-hidden="true" height="24" viewBox="0 0 24 24" version="1.1" width="24" data-view-component="true" class="octicon octicon-comment-discussion color-fg-subtle mr-3"> <path d="M1.75 1h12.5c.966 0 1.75.784 1.75 1.75v9.5A1.75 1.75 0 0 1 14.25 14H8.061l-2.574 2.573A1.458 1.458 0 0 1 3 15.543V14H1.75A1.75 1.75 0 0 1 0 12.25v-9.5C0 1.784.784 1 1.75 1ZM1.5 2.75v9.5c0 .138.112.25.25.25h2a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h6.5a.25.25 0 0 0 .25-.25v-9.5a.25.25 0 0 0-.25-.25H1.75a.25.25 0 0 0-.25.25Z"></path><path d="M22.5 8.75a.25.25 0 0 0-.25-.25h-3.5a.75.75 0 0 1 0-1.5h3.5c.966 0 1.75.784 1.75 1.75v9.5A1.75 1.75 0 0 1 22.25 20H21v1.543a1.457 1.457 0 0 1-2.487 1.03L15.939 20H10.75A1.75 1.75 0 0 1 9 18.25v-1.465a.75.75 0 0 1 1.5 0v1.465c0 .138.112.25.25.25h5.5a.75.75 0 0 1 .53.22l2.72 2.72v-2.19a.75.75 0 0 1 .75-.75h2a.25.25 0 0 0 .25-.25v-9.5Z"></path> </svg> <div> <div class="color-fg-default h4">Premium Support</div> Enterprise-grade 24/7 support </div> </a></li> </ul> </div> </div> </div> </li> <li class="HeaderMenu-item position-relative flex-wrap flex-justify-between flex-items-center d-block d-lg-flex flex-lg-nowrap flex-lg-items-center js-details-container js-header-menu-item"> <a class="HeaderMenu-link no-underline px-0 px-lg-2 py-3 py-lg-2 d-block d-lg-inline-block" data-analytics-event="{"location":"navbar","action":"pricing","context":"global","tag":"link","label":"pricing_link_global_navbar"}" href="https://github.com/pricing">Pricing</a> </li> </ul> </nav> <div class="d-flex flex-column flex-lg-row width-full flex-justify-end flex-lg-items-center text-center mt-3 mt-lg-0 text-lg-left ml-lg-3"> <qbsearch-input class="search-input" data-scope="repo:python/peps" data-custom-scopes-path="/search/custom_scopes" data-delete-custom-scopes-csrf="ddiFdNxKj28U-83gwi3kEq-XaO7Pv9yVyqUVOMCkhPDlW-f1EAp5c3_HKpmt0v9reNSJzpEK56Dd5TWTalkQ6A" data-max-custom-scopes="10" data-header-redesign-enabled="false" data-initial-value="" data-blackbird-suggestions-path="/search/suggestions" data-jump-to-suggestions-path="/_graphql/GetSuggestedNavigationDestinations" data-current-repository="python/peps" data-current-org="python" data-current-owner="" data-logged-in="false" data-copilot-chat-enabled="false" data-nl-search-enabled="false" data-retain-scroll-position="true"> <div class="search-input-container search-with-dialog position-relative d-flex flex-row flex-items-center mr-4 rounded" data-action="click:qbsearch-input#searchInputContainerClicked" > <button type="button" class="header-search-button placeholder input-button form-control d-flex flex-1 flex-self-stretch flex-items-center no-wrap width-full py-0 pl-2 pr-0 text-left border-0 box-shadow-none" data-target="qbsearch-input.inputButton" aria-label="Search or jump to…" aria-haspopup="dialog" placeholder="Search or jump to..." data-hotkey=s,/ autocapitalize="off" data-analytics-event="{"location":"navbar","action":"searchbar","context":"global","tag":"input","label":"searchbar_input_global_navbar"}" data-action="click:qbsearch-input#handleExpand" > <div class="mr-2 color-fg-muted"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-search"> <path d="M10.68 11.74a6 6 0 0 1-7.922-8.982 6 6 0 0 1 8.982 7.922l3.04 3.04a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215ZM11.5 7a4.499 4.499 0 1 0-8.997 0A4.499 4.499 0 0 0 11.5 7Z"></path> </svg> </div> <span class="flex-1" data-target="qbsearch-input.inputButtonText">Search or jump to...</span> <div class="d-flex" data-target="qbsearch-input.hotkeyIndicator"> <svg xmlns="http://www.w3.org/2000/svg" width="22" height="20" aria-hidden="true" class="mr-1"><path fill="none" stroke="#979A9C" opacity=".4" d="M3.5.5h12c1.7 0 3 1.3 3 3v13c0 1.7-1.3 3-3 3h-12c-1.7 0-3-1.3-3-3v-13c0-1.7 1.3-3 3-3z"></path><path fill="#979A9C" d="M11.8 6L8 15.1h-.9L10.8 6h1z"></path></svg> </div> </button> <input type="hidden" name="type" class="js-site-search-type-field"> <div class="Overlay--hidden " data-modal-dialog-overlay> <modal-dialog data-action="close:qbsearch-input#handleClose cancel:qbsearch-input#handleClose" data-target="qbsearch-input.searchSuggestionsDialog" role="dialog" id="search-suggestions-dialog" aria-modal="true" aria-labelledby="search-suggestions-dialog-header" data-view-component="true" class="Overlay Overlay--width-large Overlay--height-auto"> <h1 id="search-suggestions-dialog-header" class="sr-only">Search code, repositories, users, issues, pull requests...</h1> <div class="Overlay-body Overlay-body--paddingNone"> <div data-view-component="true"> <div class="search-suggestions position-fixed width-full color-shadow-large border color-fg-default color-bg-default overflow-hidden d-flex flex-column query-builder-container" style="border-radius: 12px;" data-target="qbsearch-input.queryBuilderContainer" hidden > <!-- '"` --><!-- </textarea></xmp> --></option></form><form id="query-builder-test-form" action="" accept-charset="UTF-8" method="get"> <query-builder data-target="qbsearch-input.queryBuilder" id="query-builder-query-builder-test" data-filter-key=":" data-view-component="true" class="QueryBuilder search-query-builder"> <div class="FormControl FormControl--fullWidth"> <label id="query-builder-test-label" for="query-builder-test" class="FormControl-label sr-only"> Search </label> <div class="QueryBuilder-StyledInput width-fit " data-target="query-builder.styledInput" > <span id="query-builder-test-leadingvisual-wrap" class="FormControl-input-leadingVisualWrap QueryBuilder-leadingVisualWrap"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-search FormControl-input-leadingVisual"> <path d="M10.68 11.74a6 6 0 0 1-7.922-8.982 6 6 0 0 1 8.982 7.922l3.04 3.04a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215ZM11.5 7a4.499 4.499 0 1 0-8.997 0A4.499 4.499 0 0 0 11.5 7Z"></path> </svg> </span> <div data-target="query-builder.styledInputContainer" class="QueryBuilder-StyledInputContainer"> <div aria-hidden="true" class="QueryBuilder-StyledInputContent" data-target="query-builder.styledInputContent" ></div> <div class="QueryBuilder-InputWrapper"> <div aria-hidden="true" class="QueryBuilder-Sizer" data-target="query-builder.sizer"></div> <input id="query-builder-test" name="query-builder-test" value="" autocomplete="off" type="text" role="combobox" spellcheck="false" aria-expanded="false" aria-describedby="validation-4badf7a8-a9a9-4600-a3dd-9c9a6b5707a0" data-target="query-builder.input" data-action=" input:query-builder#inputChange blur:query-builder#inputBlur keydown:query-builder#inputKeydown focus:query-builder#inputFocus " data-view-component="true" class="FormControl-input QueryBuilder-Input FormControl-medium" /> </div> </div> <span class="sr-only" id="query-builder-test-clear">Clear</span> <button role="button" id="query-builder-test-clear-button" aria-labelledby="query-builder-test-clear query-builder-test-label" data-target="query-builder.clearButton" data-action=" click:query-builder#clear focus:query-builder#clearButtonFocus blur:query-builder#clearButtonBlur " variant="small" hidden="hidden" type="button" data-view-component="true" class="Button Button--iconOnly Button--invisible Button--medium mr-1 px-2 py-0 d-flex flex-items-center rounded-1 color-fg-muted"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-x-circle-fill Button-visual"> <path d="M2.343 13.657A8 8 0 1 1 13.658 2.343 8 8 0 0 1 2.343 13.657ZM6.03 4.97a.751.751 0 0 0-1.042.018.751.751 0 0 0-.018 1.042L6.94 8 4.97 9.97a.749.749 0 0 0 .326 1.275.749.749 0 0 0 .734-.215L8 9.06l1.97 1.97a.749.749 0 0 0 1.275-.326.749.749 0 0 0-.215-.734L9.06 8l1.97-1.97a.749.749 0 0 0-.326-1.275.749.749 0 0 0-.734.215L8 6.94Z"></path> </svg> </button> </div> <template id="search-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-search"> <path d="M10.68 11.74a6 6 0 0 1-7.922-8.982 6 6 0 0 1 8.982 7.922l3.04 3.04a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215ZM11.5 7a4.499 4.499 0 1 0-8.997 0A4.499 4.499 0 0 0 11.5 7Z"></path> </svg> </template> <template id="code-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-code"> <path d="m11.28 3.22 4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734L13.94 8l-3.72-3.72a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215Zm-6.56 0a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042L2.06 8l3.72 3.72a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L.47 8.53a.75.75 0 0 1 0-1.06Z"></path> </svg> </template> <template id="file-code-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-file-code"> <path d="M4 1.75C4 .784 4.784 0 5.75 0h5.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v8.586A1.75 1.75 0 0 1 14.25 15h-9a.75.75 0 0 1 0-1.5h9a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 10 4.25V1.5H5.75a.25.25 0 0 0-.25.25v2.5a.75.75 0 0 1-1.5 0Zm1.72 4.97a.75.75 0 0 1 1.06 0l2 2a.75.75 0 0 1 0 1.06l-2 2a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734l1.47-1.47-1.47-1.47a.75.75 0 0 1 0-1.06ZM3.28 7.78 1.81 9.25l1.47 1.47a.751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018l-2-2a.75.75 0 0 1 0-1.06l2-2a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042Zm8.22-6.218V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"></path> </svg> </template> <template id="history-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-history"> <path d="m.427 1.927 1.215 1.215a8.002 8.002 0 1 1-1.6 5.685.75.75 0 1 1 1.493-.154 6.5 6.5 0 1 0 1.18-4.458l1.358 1.358A.25.25 0 0 1 3.896 6H.25A.25.25 0 0 1 0 5.75V2.104a.25.25 0 0 1 .427-.177ZM7.75 4a.75.75 0 0 1 .75.75v2.992l2.028.812a.75.75 0 0 1-.557 1.392l-2.5-1A.751.751 0 0 1 7 8.25v-3.5A.75.75 0 0 1 7.75 4Z"></path> </svg> </template> <template id="repo-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-repo"> <path d="M2 2.5A2.5 2.5 0 0 1 4.5 0h8.75a.75.75 0 0 1 .75.75v12.5a.75.75 0 0 1-.75.75h-2.5a.75.75 0 0 1 0-1.5h1.75v-2h-8a1 1 0 0 0-.714 1.7.75.75 0 1 1-1.072 1.05A2.495 2.495 0 0 1 2 11.5Zm10.5-1h-8a1 1 0 0 0-1 1v6.708A2.486 2.486 0 0 1 4.5 9h8ZM5 12.25a.25.25 0 0 1 .25-.25h3.5a.25.25 0 0 1 .25.25v3.25a.25.25 0 0 1-.4.2l-1.45-1.087a.249.249 0 0 0-.3 0L5.4 15.7a.25.25 0 0 1-.4-.2Z"></path> </svg> </template> <template id="bookmark-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-bookmark"> <path d="M3 2.75C3 1.784 3.784 1 4.75 1h6.5c.966 0 1.75.784 1.75 1.75v11.5a.75.75 0 0 1-1.227.579L8 11.722l-3.773 3.107A.751.751 0 0 1 3 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v9.91l3.023-2.489a.75.75 0 0 1 .954 0l3.023 2.49V2.75a.25.25 0 0 0-.25-.25Z"></path> </svg> </template> <template id="plus-circle-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-plus-circle"> <path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm7.25-3.25v2.5h2.5a.75.75 0 0 1 0 1.5h-2.5v2.5a.75.75 0 0 1-1.5 0v-2.5h-2.5a.75.75 0 0 1 0-1.5h2.5v-2.5a.75.75 0 0 1 1.5 0Z"></path> </svg> </template> <template id="circle-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-dot-fill"> <path d="M8 4a4 4 0 1 1 0 8 4 4 0 0 1 0-8Z"></path> </svg> </template> <template id="trash-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-trash"> <path d="M11 1.75V3h2.25a.75.75 0 0 1 0 1.5H2.75a.75.75 0 0 1 0-1.5H5V1.75C5 .784 5.784 0 6.75 0h2.5C10.216 0 11 .784 11 1.75ZM4.496 6.675l.66 6.6a.25.25 0 0 0 .249.225h5.19a.25.25 0 0 0 .249-.225l.66-6.6a.75.75 0 0 1 1.492.149l-.66 6.6A1.748 1.748 0 0 1 10.595 15h-5.19a1.75 1.75 0 0 1-1.741-1.575l-.66-6.6a.75.75 0 1 1 1.492-.15ZM6.5 1.75V3h3V1.75a.25.25 0 0 0-.25-.25h-2.5a.25.25 0 0 0-.25.25Z"></path> </svg> </template> <template id="team-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-people"> <path d="M2 5.5a3.5 3.5 0 1 1 5.898 2.549 5.508 5.508 0 0 1 3.034 4.084.75.75 0 1 1-1.482.235 4 4 0 0 0-7.9 0 .75.75 0 0 1-1.482-.236A5.507 5.507 0 0 1 3.102 8.05 3.493 3.493 0 0 1 2 5.5ZM11 4a3.001 3.001 0 0 1 2.22 5.018 5.01 5.01 0 0 1 2.56 3.012.749.749 0 0 1-.885.954.752.752 0 0 1-.549-.514 3.507 3.507 0 0 0-2.522-2.372.75.75 0 0 1-.574-.73v-.352a.75.75 0 0 1 .416-.672A1.5 1.5 0 0 0 11 5.5.75.75 0 0 1 11 4Zm-5.5-.5a2 2 0 1 0-.001 3.999A2 2 0 0 0 5.5 3.5Z"></path> </svg> </template> <template id="project-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-project"> <path d="M1.75 0h12.5C15.216 0 16 .784 16 1.75v12.5A1.75 1.75 0 0 1 14.25 16H1.75A1.75 1.75 0 0 1 0 14.25V1.75C0 .784.784 0 1.75 0ZM1.5 1.75v12.5c0 .138.112.25.25.25h12.5a.25.25 0 0 0 .25-.25V1.75a.25.25 0 0 0-.25-.25H1.75a.25.25 0 0 0-.25.25ZM11.75 3a.75.75 0 0 1 .75.75v7.5a.75.75 0 0 1-1.5 0v-7.5a.75.75 0 0 1 .75-.75Zm-8.25.75a.75.75 0 0 1 1.5 0v5.5a.75.75 0 0 1-1.5 0ZM8 3a.75.75 0 0 1 .75.75v3.5a.75.75 0 0 1-1.5 0v-3.5A.75.75 0 0 1 8 3Z"></path> </svg> </template> <template id="pencil-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-pencil"> <path d="M11.013 1.427a1.75 1.75 0 0 1 2.474 0l1.086 1.086a1.75 1.75 0 0 1 0 2.474l-8.61 8.61c-.21.21-.47.364-.756.445l-3.251.93a.75.75 0 0 1-.927-.928l.929-3.25c.081-.286.235-.547.445-.758l8.61-8.61Zm.176 4.823L9.75 4.81l-6.286 6.287a.253.253 0 0 0-.064.108l-.558 1.953 1.953-.558a.253.253 0 0 0 .108-.064Zm1.238-3.763a.25.25 0 0 0-.354 0L10.811 3.75l1.439 1.44 1.263-1.263a.25.25 0 0 0 0-.354Z"></path> </svg> </template> <template id="copilot-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-copilot"> <path d="M7.998 15.035c-4.562 0-7.873-2.914-7.998-3.749V9.338c.085-.628.677-1.686 1.588-2.065.013-.07.024-.143.036-.218.029-.183.06-.384.126-.612-.201-.508-.254-1.084-.254-1.656 0-.87.128-1.769.693-2.484.579-.733 1.494-1.124 2.724-1.261 1.206-.134 2.262.034 2.944.765.05.053.096.108.139.165.044-.057.094-.112.143-.165.682-.731 1.738-.899 2.944-.765 1.23.137 2.145.528 2.724 1.261.566.715.693 1.614.693 2.484 0 .572-.053 1.148-.254 1.656.066.228.098.429.126.612.012.076.024.148.037.218.924.385 1.522 1.471 1.591 2.095v1.872c0 .766-3.351 3.795-8.002 3.795Zm0-1.485c2.28 0 4.584-1.11 5.002-1.433V7.862l-.023-.116c-.49.21-1.075.291-1.727.291-1.146 0-2.059-.327-2.71-.991A3.222 3.222 0 0 1 8 6.303a3.24 3.24 0 0 1-.544.743c-.65.664-1.563.991-2.71.991-.652 0-1.236-.081-1.727-.291l-.023.116v4.255c.419.323 2.722 1.433 5.002 1.433ZM6.762 2.83c-.193-.206-.637-.413-1.682-.297-1.019.113-1.479.404-1.713.7-.247.312-.369.789-.369 1.554 0 .793.129 1.171.308 1.371.162.181.519.379 1.442.379.853 0 1.339-.235 1.638-.54.315-.322.527-.827.617-1.553.117-.935-.037-1.395-.241-1.614Zm4.155-.297c-1.044-.116-1.488.091-1.681.297-.204.219-.359.679-.242 1.614.091.726.303 1.231.618 1.553.299.305.784.54 1.638.54.922 0 1.28-.198 1.442-.379.179-.2.308-.578.308-1.371 0-.765-.123-1.242-.37-1.554-.233-.296-.693-.587-1.713-.7Z"></path><path d="M6.25 9.037a.75.75 0 0 1 .75.75v1.501a.75.75 0 0 1-1.5 0V9.787a.75.75 0 0 1 .75-.75Zm4.25.75v1.501a.75.75 0 0 1-1.5 0V9.787a.75.75 0 0 1 1.5 0Z"></path> </svg> </template> <template id="copilot-error-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-copilot-error"> <path d="M16 11.24c0 .112-.072.274-.21.467L13 9.688V7.862l-.023-.116c-.49.21-1.075.291-1.727.291-.198 0-.388-.009-.571-.029L6.833 5.226a4.01 4.01 0 0 0 .17-.782c.117-.935-.037-1.395-.241-1.614-.193-.206-.637-.413-1.682-.297-.683.076-1.115.231-1.395.415l-1.257-.91c.579-.564 1.413-.877 2.485-.996 1.206-.134 2.262.034 2.944.765.05.053.096.108.139.165.044-.057.094-.112.143-.165.682-.731 1.738-.899 2.944-.765 1.23.137 2.145.528 2.724 1.261.566.715.693 1.614.693 2.484 0 .572-.053 1.148-.254 1.656.066.228.098.429.126.612.012.076.024.148.037.218.924.385 1.522 1.471 1.591 2.095Zm-5.083-8.707c-1.044-.116-1.488.091-1.681.297-.204.219-.359.679-.242 1.614.091.726.303 1.231.618 1.553.299.305.784.54 1.638.54.922 0 1.28-.198 1.442-.379.179-.2.308-.578.308-1.371 0-.765-.123-1.242-.37-1.554-.233-.296-.693-.587-1.713-.7Zm2.511 11.074c-1.393.776-3.272 1.428-5.43 1.428-4.562 0-7.873-2.914-7.998-3.749V9.338c.085-.628.677-1.686 1.588-2.065.013-.07.024-.143.036-.218.029-.183.06-.384.126-.612-.18-.455-.241-.963-.252-1.475L.31 4.107A.747.747 0 0 1 0 3.509V3.49a.748.748 0 0 1 .625-.73c.156-.026.306.047.435.139l14.667 10.578a.592.592 0 0 1 .227.264.752.752 0 0 1 .046.249v.022a.75.75 0 0 1-1.19.596Zm-1.367-.991L5.635 7.964a5.128 5.128 0 0 1-.889.073c-.652 0-1.236-.081-1.727-.291l-.023.116v4.255c.419.323 2.722 1.433 5.002 1.433 1.539 0 3.089-.505 4.063-.934Z"></path> </svg> </template> <template id="workflow-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-workflow"> <path d="M0 1.75C0 .784.784 0 1.75 0h3.5C6.216 0 7 .784 7 1.75v3.5A1.75 1.75 0 0 1 5.25 7H4v4a1 1 0 0 0 1 1h4v-1.25C9 9.784 9.784 9 10.75 9h3.5c.966 0 1.75.784 1.75 1.75v3.5A1.75 1.75 0 0 1 14.25 16h-3.5A1.75 1.75 0 0 1 9 14.25v-.75H5A2.5 2.5 0 0 1 2.5 11V7h-.75A1.75 1.75 0 0 1 0 5.25Zm1.75-.25a.25.25 0 0 0-.25.25v3.5c0 .138.112.25.25.25h3.5a.25.25 0 0 0 .25-.25v-3.5a.25.25 0 0 0-.25-.25Zm9 9a.25.25 0 0 0-.25.25v3.5c0 .138.112.25.25.25h3.5a.25.25 0 0 0 .25-.25v-3.5a.25.25 0 0 0-.25-.25Z"></path> </svg> </template> <template id="book-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-book"> <path d="M0 1.75A.75.75 0 0 1 .75 1h4.253c1.227 0 2.317.59 3 1.501A3.743 3.743 0 0 1 11.006 1h4.245a.75.75 0 0 1 .75.75v10.5a.75.75 0 0 1-.75.75h-4.507a2.25 2.25 0 0 0-1.591.659l-.622.621a.75.75 0 0 1-1.06 0l-.622-.621A2.25 2.25 0 0 0 5.258 13H.75a.75.75 0 0 1-.75-.75Zm7.251 10.324.004-5.073-.002-2.253A2.25 2.25 0 0 0 5.003 2.5H1.5v9h3.757a3.75 3.75 0 0 1 1.994.574ZM8.755 4.75l-.004 7.322a3.752 3.752 0 0 1 1.992-.572H14.5v-9h-3.495a2.25 2.25 0 0 0-2.25 2.25Z"></path> </svg> </template> <template id="code-review-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-code-review"> <path d="M1.75 1h12.5c.966 0 1.75.784 1.75 1.75v8.5A1.75 1.75 0 0 1 14.25 13H8.061l-2.574 2.573A1.458 1.458 0 0 1 3 14.543V13H1.75A1.75 1.75 0 0 1 0 11.25v-8.5C0 1.784.784 1 1.75 1ZM1.5 2.75v8.5c0 .138.112.25.25.25h2a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h6.5a.25.25 0 0 0 .25-.25v-8.5a.25.25 0 0 0-.25-.25H1.75a.25.25 0 0 0-.25.25Zm5.28 1.72a.75.75 0 0 1 0 1.06L5.31 7l1.47 1.47a.751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018l-2-2a.75.75 0 0 1 0-1.06l2-2a.75.75 0 0 1 1.06 0Zm2.44 0a.75.75 0 0 1 1.06 0l2 2a.75.75 0 0 1 0 1.06l-2 2a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L10.69 7 9.22 5.53a.75.75 0 0 1 0-1.06Z"></path> </svg> </template> <template id="codespaces-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-codespaces"> <path d="M0 11.25c0-.966.784-1.75 1.75-1.75h12.5c.966 0 1.75.784 1.75 1.75v3A1.75 1.75 0 0 1 14.25 16H1.75A1.75 1.75 0 0 1 0 14.25Zm2-9.5C2 .784 2.784 0 3.75 0h8.5C13.216 0 14 .784 14 1.75v5a1.75 1.75 0 0 1-1.75 1.75h-8.5A1.75 1.75 0 0 1 2 6.75Zm1.75-.25a.25.25 0 0 0-.25.25v5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-5a.25.25 0 0 0-.25-.25Zm-2 9.5a.25.25 0 0 0-.25.25v3c0 .138.112.25.25.25h12.5a.25.25 0 0 0 .25-.25v-3a.25.25 0 0 0-.25-.25Z"></path><path d="M7 12.75a.75.75 0 0 1 .75-.75h4.5a.75.75 0 0 1 0 1.5h-4.5a.75.75 0 0 1-.75-.75Zm-4 0a.75.75 0 0 1 .75-.75h.5a.75.75 0 0 1 0 1.5h-.5a.75.75 0 0 1-.75-.75Z"></path> </svg> </template> <template id="comment-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-comment"> <path d="M1 2.75C1 1.784 1.784 1 2.75 1h10.5c.966 0 1.75.784 1.75 1.75v7.5A1.75 1.75 0 0 1 13.25 12H9.06l-2.573 2.573A1.458 1.458 0 0 1 4 13.543V12H2.75A1.75 1.75 0 0 1 1 10.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h2a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h4.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path> </svg> </template> <template id="comment-discussion-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-comment-discussion"> <path d="M1.75 1h8.5c.966 0 1.75.784 1.75 1.75v5.5A1.75 1.75 0 0 1 10.25 10H7.061l-2.574 2.573A1.458 1.458 0 0 1 2 11.543V10h-.25A1.75 1.75 0 0 1 0 8.25v-5.5C0 1.784.784 1 1.75 1ZM1.5 2.75v5.5c0 .138.112.25.25.25h1a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h3.5a.25.25 0 0 0 .25-.25v-5.5a.25.25 0 0 0-.25-.25h-8.5a.25.25 0 0 0-.25.25Zm13 2a.25.25 0 0 0-.25-.25h-.5a.75.75 0 0 1 0-1.5h.5c.966 0 1.75.784 1.75 1.75v5.5A1.75 1.75 0 0 1 14.25 12H14v1.543a1.458 1.458 0 0 1-2.487 1.03L9.22 12.28a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215l2.22 2.22v-2.19a.75.75 0 0 1 .75-.75h1a.25.25 0 0 0 .25-.25Z"></path> </svg> </template> <template id="organization-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-organization"> <path d="M1.75 16A1.75 1.75 0 0 1 0 14.25V1.75C0 .784.784 0 1.75 0h8.5C11.216 0 12 .784 12 1.75v12.5c0 .085-.006.168-.018.25h2.268a.25.25 0 0 0 .25-.25V8.285a.25.25 0 0 0-.111-.208l-1.055-.703a.749.749 0 1 1 .832-1.248l1.055.703c.487.325.779.871.779 1.456v5.965A1.75 1.75 0 0 1 14.25 16h-3.5a.766.766 0 0 1-.197-.026c-.099.017-.2.026-.303.026h-3a.75.75 0 0 1-.75-.75V14h-1v1.25a.75.75 0 0 1-.75.75Zm-.25-1.75c0 .138.112.25.25.25H4v-1.25a.75.75 0 0 1 .75-.75h2.5a.75.75 0 0 1 .75.75v1.25h2.25a.25.25 0 0 0 .25-.25V1.75a.25.25 0 0 0-.25-.25h-8.5a.25.25 0 0 0-.25.25ZM3.75 6h.5a.75.75 0 0 1 0 1.5h-.5a.75.75 0 0 1 0-1.5ZM3 3.75A.75.75 0 0 1 3.75 3h.5a.75.75 0 0 1 0 1.5h-.5A.75.75 0 0 1 3 3.75Zm4 3A.75.75 0 0 1 7.75 6h.5a.75.75 0 0 1 0 1.5h-.5A.75.75 0 0 1 7 6.75ZM7.75 3h.5a.75.75 0 0 1 0 1.5h-.5a.75.75 0 0 1 0-1.5ZM3 9.75A.75.75 0 0 1 3.75 9h.5a.75.75 0 0 1 0 1.5h-.5A.75.75 0 0 1 3 9.75ZM7.75 9h.5a.75.75 0 0 1 0 1.5h-.5a.75.75 0 0 1 0-1.5Z"></path> </svg> </template> <template id="rocket-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-rocket"> <path d="M14.064 0h.186C15.216 0 16 .784 16 1.75v.186a8.752 8.752 0 0 1-2.564 6.186l-.458.459c-.314.314-.641.616-.979.904v3.207c0 .608-.315 1.172-.833 1.49l-2.774 1.707a.749.749 0 0 1-1.11-.418l-.954-3.102a1.214 1.214 0 0 1-.145-.125L3.754 9.816a1.218 1.218 0 0 1-.124-.145L.528 8.717a.749.749 0 0 1-.418-1.11l1.71-2.774A1.748 1.748 0 0 1 3.31 4h3.204c.288-.338.59-.665.904-.979l.459-.458A8.749 8.749 0 0 1 14.064 0ZM8.938 3.623h-.002l-.458.458c-.76.76-1.437 1.598-2.02 2.5l-1.5 2.317 2.143 2.143 2.317-1.5c.902-.583 1.74-1.26 2.499-2.02l.459-.458a7.25 7.25 0 0 0 2.123-5.127V1.75a.25.25 0 0 0-.25-.25h-.186a7.249 7.249 0 0 0-5.125 2.123ZM3.56 14.56c-.732.732-2.334 1.045-3.005 1.148a.234.234 0 0 1-.201-.064.234.234 0 0 1-.064-.201c.103-.671.416-2.273 1.15-3.003a1.502 1.502 0 1 1 2.12 2.12Zm6.94-3.935c-.088.06-.177.118-.266.175l-2.35 1.521.548 1.783 1.949-1.2a.25.25 0 0 0 .119-.213ZM3.678 8.116 5.2 5.766c.058-.09.117-.178.176-.266H3.309a.25.25 0 0 0-.213.119l-1.2 1.95ZM12 5a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path> </svg> </template> <template id="shield-check-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-shield-check"> <path d="m8.533.133 5.25 1.68A1.75 1.75 0 0 1 15 3.48V7c0 1.566-.32 3.182-1.303 4.682-.983 1.498-2.585 2.813-5.032 3.855a1.697 1.697 0 0 1-1.33 0c-2.447-1.042-4.049-2.357-5.032-3.855C1.32 10.182 1 8.566 1 7V3.48a1.75 1.75 0 0 1 1.217-1.667l5.25-1.68a1.748 1.748 0 0 1 1.066 0Zm-.61 1.429.001.001-5.25 1.68a.251.251 0 0 0-.174.237V7c0 1.36.275 2.666 1.057 3.859.784 1.194 2.121 2.342 4.366 3.298a.196.196 0 0 0 .154 0c2.245-.957 3.582-2.103 4.366-3.297C13.225 9.666 13.5 8.358 13.5 7V3.48a.25.25 0 0 0-.174-.238l-5.25-1.68a.25.25 0 0 0-.153 0ZM11.28 6.28l-3.5 3.5a.75.75 0 0 1-1.06 0l-1.5-1.5a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215l.97.97 2.97-2.97a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042Z"></path> </svg> </template> <template id="heart-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-heart"> <path d="m8 14.25.345.666a.75.75 0 0 1-.69 0l-.008-.004-.018-.01a7.152 7.152 0 0 1-.31-.17 22.055 22.055 0 0 1-3.434-2.414C2.045 10.731 0 8.35 0 5.5 0 2.836 2.086 1 4.25 1 5.797 1 7.153 1.802 8 3.02 8.847 1.802 10.203 1 11.75 1 13.914 1 16 2.836 16 5.5c0 2.85-2.045 5.231-3.885 6.818a22.066 22.066 0 0 1-3.744 2.584l-.018.01-.006.003h-.002ZM4.25 2.5c-1.336 0-2.75 1.164-2.75 3 0 2.15 1.58 4.144 3.365 5.682A20.58 20.58 0 0 0 8 13.393a20.58 20.58 0 0 0 3.135-2.211C12.92 9.644 14.5 7.65 14.5 5.5c0-1.836-1.414-3-2.75-3-1.373 0-2.609.986-3.029 2.456a.749.749 0 0 1-1.442 0C6.859 3.486 5.623 2.5 4.25 2.5Z"></path> </svg> </template> <template id="server-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-server"> <path d="M1.75 1h12.5c.966 0 1.75.784 1.75 1.75v4c0 .372-.116.717-.314 1 .198.283.314.628.314 1v4a1.75 1.75 0 0 1-1.75 1.75H1.75A1.75 1.75 0 0 1 0 12.75v-4c0-.358.109-.707.314-1a1.739 1.739 0 0 1-.314-1v-4C0 1.784.784 1 1.75 1ZM1.5 2.75v4c0 .138.112.25.25.25h12.5a.25.25 0 0 0 .25-.25v-4a.25.25 0 0 0-.25-.25H1.75a.25.25 0 0 0-.25.25Zm.25 5.75a.25.25 0 0 0-.25.25v4c0 .138.112.25.25.25h12.5a.25.25 0 0 0 .25-.25v-4a.25.25 0 0 0-.25-.25ZM7 4.75A.75.75 0 0 1 7.75 4h4.5a.75.75 0 0 1 0 1.5h-4.5A.75.75 0 0 1 7 4.75ZM7.75 10h4.5a.75.75 0 0 1 0 1.5h-4.5a.75.75 0 0 1 0-1.5ZM3 4.75A.75.75 0 0 1 3.75 4h.5a.75.75 0 0 1 0 1.5h-.5A.75.75 0 0 1 3 4.75ZM3.75 10h.5a.75.75 0 0 1 0 1.5h-.5a.75.75 0 0 1 0-1.5Z"></path> </svg> </template> <template id="globe-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-globe"> <path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM5.78 8.75a9.64 9.64 0 0 0 1.363 4.177c.255.426.542.832.857 1.215.245-.296.551-.705.857-1.215A9.64 9.64 0 0 0 10.22 8.75Zm4.44-1.5a9.64 9.64 0 0 0-1.363-4.177c-.307-.51-.612-.919-.857-1.215a9.927 9.927 0 0 0-.857 1.215A9.64 9.64 0 0 0 5.78 7.25Zm-5.944 1.5H1.543a6.507 6.507 0 0 0 4.666 5.5c-.123-.181-.24-.365-.352-.552-.715-1.192-1.437-2.874-1.581-4.948Zm-2.733-1.5h2.733c.144-2.074.866-3.756 1.58-4.948.12-.197.237-.381.353-.552a6.507 6.507 0 0 0-4.666 5.5Zm10.181 1.5c-.144 2.074-.866 3.756-1.58 4.948-.12.197-.237.381-.353.552a6.507 6.507 0 0 0 4.666-5.5Zm2.733-1.5a6.507 6.507 0 0 0-4.666-5.5c.123.181.24.365.353.552.714 1.192 1.436 2.874 1.58 4.948Z"></path> </svg> </template> <template id="issue-opened-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-issue-opened"> <path d="M8 9.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path><path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Z"></path> </svg> </template> <template id="device-mobile-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-device-mobile"> <path d="M3.75 0h8.5C13.216 0 14 .784 14 1.75v12.5A1.75 1.75 0 0 1 12.25 16h-8.5A1.75 1.75 0 0 1 2 14.25V1.75C2 .784 2.784 0 3.75 0ZM3.5 1.75v12.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25V1.75a.25.25 0 0 0-.25-.25h-8.5a.25.25 0 0 0-.25.25ZM8 13a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"></path> </svg> </template> <template id="package-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-package"> <path d="m8.878.392 5.25 3.045c.54.314.872.89.872 1.514v6.098a1.75 1.75 0 0 1-.872 1.514l-5.25 3.045a1.75 1.75 0 0 1-1.756 0l-5.25-3.045A1.75 1.75 0 0 1 1 11.049V4.951c0-.624.332-1.201.872-1.514L7.122.392a1.75 1.75 0 0 1 1.756 0ZM7.875 1.69l-4.63 2.685L8 7.133l4.755-2.758-4.63-2.685a.248.248 0 0 0-.25 0ZM2.5 5.677v5.372c0 .09.047.171.125.216l4.625 2.683V8.432Zm6.25 8.271 4.625-2.683a.25.25 0 0 0 .125-.216V5.677L8.75 8.432Z"></path> </svg> </template> <template id="credit-card-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-credit-card"> <path d="M10.75 9a.75.75 0 0 0 0 1.5h1.5a.75.75 0 0 0 0-1.5h-1.5Z"></path><path d="M0 3.75C0 2.784.784 2 1.75 2h12.5c.966 0 1.75.784 1.75 1.75v8.5A1.75 1.75 0 0 1 14.25 14H1.75A1.75 1.75 0 0 1 0 12.25ZM14.5 6.5h-13v5.75c0 .138.112.25.25.25h12.5a.25.25 0 0 0 .25-.25Zm0-2.75a.25.25 0 0 0-.25-.25H1.75a.25.25 0 0 0-.25.25V5h13Z"></path> </svg> </template> <template id="play-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-play"> <path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm4.879-2.773 4.264 2.559a.25.25 0 0 1 0 .428l-4.264 2.559A.25.25 0 0 1 6 10.559V5.442a.25.25 0 0 1 .379-.215Z"></path> </svg> </template> <template id="gift-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-gift"> <path d="M2 2.75A2.75 2.75 0 0 1 4.75 0c.983 0 1.873.42 2.57 1.232.268.318.497.668.68 1.042.183-.375.411-.725.68-1.044C9.376.42 10.266 0 11.25 0a2.75 2.75 0 0 1 2.45 4h.55c.966 0 1.75.784 1.75 1.75v2c0 .698-.409 1.301-1 1.582v4.918A1.75 1.75 0 0 1 13.25 16H2.75A1.75 1.75 0 0 1 1 14.25V9.332C.409 9.05 0 8.448 0 7.75v-2C0 4.784.784 4 1.75 4h.55c-.192-.375-.3-.8-.3-1.25ZM7.25 9.5H2.5v4.75c0 .138.112.25.25.25h4.5Zm1.5 0v5h4.5a.25.25 0 0 0 .25-.25V9.5Zm0-4V8h5.5a.25.25 0 0 0 .25-.25v-2a.25.25 0 0 0-.25-.25Zm-7 0a.25.25 0 0 0-.25.25v2c0 .138.112.25.25.25h5.5V5.5h-5.5Zm3-4a1.25 1.25 0 0 0 0 2.5h2.309c-.233-.818-.542-1.401-.878-1.793-.43-.502-.915-.707-1.431-.707ZM8.941 4h2.309a1.25 1.25 0 0 0 0-2.5c-.516 0-1 .205-1.43.707-.337.392-.646.975-.879 1.793Z"></path> </svg> </template> <template id="code-square-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-code-square"> <path d="M0 1.75C0 .784.784 0 1.75 0h12.5C15.216 0 16 .784 16 1.75v12.5A1.75 1.75 0 0 1 14.25 16H1.75A1.75 1.75 0 0 1 0 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h12.5a.25.25 0 0 0 .25-.25V1.75a.25.25 0 0 0-.25-.25Zm7.47 3.97a.75.75 0 0 1 1.06 0l2 2a.75.75 0 0 1 0 1.06l-2 2a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734L10.69 8 9.22 6.53a.75.75 0 0 1 0-1.06ZM6.78 6.53 5.31 8l1.47 1.47a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215l-2-2a.75.75 0 0 1 0-1.06l2-2a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042Z"></path> </svg> </template> <template id="device-desktop-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-device-desktop"> <path d="M14.25 1c.966 0 1.75.784 1.75 1.75v7.5A1.75 1.75 0 0 1 14.25 12h-3.727c.099 1.041.52 1.872 1.292 2.757A.752.752 0 0 1 11.25 16h-6.5a.75.75 0 0 1-.565-1.243c.772-.885 1.192-1.716 1.292-2.757H1.75A1.75 1.75 0 0 1 0 10.25v-7.5C0 1.784.784 1 1.75 1ZM1.75 2.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h12.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25ZM9.018 12H6.982a5.72 5.72 0 0 1-.765 2.5h3.566a5.72 5.72 0 0 1-.765-2.5Z"></path> </svg> </template> <div class="position-relative"> <ul role="listbox" class="ActionListWrap QueryBuilder-ListWrap" aria-label="Suggestions" data-action=" combobox-commit:query-builder#comboboxCommit mousedown:query-builder#resultsMousedown " data-target="query-builder.resultsList" data-persist-list=false id="query-builder-test-results" ></ul> </div> <div class="FormControl-inlineValidation" id="validation-4badf7a8-a9a9-4600-a3dd-9c9a6b5707a0" hidden="hidden"> <span class="FormControl-inlineValidation--visual"> <svg aria-hidden="true" height="12" viewBox="0 0 12 12" version="1.1" width="12" data-view-component="true" class="octicon octicon-alert-fill"> <path d="M4.855.708c.5-.896 1.79-.896 2.29 0l4.675 8.351a1.312 1.312 0 0 1-1.146 1.954H1.33A1.313 1.313 0 0 1 .183 9.058ZM7 7V3H5v4Zm-1 3a1 1 0 1 0 0-2 1 1 0 0 0 0 2Z"></path> </svg> </span> <span></span> </div> </div> <div data-target="query-builder.screenReaderFeedback" aria-live="polite" aria-atomic="true" class="sr-only"></div> </query-builder></form> <div class="d-flex flex-row color-fg-muted px-3 text-small color-bg-default search-feedback-prompt"> <a target="_blank" href="https://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax" data-view-component="true" class="Link color-fg-accent text-normal ml-2">Search syntax tips</a> <div class="d-flex flex-1"></div> </div> </div> </div> </div> </modal-dialog></div> </div> <div data-action="click:qbsearch-input#retract" class="dark-backdrop position-fixed" hidden data-target="qbsearch-input.darkBackdrop"></div> <div class="color-fg-default"> <dialog-helper> <dialog data-target="qbsearch-input.feedbackDialog" data-action="close:qbsearch-input#handleDialogClose cancel:qbsearch-input#handleDialogClose" id="feedback-dialog" aria-modal="true" aria-labelledby="feedback-dialog-title" aria-describedby="feedback-dialog-description" data-view-component="true" class="Overlay Overlay-whenNarrow Overlay--size-medium Overlay--motion-scaleFade Overlay--disableScroll"> <div data-view-component="true" class="Overlay-header"> <div class="Overlay-headerContentWrap"> <div class="Overlay-titleWrap"> <h1 class="Overlay-title " id="feedback-dialog-title"> Provide feedback </h1> </div> <div class="Overlay-actionWrap"> <button data-close-dialog-id="feedback-dialog" aria-label="Close" type="button" data-view-component="true" class="close-button Overlay-closeButton"><svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-x"> <path d="M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734L9.06 8l3.22 3.22a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L8 9.06l-3.22 3.22a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06Z"></path> </svg></button> </div> </div> </div> <scrollable-region data-labelled-by="feedback-dialog-title"> <div data-view-component="true" class="Overlay-body"> <!-- '"` --><!-- </textarea></xmp> --></option></form><form id="code-search-feedback-form" data-turbo="false" action="/search/feedback" accept-charset="UTF-8" method="post"><input type="hidden" data-csrf="true" name="authenticity_token" value="q/A7jKzLHB42FgVmxkZIrHDod0q/wgCdHeT+55311E29kG7Mp87w4x5oAbhL84fZbXKcTf1PXnW47X+tA03JDg==" /> <p>We read every piece of feedback, and take your input very seriously.</p> <textarea name="feedback" class="form-control width-full mb-2" style="height: 120px" id="feedback"></textarea> <input name="include_email" id="include_email" aria-label="Include my email address so I can be contacted" class="form-control mr-2" type="checkbox"> <label for="include_email" style="font-weight: normal">Include my email address so I can be contacted</label> </form></div> </scrollable-region> <div data-view-component="true" class="Overlay-footer Overlay-footer--alignEnd"> <button data-close-dialog-id="feedback-dialog" type="button" data-view-component="true" class="btn"> Cancel </button> <button form="code-search-feedback-form" data-action="click:qbsearch-input#submitFeedback" type="submit" data-view-component="true" class="btn-primary btn"> Submit feedback </button> </div> </dialog></dialog-helper> <custom-scopes data-target="qbsearch-input.customScopesManager"> <dialog-helper> <dialog data-target="custom-scopes.customScopesModalDialog" data-action="close:qbsearch-input#handleDialogClose cancel:qbsearch-input#handleDialogClose" id="custom-scopes-dialog" aria-modal="true" aria-labelledby="custom-scopes-dialog-title" aria-describedby="custom-scopes-dialog-description" data-view-component="true" class="Overlay Overlay-whenNarrow Overlay--size-medium Overlay--motion-scaleFade Overlay--disableScroll"> <div data-view-component="true" class="Overlay-header Overlay-header--divided"> <div class="Overlay-headerContentWrap"> <div class="Overlay-titleWrap"> <h1 class="Overlay-title " id="custom-scopes-dialog-title"> Saved searches </h1> <h2 id="custom-scopes-dialog-description" class="Overlay-description">Use saved searches to filter your results more quickly</h2> </div> <div class="Overlay-actionWrap"> <button data-close-dialog-id="custom-scopes-dialog" aria-label="Close" type="button" data-view-component="true" class="close-button Overlay-closeButton"><svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-x"> <path d="M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734L9.06 8l3.22 3.22a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L8 9.06l-3.22 3.22a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06Z"></path> </svg></button> </div> </div> </div> <scrollable-region data-labelled-by="custom-scopes-dialog-title"> <div data-view-component="true" class="Overlay-body"> <div data-target="custom-scopes.customScopesModalDialogFlash"></div> <div hidden class="create-custom-scope-form" data-target="custom-scopes.createCustomScopeForm"> <!-- '"` --><!-- </textarea></xmp> --></option></form><form id="custom-scopes-dialog-form" data-turbo="false" action="/search/custom_scopes" accept-charset="UTF-8" method="post"><input type="hidden" data-csrf="true" name="authenticity_token" value="q86shzSWKi82+QwmG5MU7J+zdTWYPc8RJdMQnBTv129z4sQDh/2RtHxmEr9QeCOsFKem3C4qsLaAbNfGksXvMg==" /> <div data-target="custom-scopes.customScopesModalDialogFlash"></div> <input type="hidden" id="custom_scope_id" name="custom_scope_id" data-target="custom-scopes.customScopesIdField"> <div class="form-group"> <label for="custom_scope_name">Name</label> <auto-check src="/search/custom_scopes/check_name" required only-validate-on-blur="false"> <input type="text" name="custom_scope_name" id="custom_scope_name" data-target="custom-scopes.customScopesNameField" class="form-control" autocomplete="off" placeholder="github-ruby" required maxlength="50"> <input type="hidden" data-csrf="true" value="boZwvPq4gVav6sqka0G7SvdEDGXxinHs10c9snFf3rU+YLZbpcbUkpoavky6RcLyjUnT6/Y9B2QxJOHSHdqTxQ==" /> </auto-check> </div> <div class="form-group"> <label for="custom_scope_query">Query</label> <input type="text" name="custom_scope_query" id="custom_scope_query" data-target="custom-scopes.customScopesQueryField" class="form-control" autocomplete="off" placeholder="(repo:mona/a OR repo:mona/b) AND lang:python" required maxlength="500"> </div> <p class="text-small color-fg-muted"> To see all available qualifiers, see our <a class="Link--inTextBlock" href="https://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax">documentation</a>. </p> </form> </div> <div data-target="custom-scopes.manageCustomScopesForm"> <div data-target="custom-scopes.list"></div> </div> </div> </scrollable-region> <div data-view-component="true" class="Overlay-footer Overlay-footer--alignEnd Overlay-footer--divided"> <button data-action="click:custom-scopes#customScopesCancel" type="button" data-view-component="true" class="btn"> Cancel </button> <button form="custom-scopes-dialog-form" data-action="click:custom-scopes#customScopesSubmit" data-target="custom-scopes.customScopesSubmitButton" type="submit" data-view-component="true" class="btn-primary btn"> Create saved search </button> </div> </dialog></dialog-helper> </custom-scopes> </div> </qbsearch-input> <div class="position-relative HeaderMenu-link-wrap d-lg-inline-block"> <a href="/login?return_to=https%3A%2F%2Fgithub.com%2Fpython%2Fpeps%2Fblob%2Fmain%2Fpeps%2Fpep-0667.rst" class="HeaderMenu-link HeaderMenu-link--sign-in HeaderMenu-button flex-shrink-0 no-underline d-none d-lg-inline-flex border border-lg-0 rounded rounded-lg-0 px-2 py-1" style="margin-left: 12px;" data-hydro-click="{"event_type":"authentication.click","payload":{"location_in_page":"site header menu","repository_id":null,"auth_type":"SIGN_UP","originating_url":"https://github.com/python/peps/blob/main/peps/pep-0667.rst","user_id":null}}" data-hydro-click-hmac="e5178f01dfdf459929017c3f24bcd4c68f76f11c4196fead833dbd5ef9a7a272" data-analytics-event="{"category":"Marketing nav","action":"click to go to homepage","label":"ref_page:Marketing;ref_cta:Sign in;ref_loc:Header"}" > Sign in </a> </div> <a href="/signup?ref_cta=Sign+up&ref_loc=header+logged+out&ref_page=%2F%3Cuser-name%3E%2F%3Crepo-name%3E%2Fblob%2Fshow&source=header-repo&source_repo=python%2Fpeps" class="HeaderMenu-link HeaderMenu-link--sign-up HeaderMenu-button flex-shrink-0 d-flex d-lg-inline-flex no-underline border color-border-default rounded px-2 py-1" data-hydro-click="{"event_type":"authentication.click","payload":{"location_in_page":"site header menu","repository_id":null,"auth_type":"SIGN_UP","originating_url":"https://github.com/python/peps/blob/main/peps/pep-0667.rst","user_id":null}}" data-hydro-click-hmac="e5178f01dfdf459929017c3f24bcd4c68f76f11c4196fead833dbd5ef9a7a272" data-analytics-event="{"category":"Sign up","action":"click to sign up for account","label":"ref_page:/<user-name>/<repo-name>/blob/show;ref_cta:Sign up;ref_loc:header logged out"}" > Sign up </a> <button type="button" class="sr-only js-header-menu-focus-trap d-block d-lg-none">Reseting focus</button> </div> </div> </div> </div> </header> <div hidden="hidden" data-view-component="true" class="js-stale-session-flash stale-session-flash flash flash-warn flash-full"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-alert"> <path d="M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path> </svg> <span class="js-stale-session-flash-signed-in" hidden>You signed in with another tab or window. <a class="Link--inTextBlock" href="">Reload</a> to refresh your session.</span> <span class="js-stale-session-flash-signed-out" hidden>You signed out in another tab or window. <a class="Link--inTextBlock" href="">Reload</a> to refresh your session.</span> <span class="js-stale-session-flash-switched" hidden>You switched accounts on another tab or window. <a class="Link--inTextBlock" href="">Reload</a> to refresh your session.</span> <button id="icon-button-c6487f86-4402-4874-9a73-7c3a57128e86" aria-labelledby="tooltip-d55f6517-ca6d-4315-ab3d-337ad205dfee" type="button" data-view-component="true" class="Button Button--iconOnly Button--invisible Button--medium flash-close js-flash-close"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-x Button-visual"> <path d="M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734L9.06 8l3.22 3.22a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L8 9.06l-3.22 3.22a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06Z"></path> </svg> </button><tool-tip id="tooltip-d55f6517-ca6d-4315-ab3d-337ad205dfee" for="icon-button-c6487f86-4402-4874-9a73-7c3a57128e86" popover="manual" data-direction="s" data-type="label" data-view-component="true" class="sr-only position-absolute">Dismiss alert</tool-tip> </div> </div> <div id="start-of-content" class="show-on-focus"></div> <div id="js-flash-container" class="flash-container" data-turbo-replace> <template class="js-flash-template"> <div class="flash flash-full {{ className }}"> <div > <button autofocus class="flash-close js-flash-close" type="button" aria-label="Dismiss this message"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-x"> <path d="M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734L9.06 8l3.22 3.22a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L8 9.06l-3.22 3.22a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06Z"></path> </svg> </button> <div aria-atomic="true" role="alert" class="js-flash-alert"> <div>{{ message }}</div> </div> </div> </div> </template> </div> <div class="application-main " data-commit-hovercards-enabled data-discussion-hovercards-enabled data-issue-and-pr-hovercards-enabled data-project-hovercards-enabled > <div itemscope itemtype="http://schema.org/SoftwareSourceCode" class=""> <main id="js-repo-pjax-container" > <div id="repository-container-header" class="pt-3 hide-full-screen" style="background-color: var(--page-header-bgColor, var(--color-page-header-bg));" data-turbo-replace> <div class="d-flex flex-nowrap flex-justify-end mb-3 px-3 px-lg-5" style="gap: 1rem;"> <div class="flex-auto min-width-0 width-fit"> <div class=" d-flex flex-wrap flex-items-center wb-break-word f3 text-normal"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-repo color-fg-muted mr-2"> <path d="M2 2.5A2.5 2.5 0 0 1 4.5 0h8.75a.75.75 0 0 1 .75.75v12.5a.75.75 0 0 1-.75.75h-2.5a.75.75 0 0 1 0-1.5h1.75v-2h-8a1 1 0 0 0-.714 1.7.75.75 0 1 1-1.072 1.05A2.495 2.495 0 0 1 2 11.5Zm10.5-1h-8a1 1 0 0 0-1 1v6.708A2.486 2.486 0 0 1 4.5 9h8ZM5 12.25a.25.25 0 0 1 .25-.25h3.5a.25.25 0 0 1 .25.25v3.25a.25.25 0 0 1-.4.2l-1.45-1.087a.249.249 0 0 0-.3 0L5.4 15.7a.25.25 0 0 1-.4-.2Z"></path> </svg> <span class="author flex-self-stretch" itemprop="author"> <a class="url fn" rel="author" data-hovercard-type="organization" data-hovercard-url="/orgs/python/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="/python"> python </a> </span> <span class="mx-1 flex-self-stretch color-fg-muted">/</span> <strong itemprop="name" class="mr-2 flex-self-stretch"> <a data-pjax="#repo-content-pjax-container" data-turbo-frame="repo-content-turbo-frame" href="/python/peps">peps</a> </strong> <span></span><span class="Label Label--secondary v-align-middle mr-1">Public</span> </div> </div> <div id="repository-details-container" class="flex-shrink-0" data-turbo-replace style="max-width: 70%;"> <ul class="pagehead-actions flex-shrink-0 d-none d-md-inline" style="padding: 2px 0;"> <li> <include-fragment src="/python/peps/sponsor_button"></include-fragment> </li> <li> <a href="/login?return_to=%2Fpython%2Fpeps" rel="nofollow" id="repository-details-watch-button" data-hydro-click="{"event_type":"authentication.click","payload":{"location_in_page":"notification subscription menu watch","repository_id":null,"auth_type":"LOG_IN","originating_url":"https://github.com/python/peps/blob/main/peps/pep-0667.rst","user_id":null}}" data-hydro-click-hmac="01ace55ba0ca50d6255a1e31ad84aca3ca5c2792d8c148cd18138715ca6694a6" aria-label="You must be signed in to change notification settings" data-view-component="true" class="btn-sm btn"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-bell mr-2"> <path d="M8 16a2 2 0 0 0 1.985-1.75c.017-.137-.097-.25-.235-.25h-3.5c-.138 0-.252.113-.235.25A2 2 0 0 0 8 16ZM3 5a5 5 0 0 1 10 0v2.947c0 .05.015.098.042.139l1.703 2.555A1.519 1.519 0 0 1 13.482 13H2.518a1.516 1.516 0 0 1-1.263-2.36l1.703-2.554A.255.255 0 0 0 3 7.947Zm5-3.5A3.5 3.5 0 0 0 4.5 5v2.947c0 .346-.102.683-.294.97l-1.703 2.556a.017.017 0 0 0-.003.01l.001.006c0 .002.002.004.004.006l.006.004.007.001h10.964l.007-.001.006-.004.004-.006.001-.007a.017.017 0 0 0-.003-.01l-1.703-2.554a1.745 1.745 0 0 1-.294-.97V5A3.5 3.5 0 0 0 8 1.5Z"></path> </svg>Notifications </a> <tool-tip id="tooltip-2cec71c9-ca09-41c7-a4ee-da47f0dd99fd" for="repository-details-watch-button" popover="manual" data-direction="s" data-type="description" data-view-component="true" class="sr-only position-absolute">You must be signed in to change notification settings</tool-tip> </li> <li> <a icon="repo-forked" id="fork-button" href="/login?return_to=%2Fpython%2Fpeps" rel="nofollow" data-hydro-click="{"event_type":"authentication.click","payload":{"location_in_page":"repo details fork button","repository_id":13414105,"auth_type":"LOG_IN","originating_url":"https://github.com/python/peps/blob/main/peps/pep-0667.rst","user_id":null}}" data-hydro-click-hmac="0c44b279fb961ca95ed8004e9b6b1c7157105cca3c32c3125ee4e7ad9abf1763" data-view-component="true" class="btn-sm btn"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-repo-forked mr-2"> <path d="M5 5.372v.878c0 .414.336.75.75.75h4.5a.75.75 0 0 0 .75-.75v-.878a2.25 2.25 0 1 1 1.5 0v.878a2.25 2.25 0 0 1-2.25 2.25h-1.5v2.128a2.251 2.251 0 1 1-1.5 0V8.5h-1.5A2.25 2.25 0 0 1 3.5 6.25v-.878a2.25 2.25 0 1 1 1.5 0ZM5 3.25a.75.75 0 1 0-1.5 0 .75.75 0 0 0 1.5 0Zm6.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5Zm-3 8.75a.75.75 0 1 0-1.5 0 .75.75 0 0 0 1.5 0Z"></path> </svg>Fork <span id="repo-network-counter" data-pjax-replace="true" data-turbo-replace="true" title="1,572" data-view-component="true" class="Counter">1.6k</span> </a> </li> <li> <div data-view-component="true" class="BtnGroup d-flex"> <a href="/login?return_to=%2Fpython%2Fpeps" rel="nofollow" data-hydro-click="{"event_type":"authentication.click","payload":{"location_in_page":"star button","repository_id":13414105,"auth_type":"LOG_IN","originating_url":"https://github.com/python/peps/blob/main/peps/pep-0667.rst","user_id":null}}" data-hydro-click-hmac="c64276ad84843cf353ac5bc3edcc91bdd621acadb40719809c9ce98a610ca27c" aria-label="You must be signed in to star a repository" data-view-component="true" class="tooltipped tooltipped-sw btn-sm btn"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-star v-align-text-bottom d-inline-block mr-2"> <path d="M8 .25a.75.75 0 0 1 .673.418l1.882 3.815 4.21.612a.75.75 0 0 1 .416 1.279l-3.046 2.97.719 4.192a.751.751 0 0 1-1.088.791L8 12.347l-3.766 1.98a.75.75 0 0 1-1.088-.79l.72-4.194L.818 6.374a.75.75 0 0 1 .416-1.28l4.21-.611L7.327.668A.75.75 0 0 1 8 .25Zm0 2.445L6.615 5.5a.75.75 0 0 1-.564.41l-3.097.45 2.24 2.184a.75.75 0 0 1 .216.664l-.528 3.084 2.769-1.456a.75.75 0 0 1 .698 0l2.77 1.456-.53-3.084a.75.75 0 0 1 .216-.664l2.24-2.183-3.096-.45a.75.75 0 0 1-.564-.41L8 2.694Z"></path> </svg><span data-view-component="true" class="d-inline"> Star </span> <span id="repo-stars-counter-star" aria-label="4523 users starred this repository" data-singular-suffix="user starred this repository" data-plural-suffix="users starred this repository" data-turbo-replace="true" title="4,523" data-view-component="true" class="Counter js-social-count">4.5k</span> </a></div> </li> </ul> </div> </div> <div id="responsive-meta-container" data-turbo-replace> </div> <nav data-pjax="#js-repo-pjax-container" aria-label="Repository" data-view-component="true" class="js-repo-nav js-sidenav-container-pjax js-responsive-underlinenav overflow-hidden UnderlineNav px-3 px-md-4 px-lg-5"> <ul data-view-component="true" class="UnderlineNav-body list-style-none"> <li data-view-component="true" class="d-inline-flex"> <a id="code-tab" href="/python/peps" data-tab-item="i0code-tab" data-selected-links="repo_source repo_downloads repo_commits repo_releases repo_tags repo_branches repo_packages repo_deployments repo_attestations /python/peps" data-pjax="#repo-content-pjax-container" data-turbo-frame="repo-content-turbo-frame" data-hotkey="g c" data-analytics-event="{"category":"Underline navbar","action":"Click tab","label":"Code","target":"UNDERLINE_NAV.TAB"}" aria-current="page" data-view-component="true" class="UnderlineNav-item no-wrap js-responsive-underlinenav-item js-selected-navigation-item selected"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-code UnderlineNav-octicon d-none d-sm-inline"> <path d="m11.28 3.22 4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734L13.94 8l-3.72-3.72a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215Zm-6.56 0a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042L2.06 8l3.72 3.72a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L.47 8.53a.75.75 0 0 1 0-1.06Z"></path> </svg> <span data-content="Code">Code</span> <span id="code-repo-tab-count" data-pjax-replace="" data-turbo-replace="" title="Not available" data-view-component="true" class="Counter"></span> </a></li> <li data-view-component="true" class="d-inline-flex"> <a id="issues-tab" href="/python/peps/issues" data-tab-item="i1issues-tab" data-selected-links="repo_issues repo_labels repo_milestones /python/peps/issues" data-pjax="#repo-content-pjax-container" data-turbo-frame="repo-content-turbo-frame" data-hotkey="g i" data-analytics-event="{"category":"Underline navbar","action":"Click tab","label":"Issues","target":"UNDERLINE_NAV.TAB"}" data-view-component="true" class="UnderlineNav-item no-wrap js-responsive-underlinenav-item js-selected-navigation-item"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-issue-opened UnderlineNav-octicon d-none d-sm-inline"> <path d="M8 9.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path><path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Z"></path> </svg> <span data-content="Issues">Issues</span> <span id="issues-repo-tab-count" data-pjax-replace="" data-turbo-replace="" title="21" data-view-component="true" class="Counter">21</span> </a></li> <li data-view-component="true" class="d-inline-flex"> <a id="pull-requests-tab" href="/python/peps/pulls" data-tab-item="i2pull-requests-tab" data-selected-links="repo_pulls checks /python/peps/pulls" data-pjax="#repo-content-pjax-container" data-turbo-frame="repo-content-turbo-frame" data-hotkey="g p" data-analytics-event="{"category":"Underline navbar","action":"Click tab","label":"Pull requests","target":"UNDERLINE_NAV.TAB"}" data-view-component="true" class="UnderlineNav-item no-wrap js-responsive-underlinenav-item js-selected-navigation-item"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-git-pull-request UnderlineNav-octicon d-none d-sm-inline"> <path d="M1.5 3.25a2.25 2.25 0 1 1 3 2.122v5.256a2.251 2.251 0 1 1-1.5 0V5.372A2.25 2.25 0 0 1 1.5 3.25Zm5.677-.177L9.573.677A.25.25 0 0 1 10 .854V2.5h1A2.5 2.5 0 0 1 13.5 5v5.628a2.251 2.251 0 1 1-1.5 0V5a1 1 0 0 0-1-1h-1v1.646a.25.25 0 0 1-.427.177L7.177 3.427a.25.25 0 0 1 0-.354ZM3.75 2.5a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm0 9.5a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm8.25.75a.75.75 0 1 0 1.5 0 .75.75 0 0 0-1.5 0Z"></path> </svg> <span data-content="Pull requests">Pull requests</span> <span id="pull-requests-repo-tab-count" data-pjax-replace="" data-turbo-replace="" title="26" data-view-component="true" class="Counter">26</span> </a></li> <li data-view-component="true" class="d-inline-flex"> <a id="actions-tab" href="/python/peps/actions" data-tab-item="i3actions-tab" data-selected-links="repo_actions /python/peps/actions" data-pjax="#repo-content-pjax-container" data-turbo-frame="repo-content-turbo-frame" data-hotkey="g a" data-analytics-event="{"category":"Underline navbar","action":"Click tab","label":"Actions","target":"UNDERLINE_NAV.TAB"}" data-view-component="true" class="UnderlineNav-item no-wrap js-responsive-underlinenav-item js-selected-navigation-item"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-play UnderlineNav-octicon d-none d-sm-inline"> <path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm4.879-2.773 4.264 2.559a.25.25 0 0 1 0 .428l-4.264 2.559A.25.25 0 0 1 6 10.559V5.442a.25.25 0 0 1 .379-.215Z"></path> </svg> <span data-content="Actions">Actions</span> <span id="actions-repo-tab-count" data-pjax-replace="" data-turbo-replace="" title="Not available" data-view-component="true" class="Counter"></span> </a></li> <li data-view-component="true" class="d-inline-flex"> <a id="security-tab" href="/python/peps/security" data-tab-item="i4security-tab" data-selected-links="security overview alerts policy token_scanning code_scanning /python/peps/security" data-pjax="#repo-content-pjax-container" data-turbo-frame="repo-content-turbo-frame" data-hotkey="g s" data-analytics-event="{"category":"Underline navbar","action":"Click tab","label":"Security","target":"UNDERLINE_NAV.TAB"}" data-view-component="true" class="UnderlineNav-item no-wrap js-responsive-underlinenav-item js-selected-navigation-item"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-shield UnderlineNav-octicon d-none d-sm-inline"> <path d="M7.467.133a1.748 1.748 0 0 1 1.066 0l5.25 1.68A1.75 1.75 0 0 1 15 3.48V7c0 1.566-.32 3.182-1.303 4.682-.983 1.498-2.585 2.813-5.032 3.855a1.697 1.697 0 0 1-1.33 0c-2.447-1.042-4.049-2.357-5.032-3.855C1.32 10.182 1 8.566 1 7V3.48a1.75 1.75 0 0 1 1.217-1.667Zm.61 1.429a.25.25 0 0 0-.153 0l-5.25 1.68a.25.25 0 0 0-.174.238V7c0 1.358.275 2.666 1.057 3.86.784 1.194 2.121 2.34 4.366 3.297a.196.196 0 0 0 .154 0c2.245-.956 3.582-2.104 4.366-3.298C13.225 9.666 13.5 8.36 13.5 7V3.48a.251.251 0 0 0-.174-.237l-5.25-1.68ZM8.75 4.75v3a.75.75 0 0 1-1.5 0v-3a.75.75 0 0 1 1.5 0ZM9 10.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path> </svg> <span data-content="Security">Security</span> <include-fragment src="/python/peps/security/overall-count" accept="text/fragment+html"></include-fragment> </a></li> <li data-view-component="true" class="d-inline-flex"> <a id="insights-tab" href="/python/peps/pulse" data-tab-item="i5insights-tab" data-selected-links="repo_graphs repo_contributors dependency_graph dependabot_updates pulse people community /python/peps/pulse" data-pjax="#repo-content-pjax-container" data-turbo-frame="repo-content-turbo-frame" data-analytics-event="{"category":"Underline navbar","action":"Click tab","label":"Insights","target":"UNDERLINE_NAV.TAB"}" data-view-component="true" class="UnderlineNav-item no-wrap js-responsive-underlinenav-item js-selected-navigation-item"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-graph UnderlineNav-octicon d-none d-sm-inline"> <path d="M1.5 1.75V13.5h13.75a.75.75 0 0 1 0 1.5H.75a.75.75 0 0 1-.75-.75V1.75a.75.75 0 0 1 1.5 0Zm14.28 2.53-5.25 5.25a.75.75 0 0 1-1.06 0L7 7.06 4.28 9.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.25-3.25a.75.75 0 0 1 1.06 0L10 7.94l4.72-4.72a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042Z"></path> </svg> <span data-content="Insights">Insights</span> <span id="insights-repo-tab-count" data-pjax-replace="" data-turbo-replace="" title="Not available" data-view-component="true" class="Counter"></span> </a></li> </ul> <div style="visibility:hidden;" data-view-component="true" class="UnderlineNav-actions js-responsive-underlinenav-overflow position-absolute pr-3 pr-md-4 pr-lg-5 right-0"> <action-menu data-select-variant="none" data-view-component="true"> <focus-group direction="vertical" mnemonics retain> <button id="action-menu-bf605783-a58f-4e70-b751-dd047f092193-button" popovertarget="action-menu-bf605783-a58f-4e70-b751-dd047f092193-overlay" aria-controls="action-menu-bf605783-a58f-4e70-b751-dd047f092193-list" aria-haspopup="true" aria-labelledby="tooltip-605125b1-5562-4aa7-b666-6e08ede96c97" type="button" data-view-component="true" class="Button Button--iconOnly Button--secondary Button--medium UnderlineNav-item"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-kebab-horizontal Button-visual"> <path d="M8 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3ZM1.5 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Zm13 0a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path> </svg> </button><tool-tip id="tooltip-605125b1-5562-4aa7-b666-6e08ede96c97" for="action-menu-bf605783-a58f-4e70-b751-dd047f092193-button" popover="manual" data-direction="s" data-type="label" data-view-component="true" class="sr-only position-absolute">Additional navigation options</tool-tip> <anchored-position data-target="action-menu.overlay" id="action-menu-bf605783-a58f-4e70-b751-dd047f092193-overlay" anchor="action-menu-bf605783-a58f-4e70-b751-dd047f092193-button" align="start" side="outside-bottom" anchor-offset="normal" popover="auto" data-view-component="true"> <div data-view-component="true" class="Overlay Overlay--size-auto"> <div data-view-component="true" class="Overlay-body Overlay-body--paddingNone"> <action-list> <div data-view-component="true"> <ul aria-labelledby="action-menu-bf605783-a58f-4e70-b751-dd047f092193-button" id="action-menu-bf605783-a58f-4e70-b751-dd047f092193-list" role="menu" data-view-component="true" class="ActionListWrap--inset ActionListWrap"> <li hidden="hidden" data-menu-item="i0code-tab" data-targets="action-list.items" role="none" data-view-component="true" class="ActionListItem"> <a tabindex="-1" id="item-6bb31856-dc3d-4d78-b837-124920e0e671" href="/python/peps" role="menuitem" data-view-component="true" class="ActionListContent ActionListContent--visual16"> <span class="ActionListItem-visual ActionListItem-visual--leading"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-code"> <path d="m11.28 3.22 4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734L13.94 8l-3.72-3.72a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215Zm-6.56 0a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042L2.06 8l3.72 3.72a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L.47 8.53a.75.75 0 0 1 0-1.06Z"></path> </svg> </span> <span data-view-component="true" class="ActionListItem-label"> Code </span> </a> </li> <li hidden="hidden" data-menu-item="i1issues-tab" data-targets="action-list.items" role="none" data-view-component="true" class="ActionListItem"> <a tabindex="-1" id="item-78122e7e-8266-43a8-bedc-071c1173b0b8" href="/python/peps/issues" role="menuitem" data-view-component="true" class="ActionListContent ActionListContent--visual16"> <span class="ActionListItem-visual ActionListItem-visual--leading"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-issue-opened"> <path d="M8 9.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path><path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Z"></path> </svg> </span> <span data-view-component="true" class="ActionListItem-label"> Issues </span> </a> </li> <li hidden="hidden" data-menu-item="i2pull-requests-tab" data-targets="action-list.items" role="none" data-view-component="true" class="ActionListItem"> <a tabindex="-1" id="item-ef43d74b-ba39-4a95-b99e-a10aa80ae40c" href="/python/peps/pulls" role="menuitem" data-view-component="true" class="ActionListContent ActionListContent--visual16"> <span class="ActionListItem-visual ActionListItem-visual--leading"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-git-pull-request"> <path d="M1.5 3.25a2.25 2.25 0 1 1 3 2.122v5.256a2.251 2.251 0 1 1-1.5 0V5.372A2.25 2.25 0 0 1 1.5 3.25Zm5.677-.177L9.573.677A.25.25 0 0 1 10 .854V2.5h1A2.5 2.5 0 0 1 13.5 5v5.628a2.251 2.251 0 1 1-1.5 0V5a1 1 0 0 0-1-1h-1v1.646a.25.25 0 0 1-.427.177L7.177 3.427a.25.25 0 0 1 0-.354ZM3.75 2.5a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm0 9.5a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm8.25.75a.75.75 0 1 0 1.5 0 .75.75 0 0 0-1.5 0Z"></path> </svg> </span> <span data-view-component="true" class="ActionListItem-label"> Pull requests </span> </a> </li> <li hidden="hidden" data-menu-item="i3actions-tab" data-targets="action-list.items" role="none" data-view-component="true" class="ActionListItem"> <a tabindex="-1" id="item-6aeb9f35-c03c-4d75-97e4-a6c622968300" href="/python/peps/actions" role="menuitem" data-view-component="true" class="ActionListContent ActionListContent--visual16"> <span class="ActionListItem-visual ActionListItem-visual--leading"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-play"> <path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm4.879-2.773 4.264 2.559a.25.25 0 0 1 0 .428l-4.264 2.559A.25.25 0 0 1 6 10.559V5.442a.25.25 0 0 1 .379-.215Z"></path> </svg> </span> <span data-view-component="true" class="ActionListItem-label"> Actions </span> </a> </li> <li hidden="hidden" data-menu-item="i4security-tab" data-targets="action-list.items" role="none" data-view-component="true" class="ActionListItem"> <a tabindex="-1" id="item-8b2e9f93-8f49-4f33-9dd7-2c8beb5e16d4" href="/python/peps/security" role="menuitem" data-view-component="true" class="ActionListContent ActionListContent--visual16"> <span class="ActionListItem-visual ActionListItem-visual--leading"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-shield"> <path d="M7.467.133a1.748 1.748 0 0 1 1.066 0l5.25 1.68A1.75 1.75 0 0 1 15 3.48V7c0 1.566-.32 3.182-1.303 4.682-.983 1.498-2.585 2.813-5.032 3.855a1.697 1.697 0 0 1-1.33 0c-2.447-1.042-4.049-2.357-5.032-3.855C1.32 10.182 1 8.566 1 7V3.48a1.75 1.75 0 0 1 1.217-1.667Zm.61 1.429a.25.25 0 0 0-.153 0l-5.25 1.68a.25.25 0 0 0-.174.238V7c0 1.358.275 2.666 1.057 3.86.784 1.194 2.121 2.34 4.366 3.297a.196.196 0 0 0 .154 0c2.245-.956 3.582-2.104 4.366-3.298C13.225 9.666 13.5 8.36 13.5 7V3.48a.251.251 0 0 0-.174-.237l-5.25-1.68ZM8.75 4.75v3a.75.75 0 0 1-1.5 0v-3a.75.75 0 0 1 1.5 0ZM9 10.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path> </svg> </span> <span data-view-component="true" class="ActionListItem-label"> Security </span> </a> </li> <li hidden="hidden" data-menu-item="i5insights-tab" data-targets="action-list.items" role="none" data-view-component="true" class="ActionListItem"> <a tabindex="-1" id="item-6a4c8449-63ce-484b-ae2b-5b3747dc3f2e" href="/python/peps/pulse" role="menuitem" data-view-component="true" class="ActionListContent ActionListContent--visual16"> <span class="ActionListItem-visual ActionListItem-visual--leading"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-graph"> <path d="M1.5 1.75V13.5h13.75a.75.75 0 0 1 0 1.5H.75a.75.75 0 0 1-.75-.75V1.75a.75.75 0 0 1 1.5 0Zm14.28 2.53-5.25 5.25a.75.75 0 0 1-1.06 0L7 7.06 4.28 9.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.25-3.25a.75.75 0 0 1 1.06 0L10 7.94l4.72-4.72a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042Z"></path> </svg> </span> <span data-view-component="true" class="ActionListItem-label"> Insights </span> </a> </li> </ul> </div></action-list> </div> </div></anchored-position> </focus-group> </action-menu></div> </nav> </div> <turbo-frame id="repo-content-turbo-frame" target="_top" data-turbo-action="advance" class=""> <div id="repo-content-pjax-container" class="repository-content " > <react-app app-name="react-code-view" initial-path="/python/peps/blob/main/peps/pep-0667.rst" style="display: block; min-height: calc(100vh - 64px);" data-attempted-ssr="true" data-ssr="true" data-lazy="false" data-alternate="false" data-data-router-enabled="false" > <script type="application/json" data-target="react-app.embeddedData">{"payload":{"allShortcutsEnabled":false,"fileTree":{"peps":{"items":[{"name":"api","path":"peps/api","contentType":"directory"},{"name":"pep-0001","path":"peps/pep-0001","contentType":"directory"},{"name":"pep-0012","path":"peps/pep-0012","contentType":"directory"},{"name":"pep-0418","path":"peps/pep-0418","contentType":"directory"},{"name":"pep-0426","path":"peps/pep-0426","contentType":"directory"},{"name":"pep-0433","path":"peps/pep-0433","contentType":"directory"},{"name":"pep-0446","path":"peps/pep-0446","contentType":"directory"},{"name":"pep-0465","path":"peps/pep-0465","contentType":"directory"},{"name":"pep-0505","path":"peps/pep-0505","contentType":"directory"},{"name":"pep-0532","path":"peps/pep-0532","contentType":"directory"},{"name":"pep-0605","path":"peps/pep-0605","contentType":"directory"},{"name":"pep-0639","path":"peps/pep-0639","contentType":"directory"},{"name":"pep-0662","path":"peps/pep-0662","contentType":"directory"},{"name":"pep-0739","path":"peps/pep-0739","contentType":"directory"},{"name":"pep-0777","path":"peps/pep-0777","contentType":"directory"},{"name":"conf.py","path":"peps/conf.py","contentType":"file"},{"name":"contents.rst","path":"peps/contents.rst","contentType":"file"},{"name":"pep-0001.rst","path":"peps/pep-0001.rst","contentType":"file"},{"name":"pep-0002.rst","path":"peps/pep-0002.rst","contentType":"file"},{"name":"pep-0003.rst","path":"peps/pep-0003.rst","contentType":"file"},{"name":"pep-0004.rst","path":"peps/pep-0004.rst","contentType":"file"},{"name":"pep-0005.rst","path":"peps/pep-0005.rst","contentType":"file"},{"name":"pep-0006.rst","path":"peps/pep-0006.rst","contentType":"file"},{"name":"pep-0007.rst","path":"peps/pep-0007.rst","contentType":"file"},{"name":"pep-0008.rst","path":"peps/pep-0008.rst","contentType":"file"},{"name":"pep-0009.rst","path":"peps/pep-0009.rst","contentType":"file"},{"name":"pep-0010.rst","path":"peps/pep-0010.rst","contentType":"file"},{"name":"pep-0011.rst","path":"peps/pep-0011.rst","contentType":"file"},{"name":"pep-0012.rst","path":"peps/pep-0012.rst","contentType":"file"},{"name":"pep-0013.rst","path":"peps/pep-0013.rst","contentType":"file"},{"name":"pep-0020.rst","path":"peps/pep-0020.rst","contentType":"file"},{"name":"pep-0042.rst","path":"peps/pep-0042.rst","contentType":"file"},{"name":"pep-0100.rst","path":"peps/pep-0100.rst","contentType":"file"},{"name":"pep-0101.rst","path":"peps/pep-0101.rst","contentType":"file"},{"name":"pep-0102.rst","path":"peps/pep-0102.rst","contentType":"file"},{"name":"pep-0103.rst","path":"peps/pep-0103.rst","contentType":"file"},{"name":"pep-0160.rst","path":"peps/pep-0160.rst","contentType":"file"},{"name":"pep-0200.rst","path":"peps/pep-0200.rst","contentType":"file"},{"name":"pep-0201.rst","path":"peps/pep-0201.rst","contentType":"file"},{"name":"pep-0202.rst","path":"peps/pep-0202.rst","contentType":"file"},{"name":"pep-0203.rst","path":"peps/pep-0203.rst","contentType":"file"},{"name":"pep-0204.rst","path":"peps/pep-0204.rst","contentType":"file"},{"name":"pep-0205.rst","path":"peps/pep-0205.rst","contentType":"file"},{"name":"pep-0206.rst","path":"peps/pep-0206.rst","contentType":"file"},{"name":"pep-0207.rst","path":"peps/pep-0207.rst","contentType":"file"},{"name":"pep-0208.rst","path":"peps/pep-0208.rst","contentType":"file"},{"name":"pep-0209.rst","path":"peps/pep-0209.rst","contentType":"file"},{"name":"pep-0210.rst","path":"peps/pep-0210.rst","contentType":"file"},{"name":"pep-0211.rst","path":"peps/pep-0211.rst","contentType":"file"},{"name":"pep-0212.rst","path":"peps/pep-0212.rst","contentType":"file"},{"name":"pep-0213.rst","path":"peps/pep-0213.rst","contentType":"file"},{"name":"pep-0214.rst","path":"peps/pep-0214.rst","contentType":"file"},{"name":"pep-0215.rst","path":"peps/pep-0215.rst","contentType":"file"},{"name":"pep-0216.rst","path":"peps/pep-0216.rst","contentType":"file"},{"name":"pep-0217.rst","path":"peps/pep-0217.rst","contentType":"file"},{"name":"pep-0218.rst","path":"peps/pep-0218.rst","contentType":"file"},{"name":"pep-0219.rst","path":"peps/pep-0219.rst","contentType":"file"},{"name":"pep-0220.rst","path":"peps/pep-0220.rst","contentType":"file"},{"name":"pep-0221.rst","path":"peps/pep-0221.rst","contentType":"file"},{"name":"pep-0222.rst","path":"peps/pep-0222.rst","contentType":"file"},{"name":"pep-0223.rst","path":"peps/pep-0223.rst","contentType":"file"},{"name":"pep-0224.rst","path":"peps/pep-0224.rst","contentType":"file"},{"name":"pep-0225.rst","path":"peps/pep-0225.rst","contentType":"file"},{"name":"pep-0226.rst","path":"peps/pep-0226.rst","contentType":"file"},{"name":"pep-0227.rst","path":"peps/pep-0227.rst","contentType":"file"},{"name":"pep-0228.rst","path":"peps/pep-0228.rst","contentType":"file"},{"name":"pep-0229.rst","path":"peps/pep-0229.rst","contentType":"file"},{"name":"pep-0230.rst","path":"peps/pep-0230.rst","contentType":"file"},{"name":"pep-0231.rst","path":"peps/pep-0231.rst","contentType":"file"},{"name":"pep-0232.rst","path":"peps/pep-0232.rst","contentType":"file"},{"name":"pep-0233.rst","path":"peps/pep-0233.rst","contentType":"file"},{"name":"pep-0234.rst","path":"peps/pep-0234.rst","contentType":"file"},{"name":"pep-0235.rst","path":"peps/pep-0235.rst","contentType":"file"},{"name":"pep-0236.rst","path":"peps/pep-0236.rst","contentType":"file"},{"name":"pep-0237.rst","path":"peps/pep-0237.rst","contentType":"file"},{"name":"pep-0238.rst","path":"peps/pep-0238.rst","contentType":"file"},{"name":"pep-0239.rst","path":"peps/pep-0239.rst","contentType":"file"},{"name":"pep-0240.rst","path":"peps/pep-0240.rst","contentType":"file"},{"name":"pep-0241.rst","path":"peps/pep-0241.rst","contentType":"file"},{"name":"pep-0242.rst","path":"peps/pep-0242.rst","contentType":"file"},{"name":"pep-0243.rst","path":"peps/pep-0243.rst","contentType":"file"},{"name":"pep-0244.rst","path":"peps/pep-0244.rst","contentType":"file"},{"name":"pep-0245.rst","path":"peps/pep-0245.rst","contentType":"file"},{"name":"pep-0246.rst","path":"peps/pep-0246.rst","contentType":"file"},{"name":"pep-0247.rst","path":"peps/pep-0247.rst","contentType":"file"},{"name":"pep-0248.rst","path":"peps/pep-0248.rst","contentType":"file"},{"name":"pep-0249.rst","path":"peps/pep-0249.rst","contentType":"file"},{"name":"pep-0250.rst","path":"peps/pep-0250.rst","contentType":"file"},{"name":"pep-0251.rst","path":"peps/pep-0251.rst","contentType":"file"},{"name":"pep-0252.rst","path":"peps/pep-0252.rst","contentType":"file"},{"name":"pep-0253.rst","path":"peps/pep-0253.rst","contentType":"file"},{"name":"pep-0254.rst","path":"peps/pep-0254.rst","contentType":"file"},{"name":"pep-0255.rst","path":"peps/pep-0255.rst","contentType":"file"},{"name":"pep-0256.rst","path":"peps/pep-0256.rst","contentType":"file"},{"name":"pep-0257.rst","path":"peps/pep-0257.rst","contentType":"file"},{"name":"pep-0258.rst","path":"peps/pep-0258.rst","contentType":"file"},{"name":"pep-0259.rst","path":"peps/pep-0259.rst","contentType":"file"},{"name":"pep-0260.rst","path":"peps/pep-0260.rst","contentType":"file"},{"name":"pep-0261.rst","path":"peps/pep-0261.rst","contentType":"file"},{"name":"pep-0262.rst","path":"peps/pep-0262.rst","contentType":"file"},{"name":"pep-0263.rst","path":"peps/pep-0263.rst","contentType":"file"},{"name":"pep-0264.rst","path":"peps/pep-0264.rst","contentType":"file"},{"name":"pep-0265.rst","path":"peps/pep-0265.rst","contentType":"file"},{"name":"pep-0266.rst","path":"peps/pep-0266.rst","contentType":"file"},{"name":"pep-0267.rst","path":"peps/pep-0267.rst","contentType":"file"},{"name":"pep-0268.rst","path":"peps/pep-0268.rst","contentType":"file"},{"name":"pep-0269.rst","path":"peps/pep-0269.rst","contentType":"file"},{"name":"pep-0270.rst","path":"peps/pep-0270.rst","contentType":"file"},{"name":"pep-0271.rst","path":"peps/pep-0271.rst","contentType":"file"},{"name":"pep-0272.rst","path":"peps/pep-0272.rst","contentType":"file"},{"name":"pep-0273.rst","path":"peps/pep-0273.rst","contentType":"file"},{"name":"pep-0274.rst","path":"peps/pep-0274.rst","contentType":"file"},{"name":"pep-0275.rst","path":"peps/pep-0275.rst","contentType":"file"},{"name":"pep-0276.rst","path":"peps/pep-0276.rst","contentType":"file"},{"name":"pep-0277.rst","path":"peps/pep-0277.rst","contentType":"file"},{"name":"pep-0278.rst","path":"peps/pep-0278.rst","contentType":"file"},{"name":"pep-0279.rst","path":"peps/pep-0279.rst","contentType":"file"},{"name":"pep-0280.rst","path":"peps/pep-0280.rst","contentType":"file"},{"name":"pep-0281.rst","path":"peps/pep-0281.rst","contentType":"file"},{"name":"pep-0282.rst","path":"peps/pep-0282.rst","contentType":"file"},{"name":"pep-0283.rst","path":"peps/pep-0283.rst","contentType":"file"},{"name":"pep-0284.rst","path":"peps/pep-0284.rst","contentType":"file"},{"name":"pep-0285.rst","path":"peps/pep-0285.rst","contentType":"file"},{"name":"pep-0286.rst","path":"peps/pep-0286.rst","contentType":"file"},{"name":"pep-0287.rst","path":"peps/pep-0287.rst","contentType":"file"},{"name":"pep-0288.rst","path":"peps/pep-0288.rst","contentType":"file"},{"name":"pep-0289.rst","path":"peps/pep-0289.rst","contentType":"file"},{"name":"pep-0290.rst","path":"peps/pep-0290.rst","contentType":"file"},{"name":"pep-0291.rst","path":"peps/pep-0291.rst","contentType":"file"},{"name":"pep-0292.rst","path":"peps/pep-0292.rst","contentType":"file"},{"name":"pep-0293.rst","path":"peps/pep-0293.rst","contentType":"file"},{"name":"pep-0294.rst","path":"peps/pep-0294.rst","contentType":"file"},{"name":"pep-0295.rst","path":"peps/pep-0295.rst","contentType":"file"},{"name":"pep-0296.rst","path":"peps/pep-0296.rst","contentType":"file"},{"name":"pep-0297.rst","path":"peps/pep-0297.rst","contentType":"file"},{"name":"pep-0298.rst","path":"peps/pep-0298.rst","contentType":"file"},{"name":"pep-0299.rst","path":"peps/pep-0299.rst","contentType":"file"},{"name":"pep-0301.rst","path":"peps/pep-0301.rst","contentType":"file"},{"name":"pep-0302.rst","path":"peps/pep-0302.rst","contentType":"file"},{"name":"pep-0303.rst","path":"peps/pep-0303.rst","contentType":"file"},{"name":"pep-0304.rst","path":"peps/pep-0304.rst","contentType":"file"},{"name":"pep-0305.rst","path":"peps/pep-0305.rst","contentType":"file"},{"name":"pep-0306.rst","path":"peps/pep-0306.rst","contentType":"file"},{"name":"pep-0307.rst","path":"peps/pep-0307.rst","contentType":"file"},{"name":"pep-0308.rst","path":"peps/pep-0308.rst","contentType":"file"},{"name":"pep-0309.rst","path":"peps/pep-0309.rst","contentType":"file"},{"name":"pep-0310.rst","path":"peps/pep-0310.rst","contentType":"file"},{"name":"pep-0311.rst","path":"peps/pep-0311.rst","contentType":"file"},{"name":"pep-0312.rst","path":"peps/pep-0312.rst","contentType":"file"},{"name":"pep-0313.rst","path":"peps/pep-0313.rst","contentType":"file"},{"name":"pep-0314.rst","path":"peps/pep-0314.rst","contentType":"file"},{"name":"pep-0315.rst","path":"peps/pep-0315.rst","contentType":"file"},{"name":"pep-0316.rst","path":"peps/pep-0316.rst","contentType":"file"},{"name":"pep-0317.rst","path":"peps/pep-0317.rst","contentType":"file"},{"name":"pep-0318.rst","path":"peps/pep-0318.rst","contentType":"file"},{"name":"pep-0319.rst","path":"peps/pep-0319.rst","contentType":"file"},{"name":"pep-0320.rst","path":"peps/pep-0320.rst","contentType":"file"},{"name":"pep-0321.rst","path":"peps/pep-0321.rst","contentType":"file"},{"name":"pep-0322.rst","path":"peps/pep-0322.rst","contentType":"file"},{"name":"pep-0323.rst","path":"peps/pep-0323.rst","contentType":"file"},{"name":"pep-0324.rst","path":"peps/pep-0324.rst","contentType":"file"},{"name":"pep-0325.rst","path":"peps/pep-0325.rst","contentType":"file"},{"name":"pep-0326.rst","path":"peps/pep-0326.rst","contentType":"file"},{"name":"pep-0327.rst","path":"peps/pep-0327.rst","contentType":"file"},{"name":"pep-0328.rst","path":"peps/pep-0328.rst","contentType":"file"},{"name":"pep-0329.rst","path":"peps/pep-0329.rst","contentType":"file"},{"name":"pep-0330.rst","path":"peps/pep-0330.rst","contentType":"file"},{"name":"pep-0331.rst","path":"peps/pep-0331.rst","contentType":"file"},{"name":"pep-0332.rst","path":"peps/pep-0332.rst","contentType":"file"},{"name":"pep-0333.rst","path":"peps/pep-0333.rst","contentType":"file"},{"name":"pep-0334.rst","path":"peps/pep-0334.rst","contentType":"file"},{"name":"pep-0335.rst","path":"peps/pep-0335.rst","contentType":"file"},{"name":"pep-0336.rst","path":"peps/pep-0336.rst","contentType":"file"},{"name":"pep-0337.rst","path":"peps/pep-0337.rst","contentType":"file"},{"name":"pep-0338.rst","path":"peps/pep-0338.rst","contentType":"file"},{"name":"pep-0339.rst","path":"peps/pep-0339.rst","contentType":"file"},{"name":"pep-0340.rst","path":"peps/pep-0340.rst","contentType":"file"},{"name":"pep-0341.rst","path":"peps/pep-0341.rst","contentType":"file"},{"name":"pep-0342.rst","path":"peps/pep-0342.rst","contentType":"file"},{"name":"pep-0343.rst","path":"peps/pep-0343.rst","contentType":"file"},{"name":"pep-0344.rst","path":"peps/pep-0344.rst","contentType":"file"},{"name":"pep-0345.rst","path":"peps/pep-0345.rst","contentType":"file"},{"name":"pep-0346.rst","path":"peps/pep-0346.rst","contentType":"file"},{"name":"pep-0347.rst","path":"peps/pep-0347.rst","contentType":"file"},{"name":"pep-0348.rst","path":"peps/pep-0348.rst","contentType":"file"},{"name":"pep-0349.rst","path":"peps/pep-0349.rst","contentType":"file"},{"name":"pep-0350.rst","path":"peps/pep-0350.rst","contentType":"file"},{"name":"pep-0351.rst","path":"peps/pep-0351.rst","contentType":"file"},{"name":"pep-0352.rst","path":"peps/pep-0352.rst","contentType":"file"},{"name":"pep-0353.rst","path":"peps/pep-0353.rst","contentType":"file"},{"name":"pep-0354.rst","path":"peps/pep-0354.rst","contentType":"file"},{"name":"pep-0355.rst","path":"peps/pep-0355.rst","contentType":"file"},{"name":"pep-0356.rst","path":"peps/pep-0356.rst","contentType":"file"},{"name":"pep-0357.rst","path":"peps/pep-0357.rst","contentType":"file"},{"name":"pep-0358.rst","path":"peps/pep-0358.rst","contentType":"file"},{"name":"pep-0359.rst","path":"peps/pep-0359.rst","contentType":"file"},{"name":"pep-0360.rst","path":"peps/pep-0360.rst","contentType":"file"},{"name":"pep-0361.rst","path":"peps/pep-0361.rst","contentType":"file"},{"name":"pep-0362.rst","path":"peps/pep-0362.rst","contentType":"file"},{"name":"pep-0363.rst","path":"peps/pep-0363.rst","contentType":"file"},{"name":"pep-0364.rst","path":"peps/pep-0364.rst","contentType":"file"},{"name":"pep-0365.rst","path":"peps/pep-0365.rst","contentType":"file"},{"name":"pep-0366.rst","path":"peps/pep-0366.rst","contentType":"file"},{"name":"pep-0367.rst","path":"peps/pep-0367.rst","contentType":"file"},{"name":"pep-0368.rst","path":"peps/pep-0368.rst","contentType":"file"},{"name":"pep-0369.rst","path":"peps/pep-0369.rst","contentType":"file"},{"name":"pep-0370.rst","path":"peps/pep-0370.rst","contentType":"file"},{"name":"pep-0371.rst","path":"peps/pep-0371.rst","contentType":"file"},{"name":"pep-0372.rst","path":"peps/pep-0372.rst","contentType":"file"},{"name":"pep-0373.rst","path":"peps/pep-0373.rst","contentType":"file"},{"name":"pep-0374.rst","path":"peps/pep-0374.rst","contentType":"file"},{"name":"pep-0375.rst","path":"peps/pep-0375.rst","contentType":"file"},{"name":"pep-0376.rst","path":"peps/pep-0376.rst","contentType":"file"},{"name":"pep-0377.rst","path":"peps/pep-0377.rst","contentType":"file"},{"name":"pep-0378.rst","path":"peps/pep-0378.rst","contentType":"file"},{"name":"pep-0379.rst","path":"peps/pep-0379.rst","contentType":"file"},{"name":"pep-0380.rst","path":"peps/pep-0380.rst","contentType":"file"},{"name":"pep-0381.rst","path":"peps/pep-0381.rst","contentType":"file"},{"name":"pep-0382.rst","path":"peps/pep-0382.rst","contentType":"file"},{"name":"pep-0383.rst","path":"peps/pep-0383.rst","contentType":"file"},{"name":"pep-0384.rst","path":"peps/pep-0384.rst","contentType":"file"},{"name":"pep-0385.rst","path":"peps/pep-0385.rst","contentType":"file"},{"name":"pep-0386.rst","path":"peps/pep-0386.rst","contentType":"file"},{"name":"pep-0387.rst","path":"peps/pep-0387.rst","contentType":"file"},{"name":"pep-0389.rst","path":"peps/pep-0389.rst","contentType":"file"},{"name":"pep-0390.rst","path":"peps/pep-0390.rst","contentType":"file"},{"name":"pep-0391.rst","path":"peps/pep-0391.rst","contentType":"file"},{"name":"pep-0392.rst","path":"peps/pep-0392.rst","contentType":"file"},{"name":"pep-0393.rst","path":"peps/pep-0393.rst","contentType":"file"},{"name":"pep-0394.rst","path":"peps/pep-0394.rst","contentType":"file"},{"name":"pep-0395.rst","path":"peps/pep-0395.rst","contentType":"file"},{"name":"pep-0396.rst","path":"peps/pep-0396.rst","contentType":"file"},{"name":"pep-0397.rst","path":"peps/pep-0397.rst","contentType":"file"},{"name":"pep-0398.rst","path":"peps/pep-0398.rst","contentType":"file"},{"name":"pep-0399.rst","path":"peps/pep-0399.rst","contentType":"file"},{"name":"pep-0400.rst","path":"peps/pep-0400.rst","contentType":"file"},{"name":"pep-0401.rst","path":"peps/pep-0401.rst","contentType":"file"},{"name":"pep-0402.rst","path":"peps/pep-0402.rst","contentType":"file"},{"name":"pep-0403.rst","path":"peps/pep-0403.rst","contentType":"file"},{"name":"pep-0404.rst","path":"peps/pep-0404.rst","contentType":"file"},{"name":"pep-0405.rst","path":"peps/pep-0405.rst","contentType":"file"},{"name":"pep-0406.rst","path":"peps/pep-0406.rst","contentType":"file"},{"name":"pep-0407.rst","path":"peps/pep-0407.rst","contentType":"file"},{"name":"pep-0408.rst","path":"peps/pep-0408.rst","contentType":"file"},{"name":"pep-0409.rst","path":"peps/pep-0409.rst","contentType":"file"},{"name":"pep-0410.rst","path":"peps/pep-0410.rst","contentType":"file"},{"name":"pep-0411.rst","path":"peps/pep-0411.rst","contentType":"file"},{"name":"pep-0412.rst","path":"peps/pep-0412.rst","contentType":"file"},{"name":"pep-0413.rst","path":"peps/pep-0413.rst","contentType":"file"},{"name":"pep-0414.rst","path":"peps/pep-0414.rst","contentType":"file"},{"name":"pep-0415.rst","path":"peps/pep-0415.rst","contentType":"file"},{"name":"pep-0416.rst","path":"peps/pep-0416.rst","contentType":"file"},{"name":"pep-0417.rst","path":"peps/pep-0417.rst","contentType":"file"},{"name":"pep-0418.rst","path":"peps/pep-0418.rst","contentType":"file"},{"name":"pep-0419.rst","path":"peps/pep-0419.rst","contentType":"file"},{"name":"pep-0420.rst","path":"peps/pep-0420.rst","contentType":"file"},{"name":"pep-0421.rst","path":"peps/pep-0421.rst","contentType":"file"},{"name":"pep-0422.rst","path":"peps/pep-0422.rst","contentType":"file"},{"name":"pep-0423.rst","path":"peps/pep-0423.rst","contentType":"file"},{"name":"pep-0424.rst","path":"peps/pep-0424.rst","contentType":"file"},{"name":"pep-0425.rst","path":"peps/pep-0425.rst","contentType":"file"},{"name":"pep-0426.rst","path":"peps/pep-0426.rst","contentType":"file"},{"name":"pep-0427.rst","path":"peps/pep-0427.rst","contentType":"file"},{"name":"pep-0428.rst","path":"peps/pep-0428.rst","contentType":"file"},{"name":"pep-0429.rst","path":"peps/pep-0429.rst","contentType":"file"},{"name":"pep-0430.rst","path":"peps/pep-0430.rst","contentType":"file"},{"name":"pep-0431.rst","path":"peps/pep-0431.rst","contentType":"file"},{"name":"pep-0432.rst","path":"peps/pep-0432.rst","contentType":"file"},{"name":"pep-0433.rst","path":"peps/pep-0433.rst","contentType":"file"},{"name":"pep-0434.rst","path":"peps/pep-0434.rst","contentType":"file"},{"name":"pep-0435.rst","path":"peps/pep-0435.rst","contentType":"file"},{"name":"pep-0436.rst","path":"peps/pep-0436.rst","contentType":"file"},{"name":"pep-0437.rst","path":"peps/pep-0437.rst","contentType":"file"},{"name":"pep-0438.rst","path":"peps/pep-0438.rst","contentType":"file"},{"name":"pep-0439.rst","path":"peps/pep-0439.rst","contentType":"file"},{"name":"pep-0440.rst","path":"peps/pep-0440.rst","contentType":"file"},{"name":"pep-0441.rst","path":"peps/pep-0441.rst","contentType":"file"},{"name":"pep-0442.rst","path":"peps/pep-0442.rst","contentType":"file"},{"name":"pep-0443.rst","path":"peps/pep-0443.rst","contentType":"file"},{"name":"pep-0444.rst","path":"peps/pep-0444.rst","contentType":"file"},{"name":"pep-0445.rst","path":"peps/pep-0445.rst","contentType":"file"},{"name":"pep-0446.rst","path":"peps/pep-0446.rst","contentType":"file"},{"name":"pep-0447.rst","path":"peps/pep-0447.rst","contentType":"file"},{"name":"pep-0448.rst","path":"peps/pep-0448.rst","contentType":"file"},{"name":"pep-0449.rst","path":"peps/pep-0449.rst","contentType":"file"},{"name":"pep-0450.rst","path":"peps/pep-0450.rst","contentType":"file"},{"name":"pep-0451.rst","path":"peps/pep-0451.rst","contentType":"file"},{"name":"pep-0452.rst","path":"peps/pep-0452.rst","contentType":"file"},{"name":"pep-0453.rst","path":"peps/pep-0453.rst","contentType":"file"},{"name":"pep-0454.rst","path":"peps/pep-0454.rst","contentType":"file"},{"name":"pep-0455.rst","path":"peps/pep-0455.rst","contentType":"file"},{"name":"pep-0456.rst","path":"peps/pep-0456.rst","contentType":"file"},{"name":"pep-0457.rst","path":"peps/pep-0457.rst","contentType":"file"},{"name":"pep-0458-1.png","path":"peps/pep-0458-1.png","contentType":"file"},{"name":"pep-0458.rst","path":"peps/pep-0458.rst","contentType":"file"},{"name":"pep-0459.rst","path":"peps/pep-0459.rst","contentType":"file"},{"name":"pep-0460.rst","path":"peps/pep-0460.rst","contentType":"file"},{"name":"pep-0461.rst","path":"peps/pep-0461.rst","contentType":"file"},{"name":"pep-0462.rst","path":"peps/pep-0462.rst","contentType":"file"},{"name":"pep-0463.rst","path":"peps/pep-0463.rst","contentType":"file"},{"name":"pep-0464.rst","path":"peps/pep-0464.rst","contentType":"file"},{"name":"pep-0465.rst","path":"peps/pep-0465.rst","contentType":"file"},{"name":"pep-0466.rst","path":"peps/pep-0466.rst","contentType":"file"},{"name":"pep-0467.rst","path":"peps/pep-0467.rst","contentType":"file"},{"name":"pep-0468.rst","path":"peps/pep-0468.rst","contentType":"file"},{"name":"pep-0469.rst","path":"peps/pep-0469.rst","contentType":"file"},{"name":"pep-0470.rst","path":"peps/pep-0470.rst","contentType":"file"},{"name":"pep-0471.rst","path":"peps/pep-0471.rst","contentType":"file"},{"name":"pep-0472.rst","path":"peps/pep-0472.rst","contentType":"file"},{"name":"pep-0473.rst","path":"peps/pep-0473.rst","contentType":"file"},{"name":"pep-0474.rst","path":"peps/pep-0474.rst","contentType":"file"},{"name":"pep-0475.rst","path":"peps/pep-0475.rst","contentType":"file"},{"name":"pep-0476.rst","path":"peps/pep-0476.rst","contentType":"file"},{"name":"pep-0477.rst","path":"peps/pep-0477.rst","contentType":"file"},{"name":"pep-0478.rst","path":"peps/pep-0478.rst","contentType":"file"},{"name":"pep-0479.rst","path":"peps/pep-0479.rst","contentType":"file"},{"name":"pep-0480-1.png","path":"peps/pep-0480-1.png","contentType":"file"},{"name":"pep-0480.rst","path":"peps/pep-0480.rst","contentType":"file"},{"name":"pep-0481.rst","path":"peps/pep-0481.rst","contentType":"file"},{"name":"pep-0482.rst","path":"peps/pep-0482.rst","contentType":"file"},{"name":"pep-0483.rst","path":"peps/pep-0483.rst","contentType":"file"},{"name":"pep-0484.rst","path":"peps/pep-0484.rst","contentType":"file"},{"name":"pep-0485.rst","path":"peps/pep-0485.rst","contentType":"file"},{"name":"pep-0486.rst","path":"peps/pep-0486.rst","contentType":"file"},{"name":"pep-0487.rst","path":"peps/pep-0487.rst","contentType":"file"},{"name":"pep-0488.rst","path":"peps/pep-0488.rst","contentType":"file"},{"name":"pep-0489.rst","path":"peps/pep-0489.rst","contentType":"file"},{"name":"pep-0490.rst","path":"peps/pep-0490.rst","contentType":"file"},{"name":"pep-0491.rst","path":"peps/pep-0491.rst","contentType":"file"},{"name":"pep-0492.rst","path":"peps/pep-0492.rst","contentType":"file"},{"name":"pep-0493.rst","path":"peps/pep-0493.rst","contentType":"file"},{"name":"pep-0494.rst","path":"peps/pep-0494.rst","contentType":"file"},{"name":"pep-0495-daylightsavings.png","path":"peps/pep-0495-daylightsavings.png","contentType":"file"},{"name":"pep-0495-fold.svg","path":"peps/pep-0495-fold.svg","contentType":"file"},{"name":"pep-0495-gap.svg","path":"peps/pep-0495-gap.svg","contentType":"file"},{"name":"pep-0495.rst","path":"peps/pep-0495.rst","contentType":"file"},{"name":"pep-0496.rst","path":"peps/pep-0496.rst","contentType":"file"},{"name":"pep-0497.rst","path":"peps/pep-0497.rst","contentType":"file"},{"name":"pep-0498.rst","path":"peps/pep-0498.rst","contentType":"file"},{"name":"pep-0499.rst","path":"peps/pep-0499.rst","contentType":"file"},{"name":"pep-0500.rst","path":"peps/pep-0500.rst","contentType":"file"},{"name":"pep-0501.rst","path":"peps/pep-0501.rst","contentType":"file"},{"name":"pep-0502.rst","path":"peps/pep-0502.rst","contentType":"file"},{"name":"pep-0503.rst","path":"peps/pep-0503.rst","contentType":"file"},{"name":"pep-0504.rst","path":"peps/pep-0504.rst","contentType":"file"},{"name":"pep-0505.rst","path":"peps/pep-0505.rst","contentType":"file"},{"name":"pep-0506.rst","path":"peps/pep-0506.rst","contentType":"file"},{"name":"pep-0507.rst","path":"peps/pep-0507.rst","contentType":"file"},{"name":"pep-0508.rst","path":"peps/pep-0508.rst","contentType":"file"},{"name":"pep-0509.rst","path":"peps/pep-0509.rst","contentType":"file"},{"name":"pep-0510.rst","path":"peps/pep-0510.rst","contentType":"file"},{"name":"pep-0511.rst","path":"peps/pep-0511.rst","contentType":"file"},{"name":"pep-0512.rst","path":"peps/pep-0512.rst","contentType":"file"},{"name":"pep-0513.rst","path":"peps/pep-0513.rst","contentType":"file"},{"name":"pep-0514.rst","path":"peps/pep-0514.rst","contentType":"file"},{"name":"pep-0515.rst","path":"peps/pep-0515.rst","contentType":"file"},{"name":"pep-0516.rst","path":"peps/pep-0516.rst","contentType":"file"},{"name":"pep-0517.rst","path":"peps/pep-0517.rst","contentType":"file"},{"name":"pep-0518.rst","path":"peps/pep-0518.rst","contentType":"file"},{"name":"pep-0519.rst","path":"peps/pep-0519.rst","contentType":"file"},{"name":"pep-0520.rst","path":"peps/pep-0520.rst","contentType":"file"},{"name":"pep-0521.rst","path":"peps/pep-0521.rst","contentType":"file"},{"name":"pep-0522.rst","path":"peps/pep-0522.rst","contentType":"file"},{"name":"pep-0523.rst","path":"peps/pep-0523.rst","contentType":"file"},{"name":"pep-0524.rst","path":"peps/pep-0524.rst","contentType":"file"},{"name":"pep-0525-1.png","path":"peps/pep-0525-1.png","contentType":"file"},{"name":"pep-0525.rst","path":"peps/pep-0525.rst","contentType":"file"},{"name":"pep-0526.rst","path":"peps/pep-0526.rst","contentType":"file"},{"name":"pep-0527.rst","path":"peps/pep-0527.rst","contentType":"file"},{"name":"pep-0528.rst","path":"peps/pep-0528.rst","contentType":"file"},{"name":"pep-0529.rst","path":"peps/pep-0529.rst","contentType":"file"},{"name":"pep-0530.rst","path":"peps/pep-0530.rst","contentType":"file"},{"name":"pep-0531.rst","path":"peps/pep-0531.rst","contentType":"file"},{"name":"pep-0532.rst","path":"peps/pep-0532.rst","contentType":"file"},{"name":"pep-0533.rst","path":"peps/pep-0533.rst","contentType":"file"},{"name":"pep-0534.rst","path":"peps/pep-0534.rst","contentType":"file"},{"name":"pep-0535.rst","path":"peps/pep-0535.rst","contentType":"file"},{"name":"pep-0536.rst","path":"peps/pep-0536.rst","contentType":"file"},{"name":"pep-0537.rst","path":"peps/pep-0537.rst","contentType":"file"},{"name":"pep-0538.rst","path":"peps/pep-0538.rst","contentType":"file"},{"name":"pep-0539.rst","path":"peps/pep-0539.rst","contentType":"file"},{"name":"pep-0540.rst","path":"peps/pep-0540.rst","contentType":"file"},{"name":"pep-0541.rst","path":"peps/pep-0541.rst","contentType":"file"},{"name":"pep-0542.rst","path":"peps/pep-0542.rst","contentType":"file"},{"name":"pep-0543.rst","path":"peps/pep-0543.rst","contentType":"file"},{"name":"pep-0544.rst","path":"peps/pep-0544.rst","contentType":"file"},{"name":"pep-0545.rst","path":"peps/pep-0545.rst","contentType":"file"},{"name":"pep-0546.rst","path":"peps/pep-0546.rst","contentType":"file"},{"name":"pep-0547.rst","path":"peps/pep-0547.rst","contentType":"file"},{"name":"pep-0548.rst","path":"peps/pep-0548.rst","contentType":"file"},{"name":"pep-0549.rst","path":"peps/pep-0549.rst","contentType":"file"},{"name":"pep-0550-hamt_vs_dict-v2.png","path":"peps/pep-0550-hamt_vs_dict-v2.png","contentType":"file"},{"name":"pep-0550-hamt_vs_dict.png","path":"peps/pep-0550-hamt_vs_dict.png","contentType":"file"},{"name":"pep-0550-lookup_hamt.png","path":"peps/pep-0550-lookup_hamt.png","contentType":"file"},{"name":"pep-0550.rst","path":"peps/pep-0550.rst","contentType":"file"},{"name":"pep-0551.rst","path":"peps/pep-0551.rst","contentType":"file"},{"name":"pep-0552.rst","path":"peps/pep-0552.rst","contentType":"file"},{"name":"pep-0553.rst","path":"peps/pep-0553.rst","contentType":"file"},{"name":"pep-0554.rst","path":"peps/pep-0554.rst","contentType":"file"},{"name":"pep-0555.rst","path":"peps/pep-0555.rst","contentType":"file"},{"name":"pep-0556.rst","path":"peps/pep-0556.rst","contentType":"file"},{"name":"pep-0557.rst","path":"peps/pep-0557.rst","contentType":"file"},{"name":"pep-0558.rst","path":"peps/pep-0558.rst","contentType":"file"},{"name":"pep-0559.rst","path":"peps/pep-0559.rst","contentType":"file"},{"name":"pep-0560.rst","path":"peps/pep-0560.rst","contentType":"file"},{"name":"pep-0561.rst","path":"peps/pep-0561.rst","contentType":"file"},{"name":"pep-0562.rst","path":"peps/pep-0562.rst","contentType":"file"},{"name":"pep-0563.rst","path":"peps/pep-0563.rst","contentType":"file"},{"name":"pep-0564.rst","path":"peps/pep-0564.rst","contentType":"file"},{"name":"pep-0565.rst","path":"peps/pep-0565.rst","contentType":"file"},{"name":"pep-0566.rst","path":"peps/pep-0566.rst","contentType":"file"},{"name":"pep-0567.rst","path":"peps/pep-0567.rst","contentType":"file"},{"name":"pep-0568.rst","path":"peps/pep-0568.rst","contentType":"file"},{"name":"pep-0569.rst","path":"peps/pep-0569.rst","contentType":"file"},{"name":"pep-0570.rst","path":"peps/pep-0570.rst","contentType":"file"},{"name":"pep-0571.rst","path":"peps/pep-0571.rst","contentType":"file"},{"name":"pep-0572.rst","path":"peps/pep-0572.rst","contentType":"file"},{"name":"pep-0573.rst","path":"peps/pep-0573.rst","contentType":"file"},{"name":"pep-0574.rst","path":"peps/pep-0574.rst","contentType":"file"},{"name":"pep-0575.rst","path":"peps/pep-0575.rst","contentType":"file"},{"name":"pep-0576.rst","path":"peps/pep-0576.rst","contentType":"file"},{"name":"pep-0577.rst","path":"peps/pep-0577.rst","contentType":"file"},{"name":"pep-0578.rst","path":"peps/pep-0578.rst","contentType":"file"},{"name":"pep-0579.rst","path":"peps/pep-0579.rst","contentType":"file"},{"name":"pep-0580.rst","path":"peps/pep-0580.rst","contentType":"file"},{"name":"pep-0581.rst","path":"peps/pep-0581.rst","contentType":"file"},{"name":"pep-0582.rst","path":"peps/pep-0582.rst","contentType":"file"},{"name":"pep-0583.rst","path":"peps/pep-0583.rst","contentType":"file"},{"name":"pep-0584.rst","path":"peps/pep-0584.rst","contentType":"file"},{"name":"pep-0585.rst","path":"peps/pep-0585.rst","contentType":"file"},{"name":"pep-0586.rst","path":"peps/pep-0586.rst","contentType":"file"},{"name":"pep-0587.rst","path":"peps/pep-0587.rst","contentType":"file"},{"name":"pep-0588.rst","path":"peps/pep-0588.rst","contentType":"file"},{"name":"pep-0589.rst","path":"peps/pep-0589.rst","contentType":"file"},{"name":"pep-0590.rst","path":"peps/pep-0590.rst","contentType":"file"},{"name":"pep-0591.rst","path":"peps/pep-0591.rst","contentType":"file"},{"name":"pep-0592.rst","path":"peps/pep-0592.rst","contentType":"file"},{"name":"pep-0593.rst","path":"peps/pep-0593.rst","contentType":"file"},{"name":"pep-0594.rst","path":"peps/pep-0594.rst","contentType":"file"},{"name":"pep-0595.rst","path":"peps/pep-0595.rst","contentType":"file"},{"name":"pep-0596.rst","path":"peps/pep-0596.rst","contentType":"file"},{"name":"pep-0597.rst","path":"peps/pep-0597.rst","contentType":"file"},{"name":"pep-0598.rst","path":"peps/pep-0598.rst","contentType":"file"},{"name":"pep-0599.rst","path":"peps/pep-0599.rst","contentType":"file"},{"name":"pep-0600.rst","path":"peps/pep-0600.rst","contentType":"file"},{"name":"pep-0601.rst","path":"peps/pep-0601.rst","contentType":"file"},{"name":"pep-0602-example-release-calendar.png","path":"peps/pep-0602-example-release-calendar.png","contentType":"file"},{"name":"pep-0602-example-release-calendar.pptx","path":"peps/pep-0602-example-release-calendar.pptx","contentType":"file"},{"name":"pep-0602-overlapping-support-matrix.png","path":"peps/pep-0602-overlapping-support-matrix.png","contentType":"file"},{"name":"pep-0602-overlapping-support-matrix.pptx","path":"peps/pep-0602-overlapping-support-matrix.pptx","contentType":"file"},{"name":"pep-0602.rst","path":"peps/pep-0602.rst","contentType":"file"},{"name":"pep-0603-hamt_vs_dict.png","path":"peps/pep-0603-hamt_vs_dict.png","contentType":"file"},{"name":"pep-0603-lookup_hamt.png","path":"peps/pep-0603-lookup_hamt.png","contentType":"file"},{"name":"pep-0603.rst","path":"peps/pep-0603.rst","contentType":"file"},{"name":"pep-0604.rst","path":"peps/pep-0604.rst","contentType":"file"},{"name":"pep-0605-example-release-calendar.png","path":"peps/pep-0605-example-release-calendar.png","contentType":"file"},{"name":"pep-0605-overlapping-support-matrix.png","path":"peps/pep-0605-overlapping-support-matrix.png","contentType":"file"},{"name":"pep-0605.rst","path":"peps/pep-0605.rst","contentType":"file"},{"name":"pep-0606.rst","path":"peps/pep-0606.rst","contentType":"file"},{"name":"pep-0607.rst","path":"peps/pep-0607.rst","contentType":"file"},{"name":"pep-0608.rst","path":"peps/pep-0608.rst","contentType":"file"},{"name":"pep-0609.rst","path":"peps/pep-0609.rst","contentType":"file"},{"name":"pep-0610.rst","path":"peps/pep-0610.rst","contentType":"file"},{"name":"pep-0611.rst","path":"peps/pep-0611.rst","contentType":"file"},{"name":"pep-0612.rst","path":"peps/pep-0612.rst","contentType":"file"},{"name":"pep-0613.rst","path":"peps/pep-0613.rst","contentType":"file"},{"name":"pep-0614.rst","path":"peps/pep-0614.rst","contentType":"file"},{"name":"pep-0615.rst","path":"peps/pep-0615.rst","contentType":"file"},{"name":"pep-0616.rst","path":"peps/pep-0616.rst","contentType":"file"},{"name":"pep-0617.rst","path":"peps/pep-0617.rst","contentType":"file"},{"name":"pep-0618.rst","path":"peps/pep-0618.rst","contentType":"file"},{"name":"pep-0619.rst","path":"peps/pep-0619.rst","contentType":"file"},{"name":"pep-0620.rst","path":"peps/pep-0620.rst","contentType":"file"},{"name":"pep-0621.rst","path":"peps/pep-0621.rst","contentType":"file"},{"name":"pep-0622.rst","path":"peps/pep-0622.rst","contentType":"file"},{"name":"pep-0623.rst","path":"peps/pep-0623.rst","contentType":"file"},{"name":"pep-0624.rst","path":"peps/pep-0624.rst","contentType":"file"},{"name":"pep-0625.rst","path":"peps/pep-0625.rst","contentType":"file"},{"name":"pep-0626.rst","path":"peps/pep-0626.rst","contentType":"file"},{"name":"pep-0627.rst","path":"peps/pep-0627.rst","contentType":"file"},{"name":"pep-0628.rst","path":"peps/pep-0628.rst","contentType":"file"},{"name":"pep-0629.rst","path":"peps/pep-0629.rst","contentType":"file"},{"name":"pep-0630.rst","path":"peps/pep-0630.rst","contentType":"file"},{"name":"pep-0631.rst","path":"peps/pep-0631.rst","contentType":"file"},{"name":"pep-0632.rst","path":"peps/pep-0632.rst","contentType":"file"},{"name":"pep-0633.rst","path":"peps/pep-0633.rst","contentType":"file"},{"name":"pep-0634.rst","path":"peps/pep-0634.rst","contentType":"file"},{"name":"pep-0635.rst","path":"peps/pep-0635.rst","contentType":"file"},{"name":"pep-0636.rst","path":"peps/pep-0636.rst","contentType":"file"},{"name":"pep-0637.rst","path":"peps/pep-0637.rst","contentType":"file"},{"name":"pep-0638.rst","path":"peps/pep-0638.rst","contentType":"file"},{"name":"pep-0639.rst","path":"peps/pep-0639.rst","contentType":"file"},{"name":"pep-0640.rst","path":"peps/pep-0640.rst","contentType":"file"},{"name":"pep-0641.rst","path":"peps/pep-0641.rst","contentType":"file"},{"name":"pep-0642.rst","path":"peps/pep-0642.rst","contentType":"file"},{"name":"pep-0643.rst","path":"peps/pep-0643.rst","contentType":"file"},{"name":"pep-0644.rst","path":"peps/pep-0644.rst","contentType":"file"},{"name":"pep-0645.rst","path":"peps/pep-0645.rst","contentType":"file"},{"name":"pep-0646.rst","path":"peps/pep-0646.rst","contentType":"file"},{"name":"pep-0647.rst","path":"peps/pep-0647.rst","contentType":"file"},{"name":"pep-0648.rst","path":"peps/pep-0648.rst","contentType":"file"},{"name":"pep-0649.rst","path":"peps/pep-0649.rst","contentType":"file"},{"name":"pep-0650.rst","path":"peps/pep-0650.rst","contentType":"file"},{"name":"pep-0651.rst","path":"peps/pep-0651.rst","contentType":"file"},{"name":"pep-0652.rst","path":"peps/pep-0652.rst","contentType":"file"},{"name":"pep-0653.rst","path":"peps/pep-0653.rst","contentType":"file"},{"name":"pep-0654.rst","path":"peps/pep-0654.rst","contentType":"file"},{"name":"pep-0655.rst","path":"peps/pep-0655.rst","contentType":"file"},{"name":"pep-0656.rst","path":"peps/pep-0656.rst","contentType":"file"},{"name":"pep-0657.rst","path":"peps/pep-0657.rst","contentType":"file"},{"name":"pep-0658.rst","path":"peps/pep-0658.rst","contentType":"file"},{"name":"pep-0659.rst","path":"peps/pep-0659.rst","contentType":"file"},{"name":"pep-0660.rst","path":"peps/pep-0660.rst","contentType":"file"},{"name":"pep-0661.rst","path":"peps/pep-0661.rst","contentType":"file"},{"name":"pep-0662.rst","path":"peps/pep-0662.rst","contentType":"file"},{"name":"pep-0663.rst","path":"peps/pep-0663.rst","contentType":"file"},{"name":"pep-0664.rst","path":"peps/pep-0664.rst","contentType":"file"},{"name":"pep-0665.rst","path":"peps/pep-0665.rst","contentType":"file"},{"name":"pep-0666.rst","path":"peps/pep-0666.rst","contentType":"file"},{"name":"pep-0667.rst","path":"peps/pep-0667.rst","contentType":"file"},{"name":"pep-0668.rst","path":"peps/pep-0668.rst","contentType":"file"},{"name":"pep-0669.rst","path":"peps/pep-0669.rst","contentType":"file"},{"name":"pep-0670.rst","path":"peps/pep-0670.rst","contentType":"file"},{"name":"pep-0671.rst","path":"peps/pep-0671.rst","contentType":"file"},{"name":"pep-0672.rst","path":"peps/pep-0672.rst","contentType":"file"},{"name":"pep-0673.rst","path":"peps/pep-0673.rst","contentType":"file"},{"name":"pep-0674.rst","path":"peps/pep-0674.rst","contentType":"file"},{"name":"pep-0675.rst","path":"peps/pep-0675.rst","contentType":"file"},{"name":"pep-0676.rst","path":"peps/pep-0676.rst","contentType":"file"},{"name":"pep-0677.rst","path":"peps/pep-0677.rst","contentType":"file"},{"name":"pep-0678.rst","path":"peps/pep-0678.rst","contentType":"file"},{"name":"pep-0679.rst","path":"peps/pep-0679.rst","contentType":"file"},{"name":"pep-0680.rst","path":"peps/pep-0680.rst","contentType":"file"},{"name":"pep-0681.rst","path":"peps/pep-0681.rst","contentType":"file"},{"name":"pep-0682.rst","path":"peps/pep-0682.rst","contentType":"file"},{"name":"pep-0683.rst","path":"peps/pep-0683.rst","contentType":"file"},{"name":"pep-0684.rst","path":"peps/pep-0684.rst","contentType":"file"},{"name":"pep-0685.rst","path":"peps/pep-0685.rst","contentType":"file"},{"name":"pep-0686.rst","path":"peps/pep-0686.rst","contentType":"file"},{"name":"pep-0687.rst","path":"peps/pep-0687.rst","contentType":"file"},{"name":"pep-0688.rst","path":"peps/pep-0688.rst","contentType":"file"},{"name":"pep-0689.rst","path":"peps/pep-0689.rst","contentType":"file"},{"name":"pep-0690.rst","path":"peps/pep-0690.rst","contentType":"file"},{"name":"pep-0691.rst","path":"peps/pep-0691.rst","contentType":"file"},{"name":"pep-0692.rst","path":"peps/pep-0692.rst","contentType":"file"},{"name":"pep-0693.rst","path":"peps/pep-0693.rst","contentType":"file"},{"name":"pep-0694.rst","path":"peps/pep-0694.rst","contentType":"file"},{"name":"pep-0695.rst","path":"peps/pep-0695.rst","contentType":"file"},{"name":"pep-0696.rst","path":"peps/pep-0696.rst","contentType":"file"},{"name":"pep-0697.rst","path":"peps/pep-0697.rst","contentType":"file"},{"name":"pep-0698.rst","path":"peps/pep-0698.rst","contentType":"file"},{"name":"pep-0699.rst","path":"peps/pep-0699.rst","contentType":"file"},{"name":"pep-0700.rst","path":"peps/pep-0700.rst","contentType":"file"},{"name":"pep-0701.rst","path":"peps/pep-0701.rst","contentType":"file"},{"name":"pep-0702.rst","path":"peps/pep-0702.rst","contentType":"file"},{"name":"pep-0703.rst","path":"peps/pep-0703.rst","contentType":"file"},{"name":"pep-0704.rst","path":"peps/pep-0704.rst","contentType":"file"},{"name":"pep-0705.rst","path":"peps/pep-0705.rst","contentType":"file"},{"name":"pep-0706.rst","path":"peps/pep-0706.rst","contentType":"file"},{"name":"pep-0707.rst","path":"peps/pep-0707.rst","contentType":"file"},{"name":"pep-0708.rst","path":"peps/pep-0708.rst","contentType":"file"},{"name":"pep-0709.rst","path":"peps/pep-0709.rst","contentType":"file"},{"name":"pep-0710.rst","path":"peps/pep-0710.rst","contentType":"file"},{"name":"pep-0711.rst","path":"peps/pep-0711.rst","contentType":"file"},{"name":"pep-0712.rst","path":"peps/pep-0712.rst","contentType":"file"},{"name":"pep-0713.rst","path":"peps/pep-0713.rst","contentType":"file"},{"name":"pep-0714.rst","path":"peps/pep-0714.rst","contentType":"file"},{"name":"pep-0715.rst","path":"peps/pep-0715.rst","contentType":"file"},{"name":"pep-0718.rst","path":"peps/pep-0718.rst","contentType":"file"},{"name":"pep-0719.rst","path":"peps/pep-0719.rst","contentType":"file"},{"name":"pep-0720.rst","path":"peps/pep-0720.rst","contentType":"file"},{"name":"pep-0721.rst","path":"peps/pep-0721.rst","contentType":"file"},{"name":"pep-0722.rst","path":"peps/pep-0722.rst","contentType":"file"},{"name":"pep-0723.rst","path":"peps/pep-0723.rst","contentType":"file"},{"name":"pep-0724.rst","path":"peps/pep-0724.rst","contentType":"file"},{"name":"pep-0725.rst","path":"peps/pep-0725.rst","contentType":"file"},{"name":"pep-0726.rst","path":"peps/pep-0726.rst","contentType":"file"},{"name":"pep-0727.rst","path":"peps/pep-0727.rst","contentType":"file"},{"name":"pep-0728.rst","path":"peps/pep-0728.rst","contentType":"file"},{"name":"pep-0729.rst","path":"peps/pep-0729.rst","contentType":"file"},{"name":"pep-0730.rst","path":"peps/pep-0730.rst","contentType":"file"},{"name":"pep-0731.rst","path":"peps/pep-0731.rst","contentType":"file"},{"name":"pep-0732-concentric.drawio.svg","path":"peps/pep-0732-concentric.drawio.svg","contentType":"file"},{"name":"pep-0732.rst","path":"peps/pep-0732.rst","contentType":"file"},{"name":"pep-0733.rst","path":"peps/pep-0733.rst","contentType":"file"},{"name":"pep-0734.rst","path":"peps/pep-0734.rst","contentType":"file"},{"name":"pep-0735.rst","path":"peps/pep-0735.rst","contentType":"file"},{"name":"pep-0736.rst","path":"peps/pep-0736.rst","contentType":"file"},{"name":"pep-0737.rst","path":"peps/pep-0737.rst","contentType":"file"},{"name":"pep-0738.rst","path":"peps/pep-0738.rst","contentType":"file"},{"name":"pep-0739.rst","path":"peps/pep-0739.rst","contentType":"file"},{"name":"pep-0740.rst","path":"peps/pep-0740.rst","contentType":"file"},{"name":"pep-0741.rst","path":"peps/pep-0741.rst","contentType":"file"},{"name":"pep-0742.rst","path":"peps/pep-0742.rst","contentType":"file"},{"name":"pep-0743.rst","path":"peps/pep-0743.rst","contentType":"file"},{"name":"pep-0744.rst","path":"peps/pep-0744.rst","contentType":"file"},{"name":"pep-0745.rst","path":"peps/pep-0745.rst","contentType":"file"},{"name":"pep-0746.rst","path":"peps/pep-0746.rst","contentType":"file"},{"name":"pep-0747.rst","path":"peps/pep-0747.rst","contentType":"file"},{"name":"pep-0748.rst","path":"peps/pep-0748.rst","contentType":"file"},{"name":"pep-0749.rst","path":"peps/pep-0749.rst","contentType":"file"},{"name":"pep-0750.rst","path":"peps/pep-0750.rst","contentType":"file"},{"name":"pep-0751.rst","path":"peps/pep-0751.rst","contentType":"file"},{"name":"pep-0752.rst","path":"peps/pep-0752.rst","contentType":"file"},{"name":"pep-0753.rst","path":"peps/pep-0753.rst","contentType":"file"},{"name":"pep-0754.rst","path":"peps/pep-0754.rst","contentType":"file"},{"name":"pep-0755.rst","path":"peps/pep-0755.rst","contentType":"file"},{"name":"pep-0756.rst","path":"peps/pep-0756.rst","contentType":"file"},{"name":"pep-0757.rst","path":"peps/pep-0757.rst","contentType":"file"},{"name":"pep-0758.rst","path":"peps/pep-0758.rst","contentType":"file"},{"name":"pep-0759.rst","path":"peps/pep-0759.rst","contentType":"file"},{"name":"pep-0760.rst","path":"peps/pep-0760.rst","contentType":"file"},{"name":"pep-0761.rst","path":"peps/pep-0761.rst","contentType":"file"},{"name":"pep-0762.rst","path":"peps/pep-0762.rst","contentType":"file"},{"name":"pep-0763.rst","path":"peps/pep-0763.rst","contentType":"file"},{"name":"pep-0764.rst","path":"peps/pep-0764.rst","contentType":"file"},{"name":"pep-0765.rst","path":"peps/pep-0765.rst","contentType":"file"},{"name":"pep-0766.rst","path":"peps/pep-0766.rst","contentType":"file"},{"name":"pep-0767.rst","path":"peps/pep-0767.rst","contentType":"file"},{"name":"pep-0768.rst","path":"peps/pep-0768.rst","contentType":"file"},{"name":"pep-0769.rst","path":"peps/pep-0769.rst","contentType":"file"},{"name":"pep-0770.rst","path":"peps/pep-0770.rst","contentType":"file"},{"name":"pep-0771.rst","path":"peps/pep-0771.rst","contentType":"file"},{"name":"pep-0772.rst","path":"peps/pep-0772.rst","contentType":"file"},{"name":"pep-0773.rst","path":"peps/pep-0773.rst","contentType":"file"},{"name":"pep-0774.rst","path":"peps/pep-0774.rst","contentType":"file"},{"name":"pep-0777.rst","path":"peps/pep-0777.rst","contentType":"file"},{"name":"pep-0789.rst","path":"peps/pep-0789.rst","contentType":"file"},{"name":"pep-0801.rst","path":"peps/pep-0801.rst","contentType":"file"},{"name":"pep-2026.rst","path":"peps/pep-2026.rst","contentType":"file"},{"name":"pep-3000.rst","path":"peps/pep-3000.rst","contentType":"file"},{"name":"pep-3001.rst","path":"peps/pep-3001.rst","contentType":"file"},{"name":"pep-3002.rst","path":"peps/pep-3002.rst","contentType":"file"},{"name":"pep-3003.rst","path":"peps/pep-3003.rst","contentType":"file"},{"name":"pep-3099.rst","path":"peps/pep-3099.rst","contentType":"file"},{"name":"pep-3100.rst","path":"peps/pep-3100.rst","contentType":"file"},{"name":"pep-3101.rst","path":"peps/pep-3101.rst","contentType":"file"},{"name":"pep-3102.rst","path":"peps/pep-3102.rst","contentType":"file"},{"name":"pep-3103.rst","path":"peps/pep-3103.rst","contentType":"file"},{"name":"pep-3104.rst","path":"peps/pep-3104.rst","contentType":"file"},{"name":"pep-3105.rst","path":"peps/pep-3105.rst","contentType":"file"},{"name":"pep-3106.rst","path":"peps/pep-3106.rst","contentType":"file"},{"name":"pep-3107.rst","path":"peps/pep-3107.rst","contentType":"file"},{"name":"pep-3108.rst","path":"peps/pep-3108.rst","contentType":"file"},{"name":"pep-3109.rst","path":"peps/pep-3109.rst","contentType":"file"},{"name":"pep-3110.rst","path":"peps/pep-3110.rst","contentType":"file"},{"name":"pep-3111.rst","path":"peps/pep-3111.rst","contentType":"file"},{"name":"pep-3112.rst","path":"peps/pep-3112.rst","contentType":"file"},{"name":"pep-3113.rst","path":"peps/pep-3113.rst","contentType":"file"},{"name":"pep-3114.rst","path":"peps/pep-3114.rst","contentType":"file"},{"name":"pep-3115.rst","path":"peps/pep-3115.rst","contentType":"file"},{"name":"pep-3116.rst","path":"peps/pep-3116.rst","contentType":"file"},{"name":"pep-3117.rst","path":"peps/pep-3117.rst","contentType":"file"},{"name":"pep-3118.rst","path":"peps/pep-3118.rst","contentType":"file"},{"name":"pep-3119.rst","path":"peps/pep-3119.rst","contentType":"file"},{"name":"pep-3120.rst","path":"peps/pep-3120.rst","contentType":"file"},{"name":"pep-3121.rst","path":"peps/pep-3121.rst","contentType":"file"},{"name":"pep-3122.rst","path":"peps/pep-3122.rst","contentType":"file"},{"name":"pep-3123.rst","path":"peps/pep-3123.rst","contentType":"file"},{"name":"pep-3124.rst","path":"peps/pep-3124.rst","contentType":"file"},{"name":"pep-3125.rst","path":"peps/pep-3125.rst","contentType":"file"},{"name":"pep-3126.rst","path":"peps/pep-3126.rst","contentType":"file"},{"name":"pep-3127.rst","path":"peps/pep-3127.rst","contentType":"file"},{"name":"pep-3128.rst","path":"peps/pep-3128.rst","contentType":"file"},{"name":"pep-3129.rst","path":"peps/pep-3129.rst","contentType":"file"},{"name":"pep-3130.rst","path":"peps/pep-3130.rst","contentType":"file"},{"name":"pep-3131.rst","path":"peps/pep-3131.rst","contentType":"file"},{"name":"pep-3132.rst","path":"peps/pep-3132.rst","contentType":"file"},{"name":"pep-3133.rst","path":"peps/pep-3133.rst","contentType":"file"},{"name":"pep-3134.rst","path":"peps/pep-3134.rst","contentType":"file"},{"name":"pep-3135.rst","path":"peps/pep-3135.rst","contentType":"file"},{"name":"pep-3136.rst","path":"peps/pep-3136.rst","contentType":"file"},{"name":"pep-3137.rst","path":"peps/pep-3137.rst","contentType":"file"},{"name":"pep-3138.rst","path":"peps/pep-3138.rst","contentType":"file"},{"name":"pep-3139.rst","path":"peps/pep-3139.rst","contentType":"file"},{"name":"pep-3140.rst","path":"peps/pep-3140.rst","contentType":"file"},{"name":"pep-3141.rst","path":"peps/pep-3141.rst","contentType":"file"},{"name":"pep-3142.rst","path":"peps/pep-3142.rst","contentType":"file"},{"name":"pep-3143.rst","path":"peps/pep-3143.rst","contentType":"file"},{"name":"pep-3144.rst","path":"peps/pep-3144.rst","contentType":"file"},{"name":"pep-3145.rst","path":"peps/pep-3145.rst","contentType":"file"},{"name":"pep-3146.rst","path":"peps/pep-3146.rst","contentType":"file"},{"name":"pep-3147-1.dia","path":"peps/pep-3147-1.dia","contentType":"file"},{"name":"pep-3147-1.png","path":"peps/pep-3147-1.png","contentType":"file"},{"name":"pep-3147.rst","path":"peps/pep-3147.rst","contentType":"file"},{"name":"pep-3148.rst","path":"peps/pep-3148.rst","contentType":"file"},{"name":"pep-3149.rst","path":"peps/pep-3149.rst","contentType":"file"},{"name":"pep-3150.rst","path":"peps/pep-3150.rst","contentType":"file"},{"name":"pep-3151.rst","path":"peps/pep-3151.rst","contentType":"file"},{"name":"pep-3152.rst","path":"peps/pep-3152.rst","contentType":"file"},{"name":"pep-3153.rst","path":"peps/pep-3153.rst","contentType":"file"},{"name":"pep-3154.rst","path":"peps/pep-3154.rst","contentType":"file"},{"name":"pep-3155.rst","path":"peps/pep-3155.rst","contentType":"file"},{"name":"pep-3156.rst","path":"peps/pep-3156.rst","contentType":"file"},{"name":"pep-3333.rst","path":"peps/pep-3333.rst","contentType":"file"},{"name":"pep-789-example-no-yield.png","path":"peps/pep-789-example-no-yield.png","contentType":"file"},{"name":"pep-789-example-yield-allowed.png","path":"peps/pep-789-example-yield-allowed.png","contentType":"file"},{"name":"pep-789-example-yield-errors.png","path":"peps/pep-789-example-yield-errors.png","contentType":"file"},{"name":"pep-8000.rst","path":"peps/pep-8000.rst","contentType":"file"},{"name":"pep-8001.rst","path":"peps/pep-8001.rst","contentType":"file"},{"name":"pep-8002.rst","path":"peps/pep-8002.rst","contentType":"file"},{"name":"pep-8010.rst","path":"peps/pep-8010.rst","contentType":"file"},{"name":"pep-8011.rst","path":"peps/pep-8011.rst","contentType":"file"},{"name":"pep-8012.rst","path":"peps/pep-8012.rst","contentType":"file"},{"name":"pep-8013.rst","path":"peps/pep-8013.rst","contentType":"file"},{"name":"pep-8014.rst","path":"peps/pep-8014.rst","contentType":"file"},{"name":"pep-8015.rst","path":"peps/pep-8015.rst","contentType":"file"},{"name":"pep-8016.rst","path":"peps/pep-8016.rst","contentType":"file"},{"name":"pep-8100.rst","path":"peps/pep-8100.rst","contentType":"file"},{"name":"pep-8101.rst","path":"peps/pep-8101.rst","contentType":"file"},{"name":"pep-8102.rst","path":"peps/pep-8102.rst","contentType":"file"},{"name":"pep-8103.rst","path":"peps/pep-8103.rst","contentType":"file"},{"name":"pep-8104.rst","path":"peps/pep-8104.rst","contentType":"file"},{"name":"pep-8105.rst","path":"peps/pep-8105.rst","contentType":"file"},{"name":"pep-8106.rst","path":"peps/pep-8106.rst","contentType":"file"}],"totalCount":715},"":{"items":[{"name":".codespell","path":".codespell","contentType":"directory"},{"name":".github","path":".github","contentType":"directory"},{"name":"docs","path":"docs","contentType":"directory"},{"name":"infra","path":"infra","contentType":"directory"},{"name":"pep_sphinx_extensions","path":"pep_sphinx_extensions","contentType":"directory"},{"name":"peps","path":"peps","contentType":"directory"},{"name":".codespellrc","path":".codespellrc","contentType":"file"},{"name":".gitattributes","path":".gitattributes","contentType":"file"},{"name":".gitignore","path":".gitignore","contentType":"file"},{"name":".pre-commit-config.yaml","path":".pre-commit-config.yaml","contentType":"file"},{"name":".readthedocs.yaml","path":".readthedocs.yaml","contentType":"file"},{"name":".ruff.toml","path":".ruff.toml","contentType":"file"},{"name":"CONTRIBUTING.rst","path":"CONTRIBUTING.rst","contentType":"file"},{"name":"Makefile","path":"Makefile","contentType":"file"},{"name":"README.rst","path":"README.rst","contentType":"file"},{"name":"build.py","path":"build.py","contentType":"file"},{"name":"check-peps.py","path":"check-peps.py","contentType":"file"},{"name":"pytest.ini","path":"pytest.ini","contentType":"file"},{"name":"requirements.txt","path":"requirements.txt","contentType":"file"},{"name":"tox.ini","path":"tox.ini","contentType":"file"}],"totalCount":20}},"fileTreeProcessingTime":209.350548,"foldersToFetch":[],"repo":{"id":13414105,"defaultBranch":"main","name":"peps","ownerLogin":"python","currentUserCanPush":false,"isFork":false,"isEmpty":false,"createdAt":"2013-10-08T13:27:12.000Z","ownerAvatar":"https://avatars.githubusercontent.com/u/1525981?v=4","public":true,"private":false,"isOrgOwned":true},"codeLineWrapEnabled":false,"symbolsExpanded":false,"treeExpanded":true,"refInfo":{"name":"main","listCacheKey":"v0:1736207583.0","canEdit":false,"refType":"branch","currentOid":"d99042d084c53033ad70eb03b79f375ce95a3c5b"},"path":"peps/pep-0667.rst","currentUser":null,"blob":{"rawLines":null,"stylingDirectives":null,"colorizedLines":null,"csv":null,"csvError":null,"dependabotInfo":{"showConfigurationBanner":false,"configFilePath":null,"networkDependabotPath":"/python/peps/network/updates","dismissConfigurationNoticePath":"/settings/dismiss-notice/dependabot_configuration_notice","configurationNoticeDismissed":null},"displayName":"pep-0667.rst","displayUrl":"https://github.com/python/peps/blob/main/peps/pep-0667.rst?raw=true","headerInfo":{"blobSize":"31.2 KB","deleteTooltip":"You must be signed in to make or propose changes","editTooltip":"You must be signed in to make or propose changes","ghDesktopPath":"https://desktop.github.com","isGitLfs":false,"onBranch":true,"shortPath":"1cd82b4","siteNavLoginPath":"/login?return_to=https%3A%2F%2Fgithub.com%2Fpython%2Fpeps%2Fblob%2Fmain%2Fpeps%2Fpep-0667.rst","isCSV":false,"isRichtext":true,"toc":[{"level":2,"text":"Abstract","anchor":"abstract","htmlText":"Abstract"},{"level":2,"text":"Motivation","anchor":"motivation","htmlText":"Motivation"},{"level":2,"text":"Rationale","anchor":"rationale","htmlText":"Rationale"},{"level":3,"text":"Making the frame.f_locals attribute a write-through proxy","anchor":"making-the-framef_locals-attribute-a-write-through-proxy","htmlText":"Making the frame.f_locals attribute a write-through proxy"},{"level":3,"text":"Making the locals() builtin return independent snapshots","anchor":"making-the-locals-builtin-return-independent-snapshots","htmlText":"Making the locals() builtin return independent snapshots"},{"level":2,"text":"Specification","anchor":"specification","htmlText":"Specification"},{"level":3,"text":"Python API","anchor":"python-api","htmlText":"Python API"},{"level":4,"text":"The frame.f_locals attribute","anchor":"the-framef_locals-attribute","htmlText":"The frame.f_locals attribute"},{"level":4,"text":"The locals() builtin","anchor":"the-locals-builtin","htmlText":"The locals() builtin"},{"level":4,"text":"The eval() and exec() builtins","anchor":"the-eval-and-exec-builtins","htmlText":"The eval() and exec() builtins"},{"level":3,"text":"C API","anchor":"c-api","htmlText":"C API"},{"level":4,"text":"Additions to the PyEval C API","anchor":"additions-to-the-pyeval-c-api","htmlText":"Additions to the PyEval C API"},{"level":4,"text":"PyFrame_GetLocals C API","anchor":"pyframe_getlocals-c-api","htmlText":"PyFrame_GetLocals C API"},{"level":4,"text":"Deprecated C APIs","anchor":"deprecated-c-apis","htmlText":"Deprecated C APIs"},{"level":2,"text":"Summary of Changes","anchor":"summary-of-changes","htmlText":"Summary of Changes"},{"level":3,"text":"Python API changes","anchor":"python-api-changes","htmlText":"Python API changes"},{"level":4,"text":"frame.f_locals changes","anchor":"framef_locals-changes","htmlText":"frame.f_locals changes"},{"level":4,"text":"locals() changes","anchor":"locals-changes","htmlText":"locals() changes"},{"level":4,"text":"eval() and exec() changes","anchor":"eval-and-exec-changes","htmlText":"eval() and exec() changes"},{"level":3,"text":"C API changes","anchor":"c-api-changes","htmlText":"C API changes"},{"level":4,"text":"PyFrame_GetLocals change","anchor":"pyframe_getlocals-change","htmlText":"PyFrame_GetLocals change"},{"level":4,"text":"PyEval_GetLocals change","anchor":"pyeval_getlocals-change","htmlText":"PyEval_GetLocals change"},{"level":2,"text":"Backwards Compatibility","anchor":"backwards-compatibility","htmlText":"Backwards Compatibility"},{"level":3,"text":"Python API compatibility","anchor":"python-api-compatibility","htmlText":"Python API compatibility"},{"level":3,"text":"frame.f_locals compatibility","anchor":"framef_locals-compatibility","htmlText":"frame.f_locals compatibility"},{"level":4,"text":"locals() compatibility","anchor":"locals-compatibility","htmlText":"locals() compatibility"},{"level":4,"text":"Impact on exec() and eval()","anchor":"impact-on-exec-and-eval","htmlText":"Impact on exec() and eval()"},{"level":4,"text":"Impact on other code execution APIs in the standard library","anchor":"impact-on-other-code-execution-apis-in-the-standard-library","htmlText":"Impact on other code execution APIs in the standard library"},{"level":3,"text":"C API compatibility","anchor":"c-api-compatibility","htmlText":"C API compatibility"},{"level":4,"text":"PyEval_GetLocals compatibility","anchor":"pyeval_getlocals-compatibility","htmlText":"PyEval_GetLocals compatibility"},{"level":3,"text":"Impact on PEP 709 inlined comprehensions","anchor":"impact-on-pep-709-inlined-comprehensions","htmlText":"Impact on PEP 709 inlined comprehensions"},{"level":2,"text":"Implementation","anchor":"implementation","htmlText":"Implementation"},{"level":3,"text":"C API","anchor":"c-api-1","htmlText":"C API"},{"level":2,"text":"Implementation Notes","anchor":"implementation-notes","htmlText":"Implementation Notes"},{"level":2,"text":"Comparison with PEP 558","anchor":"comparison-with-pep-558","htmlText":"Comparison with PEP 558"},{"level":2,"text":"Reference Implementation","anchor":"reference-implementation","htmlText":"Reference Implementation"},{"level":2,"text":"Copyright","anchor":"copyright","htmlText":"Copyright"}],"lineInfo":{"truncatedLoc":"832","truncatedSloc":"644"},"mode":"file"},"image":false,"isCodeownersFile":null,"isPlain":false,"isValidLegacyIssueTemplate":false,"issueTemplate":null,"discussionTemplate":null,"language":"reStructuredText","languageID":419,"large":false,"planSupportInfo":{"repoIsFork":null,"repoOwnedByCurrentUser":null,"requestFullPath":"/python/peps/blob/main/peps/pep-0667.rst","showFreeOrgGatedFeatureMessage":null,"showPlanSupportBanner":null,"upgradeDataAttributes":null,"upgradePath":null},"publishBannersInfo":{"dismissActionNoticePath":"/settings/dismiss-notice/publish_action_from_dockerfile","releasePath":"/python/peps/releases/new?marketplace=true","showPublishActionBanner":false},"rawBlobUrl":"https://github.com/python/peps/raw/refs/heads/main/peps/pep-0667.rst","renderImageOrRaw":false,"richText":"\u003carticle class=\"markdown-body entry-content container-lg\" itemprop=\"text\"\u003e\u003cp dir=\"auto\"\u003ePEP: 667\nTitle: Consistent views of namespaces\nAuthor: Mark Shannon \u0026lt;\u003ca href=\"mailto:mark@hotpy.org\"\u003emark@hotpy.org\u003c/a\u003e\u0026gt;,\u003c/p\u003e\n\u003cblockquote\u003e\nTian Gao \u0026lt;\u003ca href=\"mailto:gaogaotiantian@hotmail.com\"\u003egaogaotiantian@hotmail.com\u003c/a\u003e\u0026gt;\u003c/blockquote\u003e\n\u003cp dir=\"auto\"\u003eDiscussions-To: \u003ca href=\"https://discuss.python.org/t/46631\" rel=\"nofollow\"\u003ehttps://discuss.python.org/t/46631\u003c/a\u003e\nStatus: Final\nType: Standards Track\nCreated: 30-Jul-2021\nPython-Version: 3.13\nPost-History: 20-Aug-2021, 22-Feb-2024\nResolution: \u003ca href=\"https://discuss.python.org/t/46631/25\" rel=\"nofollow\"\u003e25-Apr-2024\u003c/a\u003e\u003c/p\u003e\n\u003cpre\u003e.. canonical-doc:: :external+py3.13:func:`locals`\n\n\u003c/pre\u003e\n\u003ca name=\"user-content-abstract\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eAbstract\u003c/h2\u003e\u003ca id=\"user-content-abstract\" class=\"anchor\" aria-label=\"Permalink: Abstract\" href=\"#abstract\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eIn early versions of Python all namespaces, whether in functions,\nclasses or modules, were all implemented the same way: as a dictionary.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eFor performance reasons, the implementation of function namespaces was\nchanged. Unfortunately this meant that accessing these namespaces through\n\u003ccode\u003elocals()\u003c/code\u003e and \u003ccode\u003eframe.f_locals\u003c/code\u003e ceased to be consistent and some\nodd bugs crept in over the years as threads, generators and coroutines\nwere added.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThis PEP proposes making these namespaces consistent once more.\nModifications to \u003ccode\u003eframe.f_locals\u003c/code\u003e will always be visible in\nthe underlying variables. Modifications to local variables will\nimmediately be visible in \u003ccode\u003eframe.f_locals\u003c/code\u003e, and they will be\nconsistent regardless of threading or coroutines.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003elocals()\u003c/code\u003e function will act the same as it does now for class\nand modules scopes. For function scopes it will return an instantaneous\nsnapshot of the underlying \u003ccode\u003eframe.f_locals\u003c/code\u003e rather than implicitly\nrefreshing a single shared dictionary cached on the frame object.\u003c/p\u003e\n\u003ca name=\"user-content-motivation\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eMotivation\u003c/h2\u003e\u003ca id=\"user-content-motivation\" class=\"anchor\" aria-label=\"Permalink: Motivation\" href=\"#motivation\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe implementation of \u003ccode\u003elocals()\u003c/code\u003e and \u003ccode\u003eframe.f_locals\u003c/code\u003e in releases up to and\nincluding Python 3.12 is slow, inconsistent and buggy.\nWe want to make it faster, consistent, and most importantly fix the bugs.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eFor example, when attempting to manipulate local variables via frame objects:\u003c/p\u003e\n\u003cpre\u003eclass C:\n x = 1\n sys._getframe().f_locals['x'] = 2\n print(x)\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eprints \u003ccode\u003e2\u003c/code\u003e, but:\u003c/p\u003e\n\u003cpre\u003edef f():\n x = 1\n sys._getframe().f_locals['x'] = 2\n print(x)\nf()\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eprints \u003ccode\u003e1\u003c/code\u003e.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThis is inconsistent, and confusing. Worse than that, the Python 3.12 behavior can\nresult in strange \u003ca href=\"https://github.com/python/cpython/issues/74929\" data-hovercard-type=\"issue\" data-hovercard-url=\"/python/cpython/issues/74929/hovercard\"\u003ebugs\u003c/a\u003e.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eWith this PEP both examples would print \u003ccode\u003e2\u003c/code\u003e as the function level\nchange would be written directly to the optimized local variables in\nthe frame rather than to a cached dictionary snapshot.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThere are no compensating advantages for the Python 3.12 behavior;\nit is unreliable and slow.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003elocals()\u003c/code\u003e builtin has its own undesirable behaviours. Refer to \u003ca href=\"http://www.python.org/dev/peps/pep-0558\" rel=\"nofollow\"\u003ePEP 558\u003c/a\u003e\nfor additional details on those concerns.\u003c/p\u003e\n\u003ca name=\"user-content-rationale\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eRationale\u003c/h2\u003e\u003ca id=\"user-content-rationale\" class=\"anchor\" aria-label=\"Permalink: Rationale\" href=\"#rationale\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003ca name=\"user-content-making-the-frame-f-locals-attribute-a-write-through-proxy\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eMaking the \u003ccode\u003eframe.f_locals\u003c/code\u003e attribute a write-through proxy\u003c/h3\u003e\u003ca id=\"user-content-making-the-framef_locals-attribute-a-write-through-proxy\" class=\"anchor\" aria-label=\"Permalink: Making the frame.f_locals attribute a write-through proxy\" href=\"#making-the-framef_locals-attribute-a-write-through-proxy\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe Python 3.12 implementation of \u003ccode\u003eframe.f_locals\u003c/code\u003e returns a dictionary\nthat is created on the fly from the array of local variables. The\n\u003ccode\u003ePyFrame_LocalsToFast()\u003c/code\u003e C API is then called by debuggers and trace\nfunctions that want to write their changes back to the array (until\nPython 3.11, this API was called implicitly after every trace function\ninvocation rather than being called explicitly by the trace functions).\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThis can result in the array and dictionary getting out of sync with\neach other. Writes to the \u003ccode\u003ef_locals\u003c/code\u003e frame attribute may not show up as\nmodifications to local variables if \u003ccode\u003ePyFrame_LocalsToFast()\u003c/code\u003e is never\ncalled. Writes to local variables can get lost if a dictionary snapshot\ncreated before the variables were modified is written back to the frame\n(since \u003cem\u003eevery\u003c/em\u003e known variable stored in the snapshot is written back to\nthe frame, even if the value stored on the frame had changed since the\nsnapshot was taken).\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eBy making \u003ccode\u003eframe.f_locals\u003c/code\u003e return a view on the\nunderlying frame, these problems go away. \u003ccode\u003eframe.f_locals\u003c/code\u003e is always in\nsync with the frame because it is a view of it, not a copy of it.\u003c/p\u003e\n\u003ca name=\"user-content-making-the-locals-builtin-return-independent-snapshots\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eMaking the \u003ccode\u003elocals()\u003c/code\u003e builtin return independent snapshots\u003c/h3\u003e\u003ca id=\"user-content-making-the-locals-builtin-return-independent-snapshots\" class=\"anchor\" aria-label=\"Permalink: Making the locals() builtin return independent snapshots\" href=\"#making-the-locals-builtin-return-independent-snapshots\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ca href=\"http://www.python.org/dev/peps/pep-0558\" rel=\"nofollow\"\u003ePEP 558\u003c/a\u003e considered three potential options for standardising the behavior of the\n\u003ccode\u003elocals()\u003c/code\u003e builtin in \u003ca href=\"#id1\"\u003e\u003cspan id=\"user-content-id2\"\u003e:term:`optimized scopes \u0026lt;py3.13:optimized scope\u0026gt;`\u003c/span\u003e\u003c/a\u003e:\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eretain the historical behaviour of having each call to \u003ccode\u003elocals()\u003c/code\u003e on a given frame\nupdate a single shared snapshot of the local variables\u003c/li\u003e\n\u003cli\u003emake \u003ccode\u003elocals()\u003c/code\u003e return write-through proxy instances (similar\nto \u003ccode\u003eframe.f_locals\u003c/code\u003e)\u003c/li\u003e\n\u003cli\u003emake \u003ccode\u003elocals()\u003c/code\u003e return genuinely independent snapshots so that\nattempts to change the values of local variables via \u003ccode\u003eexec()\u003c/code\u003e\nwould be \u003cem\u003econsistently\u003c/em\u003e ignored rather than being accepted in some circumstances\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003eThe last option was chosen as the one which could most easily be explained in the\nlanguage reference, and memorised by users:\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003ethe \u003ccode\u003elocals()\u003c/code\u003e builtin gives an instantaneous snapshot of the local variables in\noptimized scopes, and read/write access in other scopes; and\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eframe.f_locals\u003c/code\u003e gives read/write access to the local variables in all scopes,\nincluding optimized scopes\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003eThis approach allows the intent of a piece of code to be clearer than it would be if both\nAPIs granted full read/write access in optimized scopes, even when write access wasn't\nneeded or desired. For additional details on this design decision, refer to \u003ca href=\"http://www.python.org/dev/peps/pep-0558\" rel=\"nofollow\"\u003ePEP 558\u003c/a\u003e,\nespecially the \u003ca href=\"#id3\"\u003e\u003cspan id=\"user-content-id4\"\u003e:ref:`pep-558-motivation`\u003c/span\u003e\u003c/a\u003e section and \u003ca href=\"#id5\"\u003e\u003cspan id=\"user-content-id6\"\u003e:ref:`pep-558-exec-eval-impact`\u003c/span\u003e\u003c/a\u003e.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThis approach is not without its drawbacks, which are covered\nin the Backwards Compatibility section below.\u003c/p\u003e\n\u003ca name=\"user-content-specification\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eSpecification\u003c/h2\u003e\u003ca id=\"user-content-specification\" class=\"anchor\" aria-label=\"Permalink: Specification\" href=\"#specification\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003ca name=\"user-content-python-api\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003ePython API\u003c/h3\u003e\u003ca id=\"user-content-python-api\" class=\"anchor\" aria-label=\"Permalink: Python API\" href=\"#python-api\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003ca name=\"user-content-the-frame-f-locals-attribute\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eThe \u003ccode\u003eframe.f_locals\u003c/code\u003e attribute\u003c/h4\u003e\u003ca id=\"user-content-the-framef_locals-attribute\" class=\"anchor\" aria-label=\"Permalink: The frame.f_locals attribute\" href=\"#the-framef_locals-attribute\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eFor module and class scopes (including \u003ccode\u003eexec()\u003c/code\u003e and \u003ccode\u003eeval()\u003c/code\u003e\ninvocations), \u003ccode\u003eframe.f_locals\u003c/code\u003e is a direct\nreference to the local variable namespace used in code execution.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eFor function scopes (and other \u003ca href=\"#id7\"\u003e\u003cspan id=\"user-content-id8\"\u003e:term:`optimized scopes \u0026lt;py3.13:optimized scope\u0026gt;`\u003c/span\u003e\u003c/a\u003e)\nit will be an instance of a new write-through proxy type that can directly modify\nthe optimized local variable storage array in the underlying frame, as well as the\ncontents of any cell references to non-local variables.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThe view objects fully implement the \u003ccode\u003ecollections.abc.Mapping\u003c/code\u003e interface,\nand also implement the following mutable mapping operations:\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eusing assignment to add new key/value pairs\u003c/li\u003e\n\u003cli\u003eusing assignment to update the value associated with a key\u003c/li\u003e\n\u003cli\u003econditional assignment via the \u003ccode\u003esetdefault()\u003c/code\u003e method\u003c/li\u003e\n\u003cli\u003ebulk updates via the \u003ccode\u003eupdate()\u003c/code\u003e method\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003eViews of different frames compare unequal even if they have the same contents.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eAll writes to the \u003ccode\u003ef_locals\u003c/code\u003e mapping will be immediately visible\nin the underlying variables. All changes to the underlying variables\nwill be immediately visible in the mapping.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003ef_locals\u003c/code\u003e object will be a full mapping, and can have arbitrary\nkey-value pairs added to it. New names added via the proxies\nwill be stored in a dedicated shared dictionary stored on the\nunderlying frame object (so all proxy instances for a given frame\nwill be able to access any names added this way).\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eExtra keys (which do not correspond to local variables on the underlying\nframe) may be removed as usual with \u003ccode\u003edel\u003c/code\u003e statements or the \u003ccode\u003epop()\u003c/code\u003e\nmethod.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eUsing \u003ccode\u003edel\u003c/code\u003e, or the \u003ccode\u003epop()\u003c/code\u003e method, to remove keys that correspond to local\nvariables on the underlying frame is NOT supported, and attempting to do so\nwill raise \u003ccode\u003eValueError\u003c/code\u003e.\nLocal variables can only be set to \u003ccode\u003eNone\u003c/code\u003e (or some other value) via the proxy,\nthey cannot be unbound completely.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003eclear()\u003c/code\u003e method is NOT implemented on the write-through proxies, as it\nis unclear how it should handle the inability to delete entries corresponding\nto local variables.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eTo maintain backwards compatibility, proxy APIs that need to produce a\nnew mapping (such as \u003ccode\u003ecopy()\u003c/code\u003e) will produce regular builtin \u003ccode\u003edict\u003c/code\u003e\ninstances, rather than write-through proxy instances.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eTo avoid introducing a circular reference between frame objects and the\nwrite-through proxies, each access to \u003ccode\u003eframe.f_locals\u003c/code\u003e returns a \u003cem\u003enew\u003c/em\u003e\nwrite-through proxy instance.\u003c/p\u003e\n\u003ca name=\"user-content-the-locals-builtin\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eThe \u003ccode\u003elocals()\u003c/code\u003e builtin\u003c/h4\u003e\u003ca id=\"user-content-the-locals-builtin\" class=\"anchor\" aria-label=\"Permalink: The locals() builtin\" href=\"#the-locals-builtin\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003elocals()\u003c/code\u003e will be defined as:\u003c/p\u003e\n\u003cpre\u003edef locals():\n frame = sys._getframe(1)\n f_locals = frame.f_locals\n if frame._is_optimized(): # Not an actual frame method\n f_locals = dict(f_locals)\n return f_locals\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eFor module and class scopes (including \u003ccode\u003eexec()\u003c/code\u003e and \u003ccode\u003eeval()\u003c/code\u003e\ninvocations), \u003ccode\u003elocals()\u003c/code\u003e continues to return a direct\nreference to the local variable namespace used in code execution\n(which is also the same value reported by \u003ccode\u003eframe.f_locals\u003c/code\u003e).\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eIn \u003ca href=\"#id9\"\u003e\u003cspan id=\"user-content-id10\"\u003e:term:`optimized scopes \u0026lt;py3.13:optimized scope\u0026gt;`\u003c/span\u003e\u003c/a\u003e,\neach call to \u003ccode\u003elocals()\u003c/code\u003e will produce an \u003cem\u003eindependent\u003c/em\u003e\nsnapshot of the local variables.\u003c/p\u003e\n\u003ca name=\"user-content-the-eval-and-exec-builtins\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eThe \u003ccode\u003eeval()\u003c/code\u003e and \u003ccode\u003eexec()\u003c/code\u003e builtins\u003c/h4\u003e\u003ca id=\"user-content-the-eval-and-exec-builtins\" class=\"anchor\" aria-label=\"Permalink: The eval() and exec() builtins\" href=\"#the-eval-and-exec-builtins\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eBecause this PEP changes the behavior of \u003ccode\u003elocals()\u003c/code\u003e, the\nbehavior of \u003ccode\u003eeval()\u003c/code\u003e and \u003ccode\u003eexec()\u003c/code\u003e also changes.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eAssuming a function \u003ccode\u003e_eval()\u003c/code\u003e which performs the job of\n\u003ccode\u003eeval()\u003c/code\u003e with explicit namespace arguments, \u003ccode\u003eeval()\u003c/code\u003e\ncan be defined as follows:\u003c/p\u003e\n\u003cpre\u003eFrameProxyType = type((lambda: sys._getframe().f_locals)())\n\ndef eval(expression, /, globals=None, locals=None):\n if globals is None:\n # No globals -\u0026gt; use calling frame's globals\n _calling_frame = sys._getframe(1)\n globals = _calling_frame.f_globals\n if locals is None:\n # No globals or locals -\u0026gt; use calling frame's locals\n locals = _calling_frame.f_locals\n if isinstance(locals, FrameProxyType):\n # Align with locals() builtin in optimized frame\n locals = dict(locals)\n elif locals is None:\n # Globals but no locals -\u0026gt; use same namespace for both\n locals = globals\n return _eval(expression, globals, locals)\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eThe specified argument handling for \u003ccode\u003eexec()\u003c/code\u003e is similarly updated.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e(In Python 3.12 and earlier, it was not possible to provide \u003ccode\u003elocals\u003c/code\u003e\nto \u003ccode\u003eeval()\u003c/code\u003e or \u003ccode\u003eexec()\u003c/code\u003e without also providing \u003ccode\u003eglobals\u003c/code\u003e as these\nwere previously positional-only arguments. Independently of this\nPEP, Python 3.13 updated these builtins to accept keyword arguments)\u003c/p\u003e\n\u003ca name=\"user-content-c-api\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eC API\u003c/h3\u003e\u003ca id=\"user-content-c-api\" class=\"anchor\" aria-label=\"Permalink: C API\" href=\"#c-api\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003ca name=\"user-content-additions-to-the-pyeval-c-api\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eAdditions to the \u003ccode\u003ePyEval\u003c/code\u003e C API\u003c/h4\u003e\u003ca id=\"user-content-additions-to-the-pyeval-c-api\" class=\"anchor\" aria-label=\"Permalink: Additions to the PyEval C API\" href=\"#additions-to-the-pyeval-c-api\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThree new C-API functions will be added:\u003c/p\u003e\n\u003cpre\u003ePyObject *PyEval_GetFrameLocals(void)\nPyObject *PyEval_GetFrameGlobals(void)\nPyObject *PyEval_GetFrameBuiltins(void)\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003ePyEval_GetFrameLocals()\u003c/code\u003e is equivalent to: \u003ccode\u003elocals()\u003c/code\u003e.\n\u003ccode\u003ePyEval_GetFrameGlobals()\u003c/code\u003e is equivalent to: \u003ccode\u003eglobals()\u003c/code\u003e.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eAll of these functions will return a new reference.\u003c/p\u003e\n\u003ca name=\"user-content-pyframe-getlocals-c-api\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e\u003ccode\u003ePyFrame_GetLocals\u003c/code\u003e C API\u003c/h4\u003e\u003ca id=\"user-content-pyframe_getlocals-c-api\" class=\"anchor\" aria-label=\"Permalink: PyFrame_GetLocals C API\" href=\"#pyframe_getlocals-c-api\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe existing \u003ccode\u003ePyFrame_GetLocals(f)\u003c/code\u003e C API is equivalent to \u003ccode\u003ef.f_locals\u003c/code\u003e.\nIts return value will be as described above for accessing \u003ccode\u003ef.f_locals\u003c/code\u003e.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThis function returns a new reference, so it is able to accommodate the\ncreation of a new write-through proxy instance on each call in an\noptimized scope.\u003c/p\u003e\n\u003ca name=\"user-content-deprecated-c-apis\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eDeprecated C APIs\u003c/h4\u003e\u003ca id=\"user-content-deprecated-c-apis\" class=\"anchor\" aria-label=\"Permalink: Deprecated C APIs\" href=\"#deprecated-c-apis\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe following C API functions will be deprecated, as they return borrowed references:\u003c/p\u003e\n\u003cpre\u003ePyEval_GetLocals()\nPyEval_GetGlobals()\nPyEval_GetBuiltins()\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eThe following functions (which return new references) should be used instead:\u003c/p\u003e\n\u003cpre\u003ePyEval_GetFrameLocals()\nPyEval_GetFrameGlobals()\nPyEval_GetFrameBuiltins()\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eThe following C API functions will become no-ops, and will be deprecated without\nreplacement:\u003c/p\u003e\n\u003cpre\u003ePyFrame_FastToLocalsWithError()\nPyFrame_FastToLocals()\nPyFrame_LocalsToFast()\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eAll of the deprecated functions will be marked as deprecated in the Python 3.13 documentation.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eOf these functions, only \u003ccode\u003ePyEval_GetLocals()\u003c/code\u003e poses any significant maintenance burden.\nAccordingly, calls to \u003ccode\u003ePyEval_GetLocals()\u003c/code\u003e will emit \u003ccode\u003eDeprecationWarning\u003c/code\u003e in Python\n3.14, with a target removal date of Python 3.16 (two releases after Python 3.14).\nAlternatives are recommended as described in \u003ca href=\"#id11\"\u003e\u003cspan id=\"user-content-id12\"\u003e:ref:`pep-667-pyeval-getlocals-compatibility`\u003c/span\u003e\u003c/a\u003e.\u003c/p\u003e\n\u003ca name=\"user-content-summary-of-changes\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eSummary of Changes\u003c/h2\u003e\u003ca id=\"user-content-summary-of-changes\" class=\"anchor\" aria-label=\"Permalink: Summary of Changes\" href=\"#summary-of-changes\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThis section summarises how the specified behaviour in Python 3.13 and later\ndiffers from the historical behaviour in Python 3.12 and earlier versions.\u003c/p\u003e\n\u003ca name=\"user-content-python-api-changes\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003ePython API changes\u003c/h3\u003e\u003ca id=\"user-content-python-api-changes\" class=\"anchor\" aria-label=\"Permalink: Python API changes\" href=\"#python-api-changes\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003ca name=\"user-content-frame-f-locals-changes\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e\u003ccode\u003eframe.f_locals\u003c/code\u003e changes\u003c/h4\u003e\u003ca id=\"user-content-framef_locals-changes\" class=\"anchor\" aria-label=\"Permalink: frame.f_locals changes\" href=\"#framef_locals-changes\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eConsider the following example:\u003c/p\u003e\n\u003cpre\u003edef l():\n \"Get the locals of caller\"\n return sys._getframe(1).f_locals\n\ndef test():\n if 0: y = 1 # Make 'y' a local variable\n x = 1\n l()['x'] = 2\n l()['y'] = 4\n l()['z'] = 5\n y\n print(locals(), x)\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eGiven the changes in this PEP,\n\u003ccode\u003etest()\u003c/code\u003e will print \u003ccode\u003e{'x': 2, 'y': 4, 'z': 5} 2\u003c/code\u003e.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eIn Python 3.12, this example will fail with an \u003ccode\u003eUnboundLocalError\u003c/code\u003e,\nas the definition of \u003ccode\u003ey\u003c/code\u003e by \u003ccode\u003el()['y'] = 4\u003c/code\u003e is lost.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eIf the second-to-last line were changed from \u003ccode\u003ey\u003c/code\u003e to \u003ccode\u003ez\u003c/code\u003e, this will still\nraise \u003ccode\u003eNameError\u003c/code\u003e, as it does in Python 3.12.\nKeys added to \u003ccode\u003eframe.f_locals\u003c/code\u003e that are not lexically local variables\nremain visible in \u003ccode\u003eframe.f_locals\u003c/code\u003e,\nbut do not dynamically become local variables.\u003c/p\u003e\n\u003ca name=\"user-content-locals-changes\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e\u003ccode\u003elocals()\u003c/code\u003e changes\u003c/h4\u003e\u003ca id=\"user-content-locals-changes\" class=\"anchor\" aria-label=\"Permalink: locals() changes\" href=\"#locals-changes\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eConsider the following example:\u003c/p\u003e\n\u003cpre\u003edef f():\n exec(\"x = 1\")\n print(locals().get(\"x\"))\nf()\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eGiven the changes in this PEP, this will \u003cem\u003ealways\u003c/em\u003e print \u003ccode\u003eNone\u003c/code\u003e\n(regardless of whether \u003ccode\u003ex\u003c/code\u003e is a defined local variable in the function),\nas the explicit call to \u003ccode\u003elocals()\u003c/code\u003e produces a distinct snapshot from\nthe one implicitly used in the \u003ccode\u003eexec()\u003c/code\u003e call.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eIn Python 3.12, the exact example shown would print \u003ccode\u003e1\u003c/code\u003e, but seemingly\nunrelated changes to the definition of the function involved could make\nit print \u003ccode\u003eNone\u003c/code\u003e instead (\u003ca href=\"#id13\"\u003e\u003cspan id=\"user-content-id14\"\u003e:ref:`pep-558-exec-eval-impact`\u003c/span\u003e\u003c/a\u003e in PEP 558\ngoes into more detail on that topic).\u003c/p\u003e\n\u003ca name=\"user-content-eval-and-exec-changes\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e\u003ccode\u003eeval()\u003c/code\u003e and \u003ccode\u003eexec()\u003c/code\u003e changes\u003c/h4\u003e\u003ca id=\"user-content-eval-and-exec-changes\" class=\"anchor\" aria-label=\"Permalink: eval() and exec() changes\" href=\"#eval-and-exec-changes\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe primary change affecting \u003ccode\u003eeval()\u003c/code\u003e and \u003ccode\u003eexec()\u003c/code\u003e is shown\nin the \"\u003ca href=\"#id15\"\u003e\u003cspan id=\"user-content-id16\"\u003e:ref:`pep-667-locals-changes`\u003c/span\u003e\u003c/a\u003e\" example: repeatedly\naccessing \u003ccode\u003elocals()\u003c/code\u003e in an optimized scope will no longer\nimplicitly share a common underlying namespace.\u003c/p\u003e\n\u003ca name=\"user-content-c-api-changes\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eC API changes\u003c/h3\u003e\u003ca id=\"user-content-c-api-changes\" class=\"anchor\" aria-label=\"Permalink: C API changes\" href=\"#c-api-changes\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003ca name=\"user-content-pyframe-getlocals-change\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e\u003ccode\u003ePyFrame_GetLocals\u003c/code\u003e change\u003c/h4\u003e\u003ca id=\"user-content-pyframe_getlocals-change\" class=\"anchor\" aria-label=\"Permalink: PyFrame_GetLocals change\" href=\"#pyframe_getlocals-change\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003ePyFrame_GetLocals\u003c/code\u003e can already return arbitrary mappings in Python 3.12,\nas \u003ccode\u003eexec()\u003c/code\u003e and \u003ccode\u003eeval()\u003c/code\u003e accept arbitrary mappings as their \u003ccode\u003elocals\u003c/code\u003e argument,\nand metaclasses may return arbitrary mappings from their \u003ccode\u003e__prepare__\u003c/code\u003e methods.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eReturning a frame locals proxy in optimized scopes just adds another case where\nsomething other than a builtin dictionary will be returned.\u003c/p\u003e\n\u003ca name=\"user-content-pyeval-getlocals-change\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e\u003ccode\u003ePyEval_GetLocals\u003c/code\u003e change\u003c/h4\u003e\u003ca id=\"user-content-pyeval_getlocals-change\" class=\"anchor\" aria-label=\"Permalink: PyEval_GetLocals change\" href=\"#pyeval_getlocals-change\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe semantics of \u003ccode\u003ePyEval_GetLocals()\u003c/code\u003e are technically unchanged, but they do change in\npractice as the dictionary cached on optimized frames is no longer shared with other\nmechanisms for accessing the frame locals (\u003ccode\u003elocals()\u003c/code\u003e builtin, \u003ccode\u003ePyFrame_GetLocals\u003c/code\u003e\nfunction, frame \u003ccode\u003ef_locals\u003c/code\u003e attributes).\u003c/p\u003e\n\u003ca name=\"user-content-backwards-compatibility\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eBackwards Compatibility\u003c/h2\u003e\u003ca id=\"user-content-backwards-compatibility\" class=\"anchor\" aria-label=\"Permalink: Backwards Compatibility\" href=\"#backwards-compatibility\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003ca name=\"user-content-python-api-compatibility\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003ePython API compatibility\u003c/h3\u003e\u003ca id=\"user-content-python-api-compatibility\" class=\"anchor\" aria-label=\"Permalink: Python API compatibility\" href=\"#python-api-compatibility\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe implementation used in versions up to and including Python 3.12 has many\ncorner cases and oddities. Code that works around those may need to be changed.\nCode that uses \u003ccode\u003elocals()\u003c/code\u003e for simple templating, or print debugging,\nwill continue to work correctly. Debuggers and other tools that use\n\u003ccode\u003ef_locals\u003c/code\u003e to modify local variables, will now work correctly,\neven in the presence of threaded code, coroutines and generators.\u003c/p\u003e\n\u003ca name=\"user-content-frame-f-locals-compatibility\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e\u003ccode\u003eframe.f_locals\u003c/code\u003e compatibility\u003c/h3\u003e\u003ca id=\"user-content-framef_locals-compatibility\" class=\"anchor\" aria-label=\"Permalink: frame.f_locals compatibility\" href=\"#framef_locals-compatibility\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eAlthough \u003ccode\u003ef.f_locals\u003c/code\u003e behaves as if it were the namespace of the function,\nthere will be some observable differences.\nFor example, \u003ccode\u003ef.f_locals is f.f_locals\u003c/code\u003e will be \u003ccode\u003eFalse\u003c/code\u003e for optimized\nframes, as each access to the attribute produces a new write-through proxy\ninstance.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eHowever \u003ccode\u003ef.f_locals == f.f_locals\u003c/code\u003e will be \u003ccode\u003eTrue\u003c/code\u003e, and\nall changes to the underlying variables, by any means, including the\naddition of new variable names as mapping keys, will always be visible.\u003c/p\u003e\n\u003ca name=\"user-content-locals-compatibility\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e\u003ccode\u003elocals()\u003c/code\u003e compatibility\u003c/h4\u003e\u003ca id=\"user-content-locals-compatibility\" class=\"anchor\" aria-label=\"Permalink: locals() compatibility\" href=\"#locals-compatibility\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003elocals() is locals()\u003c/code\u003e will be \u003ccode\u003eFalse\u003c/code\u003e for optimized frames, so\ncode like the following will raise \u003ccode\u003eKeyError\u003c/code\u003e instead of returning\n\u003ccode\u003e1\u003c/code\u003e:\u003c/p\u003e\n\u003cpre\u003edef f():\n locals()[\"x\"] = 1\n return locals()[\"x\"]\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eTo continue working, such code will need to explicitly store the namespace\nto be modified in a local variable, rather than relying on the previous\nimplicit caching on the frame object:\u003c/p\u003e\n\u003cpre\u003edef f():\n ns = {}\n ns[\"x\"] = 1\n return ns[\"x\"]\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eWhile this technically isn't a formal backwards compatibility break\n(since the behaviour of writing back to \u003ccode\u003elocals()\u003c/code\u003e was explicitly\ndocumented as undefined), there is definitely some code that relies\non the existing behaviour. Accordingly, the updated behaviour will\nbe explicitly noted in the documentation as a change and it will be\ncovered in the Python 3.13 porting guide.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eTo work with a copy of \u003ccode\u003elocals()\u003c/code\u003e in optimized scopes on all\nversions without making redundant copies on Python 3.13+, users\nwill need to define a version-dependent helper function that only\nmakes an explicit copy on Python versions prior to Python 3.13:\u003c/p\u003e\n\u003cpre\u003eif sys.version_info \u0026gt;= (3, 13):\n def _ensure_func_snapshot(d):\n return d # 3.13+ locals() already returns a snapshot\nelse:\n def _ensure_func_snapshot(d):\n return dict(d) # Create snapshot on older versions\n\ndef f():\n ns = _ensure_func_snapshot(locals())\n ns[\"x\"] = 1\n return ns\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eIn other scopes, \u003ccode\u003elocals().copy()\u003c/code\u003e can continue to be called\nunconditionally without introducing any redundant copies.\u003c/p\u003e\n\u003ca name=\"user-content-impact-on-exec-and-eval\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eImpact on \u003ccode\u003eexec()\u003c/code\u003e and \u003ccode\u003eeval()\u003c/code\u003e\u003c/h4\u003e\u003ca id=\"user-content-impact-on-exec-and-eval\" class=\"anchor\" aria-label=\"Permalink: Impact on exec() and eval()\" href=\"#impact-on-exec-and-eval\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eEven though this PEP does not modify \u003ccode\u003eexec()\u003c/code\u003e or \u003ccode\u003eeval()\u003c/code\u003e directly,\nthe semantic change to \u003ccode\u003elocals()\u003c/code\u003e impacts the behavior of \u003ccode\u003eexec()\u003c/code\u003e\nand \u003ccode\u003eeval()\u003c/code\u003e as they default to running code in the calling namespace.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThis poses a potential compatibility issue for some code, as with the\nprevious implementation that returns the same dict when \u003ccode\u003elocals()\u003c/code\u003e is called\nmultiple times in function scope, the following code usually worked due to\nthe implicitly shared local variable namespace:\u003c/p\u003e\n\u003cpre\u003edef f():\n exec('a = 0') # equivalent to exec('a = 0', globals(), locals())\n exec('print(a)') # equivalent to exec('print(a)', globals(), locals())\n print(locals()) # {'a': 0}\n # However, print(a) will not work here\nf()\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eWith the semantic changes to \u003ccode\u003elocals()\u003c/code\u003e in this PEP, the \u003ccode\u003eexec('print(a)')'\u003c/code\u003e call\nwill fail with \u003ccode\u003eNameError\u003c/code\u003e, and \u003ccode\u003eprint(locals())\u003c/code\u003e will report an empty dictionary, as\neach line will be using its own distinct snapshot of the local variables rather than\nimplicitly sharing a single cached snapshot stored on the frame object.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eA shared namespace across \u003ccode\u003eexec()\u003c/code\u003e calls can still be obtained by using explicit\nnamespaces rather than relying on the previously implicitly shared frame namespace:\u003c/p\u003e\n\u003cpre\u003edef f():\n ns = {}\n exec('a = 0', locals=ns)\n exec('print(a)', locals=ns) # 0\nf()\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eYou can even reliably change the variables in the local scope by explicitly using\n\u003ccode\u003eframe.f_locals\u003c/code\u003e, which was not possible before (even using \u003ccode\u003ectypes\u003c/code\u003e to\ninvoke \u003ccode\u003ePyFrame_LocalsToFast\u003c/code\u003e was subject to the state inconsistency problems\ndiscussed elsewhere in this PEP):\u003c/p\u003e\n\u003cpre\u003edef f():\n a = None\n exec('a = 0', locals=sys._getframe().f_locals)\n print(a) # 0\nf()\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eThe behavior of \u003ccode\u003eexec()\u003c/code\u003e and \u003ccode\u003eeval()\u003c/code\u003e for module and class scopes (including\nnested invocations) is not changed, as the behaviour of \u003ccode\u003elocals()\u003c/code\u003e in those\nscopes is not changing.\u003c/p\u003e\n\u003ca name=\"user-content-impact-on-other-code-execution-apis-in-the-standard-library\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eImpact on other code execution APIs in the standard library\u003c/h4\u003e\u003ca id=\"user-content-impact-on-other-code-execution-apis-in-the-standard-library\" class=\"anchor\" aria-label=\"Permalink: Impact on other code execution APIs in the standard library\" href=\"#impact-on-other-code-execution-apis-in-the-standard-library\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003epdb\u003c/code\u003e and \u003ccode\u003ebdb\u003c/code\u003e use the \u003ccode\u003eframe.f_locals\u003c/code\u003e API, and hence will be able to\nreliably update local variables even in optimized frames. Implementing this\nPEP will resolve several longstanding bugs in these modules relating to threads,\ngenerators, coroutines, and other mechanisms that allow concurrent code execution\nwhile the debugger is active.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eOther code execution APIs in the standard library (such as the \u003ccode\u003ecode\u003c/code\u003e module)\ndo not implicitly access \u003ccode\u003elocals()\u003c/code\u003e \u003cem\u003eor\u003c/em\u003e \u003ccode\u003eframe.f_locals\u003c/code\u003e, but the behaviour\nof explicitly passing these namespaces will change as described in the rest of\nthis PEP (passing \u003ccode\u003elocals()\u003c/code\u003e in optimized scopes will no longer implicitly\nshare the code execution namespace across calls, passing \u003ccode\u003eframe.f_locals\u003c/code\u003e\nin optimized scopes will allow reliable modification of local variables and\nnonlocal cell references).\u003c/p\u003e\n\u003ca name=\"user-content-c-api-compatibility\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eC API compatibility\u003c/h3\u003e\u003ca id=\"user-content-c-api-compatibility\" class=\"anchor\" aria-label=\"Permalink: C API compatibility\" href=\"#c-api-compatibility\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003ca name=\"user-content-pyeval-getlocals-compatibility\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e\u003ccode\u003ePyEval_GetLocals\u003c/code\u003e compatibility\u003c/h4\u003e\u003ca id=\"user-content-pyeval_getlocals-compatibility\" class=\"anchor\" aria-label=\"Permalink: PyEval_GetLocals compatibility\" href=\"#pyeval_getlocals-compatibility\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003ePyEval_GetLocals()\u003c/code\u003e has never historically distinguished between whether it was\nemulating \u003ccode\u003elocals()\u003c/code\u003e or \u003ccode\u003esys._getframe().f_locals\u003c/code\u003e at the Python level, as they all\nreturned references to the same shared cache of the local variable bindings.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eWith this PEP, \u003ccode\u003elocals()\u003c/code\u003e changes to return independent snapshots on each call for\noptimized frames, and \u003ccode\u003eframe.f_locals\u003c/code\u003e (along with \u003ccode\u003ePyFrame_GetLocals\u003c/code\u003e) changes to\nreturn new write-through proxy instances.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eBecause \u003ccode\u003ePyEval_GetLocals()\u003c/code\u003e returns a borrowed reference, it isn't possible to update\nits semantics to align with either of those alternatives, leaving it as the only remaining\nAPI that requires a shared cache dictionary stored on the frame object.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eWhile this technically leaves the semantics of the function unchanged, it no longer allows\nextra dict entries to be made visible to users of the other APIs, as those APIs are no longer\naccessing the same underlying cache dictionary.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eWhen \u003ccode\u003ePyEval_GetLocals()\u003c/code\u003e is being used as an equivalent to the Python \u003ccode\u003elocals()\u003c/code\u003e\nbuiltin, \u003ccode\u003ePyEval_GetFrameLocals()\u003c/code\u003e should be used instead.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThis code:\u003c/p\u003e\n\u003cpre\u003elocals = PyEval_GetLocals();\nif (locals == NULL) {\n goto error_handler;\n}\nPy_INCREF(locals);\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eshould be replaced with:\u003c/p\u003e\n\u003cpre\u003e// Equivalent to \"locals()\" in Python code\nlocals = PyEval_GetFrameLocals();\nif (locals == NULL) {\n goto error_handler;\n}\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eWhen \u003ccode\u003ePyEval_GetLocals()\u003c/code\u003e is being used as an equivalent to calling\n\u003ccode\u003esys._getframe().f_locals\u003c/code\u003e in Python, it should be replaced by calling\n\u003ccode\u003ePyFrame_GetLocals()\u003c/code\u003e on the result of \u003ccode\u003ePyEval_GetFrame()\u003c/code\u003e.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eIn these cases, the original code should be replaced with:\u003c/p\u003e\n\u003cpre\u003e// Equivalent to \"sys._getframe()\" in Python code\nframe = PyEval_GetFrame();\nif (frame == NULL) {\n goto error_handler;\n}\n// Equivalent to \"frame.f_locals\" in Python code\nlocals = PyFrame_GetLocals(frame);\nframe = NULL; // Minimise visibility of borrowed reference\nif (locals == NULL) {\n goto error_handler;\n}\n\u003c/pre\u003e\n\u003ca name=\"user-content-impact-on-pep-709-inlined-comprehensions\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eImpact on PEP 709 inlined comprehensions\u003c/h3\u003e\u003ca id=\"user-content-impact-on-pep-709-inlined-comprehensions\" class=\"anchor\" aria-label=\"Permalink: Impact on PEP 709 inlined comprehensions\" href=\"#impact-on-pep-709-inlined-comprehensions\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eFor inlined comprehensions within a function, \u003ccode\u003elocals()\u003c/code\u003e currently behaves the\nsame inside or outside of the comprehension, and this will not change. The\nbehavior of \u003ccode\u003elocals()\u003c/code\u003e inside functions will generally change as specified in\nthe rest of this PEP.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eFor inlined comprehensions at module or class scope, calling \u003ccode\u003elocals()\u003c/code\u003e within\nthe inlined comprehension returns a new dictionary for each call. This PEP will\nmake \u003ccode\u003elocals()\u003c/code\u003e within a function also always return a new dictionary for each\ncall, improving consistency; class or module scope inlined comprehensions will\nappear to behave as if the inlined comprehension is still a distinct function.\u003c/p\u003e\n\u003ca name=\"user-content-implementation\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eImplementation\u003c/h2\u003e\u003ca id=\"user-content-implementation\" class=\"anchor\" aria-label=\"Permalink: Implementation\" href=\"#implementation\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eEach read of \u003ccode\u003eframe.f_locals\u003c/code\u003e will create a new proxy object that gives\nthe appearance of being the mapping of local (including cell and free)\nvariable names to the values of those local variables.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eA possible implementation is sketched out below.\nAll attributes that start with an underscore are invisible and\ncannot be accessed directly.\nThey serve only to illustrate the proposed design.\u003c/p\u003e\n\u003cpre\u003eNULL: Object # NULL is a singleton representing the absence of a value.\n\nclass CodeType:\n\n _name_to_offset_mapping_impl: dict | NULL\n _cells: frozenset # Set of indexes of cell and free variables\n ...\n\n def __init__(self, ...):\n self._name_to_offset_mapping_impl = NULL\n self._variable_names = deduplicate(\n self.co_varnames + self.co_cellvars + self.co_freevars\n )\n ...\n\n @property\n def _name_to_offset_mapping(self):\n \"Mapping of names to offsets in local variable array.\"\n if self._name_to_offset_mapping_impl is NULL:\n self._name_to_offset_mapping_impl = {\n name: index for (index, name) in enumerate(self._variable_names)\n }\n return self._name_to_offset_mapping_impl\n\nclass FrameType:\n\n _locals : array[Object] # The values of the local variables, items may be NULL.\n _extra_locals: dict | NULL # Dictionary for storing extra locals not in _locals.\n _locals_cache: FrameLocalsProxy | NULL # required to support PyEval_GetLocals()\n\n def __init__(self, ...):\n self._extra_locals = NULL\n self._locals_cache = NULL\n ...\n\n @property\n def f_locals(self):\n return FrameLocalsProxy(self)\n\nclass FrameLocalsProxy:\n \"Implements collections.MutableMapping.\"\n\n __slots__ = (\"_frame\", )\n\n def __init__(self, frame:FrameType):\n self._frame = frame\n\n def __getitem__(self, name):\n f = self._frame\n co = f.f_code\n if name in co._name_to_offset_mapping:\n index = co._name_to_offset_mapping[name]\n val = f._locals[index]\n if val is NULL:\n raise KeyError(name)\n if index in co._cells\n val = val.cell_contents\n if val is NULL:\n raise KeyError(name)\n return val\n else:\n if f._extra_locals is NULL:\n raise KeyError(name)\n return f._extra_locals[name]\n\n def __setitem__(self, name, value):\n f = self._frame\n co = f.f_code\n if name in co._name_to_offset_mapping:\n index = co._name_to_offset_mapping[name]\n kind = co._local_kinds[index]\n if index in co._cells\n cell = f._locals[index]\n cell.cell_contents = val\n else:\n f._locals[index] = val\n else:\n if f._extra_locals is NULL:\n f._extra_locals = {}\n f._extra_locals[name] = val\n\n def __iter__(self):\n f = self._frame\n co = f.f_code\n yield from iter(f._extra_locals)\n for index, name in enumerate(co._variable_names):\n val = f._locals[index]\n if val is NULL:\n continue\n if index in co._cells:\n val = val.cell_contents\n if val is NULL:\n continue\n yield name\n\n def __contains__(self, item):\n f = self._frame\n if item in f._extra_locals:\n return True\n return item in co._variable_names\n\n def __len__(self):\n f = self._frame\n co = f.f_code\n res = 0\n for index, _ in enumerate(co._variable_names):\n val = f._locals[index]\n if val is NULL:\n continue\n if index in co._cells:\n if val.cell_contents is NULL:\n continue\n res += 1\n return len(self._extra_locals) + res\n\u003c/pre\u003e\n\u003ca name=\"user-content-id17\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eC API\u003c/h3\u003e\u003ca id=\"user-content-c-api-1\" class=\"anchor\" aria-label=\"Permalink: C API\" href=\"#c-api-1\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003ePyEval_GetLocals()\u003c/code\u003e will be implemented roughly as follows:\u003c/p\u003e\n\u003cpre\u003ePyObject *PyEval_GetLocals(void) {\n PyFrameObject * = ...; // Get the current frame.\n if (frame-\u0026gt;_locals_cache == NULL) {\n frame-\u0026gt;_locals_cache = PyEval_GetFrameLocals();\n } else {\n PyDict_Update(frame-\u0026gt;_locals_cache, PyFrame_GetLocals(frame));\n }\n return frame-\u0026gt;_locals_cache;\n}\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eAs with all functions that return a borrowed reference, care must be taken to\nensure that the reference is not used beyond the lifetime of the object.\u003c/p\u003e\n\u003ca name=\"user-content-implementation-notes\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eImplementation Notes\u003c/h2\u003e\u003ca id=\"user-content-implementation-notes\" class=\"anchor\" aria-label=\"Permalink: Implementation Notes\" href=\"#implementation-notes\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eWhen accepted, the PEP text suggested that \u003ccode\u003ePyEval_GetLocals\u003c/code\u003e would start returning a\ncached instance of the new write-through proxy, while the implementation sketch indicated\nit would continue to return a dictionary snapshot cached on the frame instance. This\ndiscrepancy was identified while implementing the PEP, and\n\u003ca href=\"https://github.com/python/steering-council/issues/245#issuecomment-2179005461\" data-hovercard-type=\"issue\" data-hovercard-url=\"/python/steering-council/issues/245/hovercard\"\u003eresolved by the Steering Council\u003c/a\u003e\nin favour of retaining the Python 3.12 behaviour of returning a dictionary snapshot\ncached on the frame instance.\nThe PEP text has been updated accordingly.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eDuring the discussions of the C API clarification, it also became apparent that the\nrationale behind \u003ccode\u003elocals()\u003c/code\u003e being updated to return independent snapshots in\n\u003ca href=\"#id18\"\u003e\u003cspan id=\"user-content-id19\"\u003e:term:`optimized scopes \u0026lt;py3.13:optimized scope\u0026gt;`\u003c/span\u003e\u003c/a\u003e wasn't clear, as it had been inherited\nfrom the original \u003ca href=\"http://www.python.org/dev/peps/pep-0558\" rel=\"nofollow\"\u003ePEP 558\u003c/a\u003e discussions rather than being independently covered in this\nPEP. The PEP text has been updated to better cover this change, with additional updates\nto the Specification and Backwards Compatibility sections to cover the impact on code\nexecution APIs that default to executing code in the \u003ccode\u003elocals()\u003c/code\u003e namespace. Additional\nmotivation and rationale details have also been added to \u003ca href=\"http://www.python.org/dev/peps/pep-0558\" rel=\"nofollow\"\u003ePEP 558\u003c/a\u003e.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eIn 3.13.0, the write-through proxies did not allow deletion of even extra variables\nwith \u003ccode\u003edel\u003c/code\u003e and \u003ccode\u003epop()\u003c/code\u003e. This was subsequently reported as a\n\u003ca href=\"https://github.com/python/cpython/issues/125590\" data-hovercard-type=\"issue\" data-hovercard-url=\"/python/cpython/issues/125590/hovercard\"\u003ecompatibility regression\u003c/a\u003e,\nand \u003ca href=\"https://github.com/python/cpython/pull/125616\" data-hovercard-type=\"pull_request\" data-hovercard-url=\"/python/cpython/pull/125616/hovercard\"\u003eresolved\u003c/a\u003e as now described\nin \u003ca href=\"#id20\"\u003e\u003cspan id=\"user-content-id21\"\u003e:ref:`pep-667-f_locals-spec`\u003c/span\u003e\u003c/a\u003e.\u003c/p\u003e\n\u003ca name=\"user-content-comparison-with-pep-558\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eComparison with PEP 558\u003c/h2\u003e\u003ca id=\"user-content-comparison-with-pep-558\" class=\"anchor\" aria-label=\"Permalink: Comparison with PEP 558\" href=\"#comparison-with-pep-558\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThis PEP and \u003ca href=\"http://www.python.org/dev/peps/pep-0558\" rel=\"nofollow\"\u003ePEP 558\u003c/a\u003e shared a common goal:\nto make the semantics of \u003ccode\u003elocals()\u003c/code\u003e and \u003ccode\u003eframe.f_locals()\u003c/code\u003e\nintelligible, and their operation reliable.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThe key difference between this PEP and PEP 558 is that\nPEP 558 attempted to store extra variables inside a full\ninternal dictionary copy of the local variables in an effort\nto improve backwards compatibility with the legacy\n\u003ccode\u003ePyEval_GetLocals()\u003c/code\u003e API, whereas this PEP does not (it stores\nthe extra local variables in a dedicated dictionary accessed\nsolely via the new frame proxy objects, and copies them to the\n\u003ccode\u003ePyEval_GetLocals()\u003c/code\u003e shared dict only when requested).\u003c/p\u003e\n\u003cp dir=\"auto\"\u003ePEP 558 did not specify exactly when that internal copy was\nupdated, making the behavior of PEP 558 impossible to reason\nabout in several cases where this PEP remains well specified.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003ePEP 558 also proposed the introduction of some additional Python\nscope introspection interfaces to the C API that would allow\nextension modules to more easily determine whether the currently\nactive Python scope is optimized or not, and hence whether\nthe C API's \u003ccode\u003elocals()\u003c/code\u003e equivalent returns a direct reference\nto the frame's local execution namespace or a shallow copy of\nthe frame's local variables and nonlocal cell references.\nWhether or not to add such introspection APIs is independent\nof the proposed changes to \u003ccode\u003elocals()\u003c/code\u003e and \u003ccode\u003eframe.f_locals\u003c/code\u003e\nand hence no such proposals have been included in this PEP.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003ePEP 558 was\n\u003ca href=\"#id22\"\u003e\u003cspan id=\"user-content-id23\"\u003e:pep:`ultimately withdrawn \u0026lt;558#pep-withdrawal\u0026gt;`\u003c/span\u003e\u003c/a\u003e\nin favour of this PEP.\u003c/p\u003e\n\u003ca name=\"user-content-reference-implementation\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eReference Implementation\u003c/h2\u003e\u003ca id=\"user-content-reference-implementation\" class=\"anchor\" aria-label=\"Permalink: Reference Implementation\" href=\"#reference-implementation\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe implementation is in development as a \u003ca href=\"https://github.com/python/cpython/pull/115153\" data-hovercard-type=\"pull_request\" data-hovercard-url=\"/python/cpython/pull/115153/hovercard\"\u003edraft pull request on GitHub\u003c/a\u003e.\u003c/p\u003e\n\u003ca name=\"user-content-copyright\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eCopyright\u003c/h2\u003e\u003ca id=\"user-content-copyright\" class=\"anchor\" aria-label=\"Permalink: Copyright\" href=\"#copyright\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThis document is placed in the public domain or under the\nCC0-1.0-Universal license, whichever is more permissive.\u003c/p\u003e\n\n\u003c/article\u003e","renderedFileInfo":null,"shortPath":null,"symbolsEnabled":true,"tabSize":8,"topBannersInfo":{"overridingGlobalFundingFile":false,"globalPreferredFundingPath":"/python/.github/blob/5a0a7cb55767fb3667fe2391bcb66bda638edcb4/FUNDING.yml","showInvalidCitationWarning":false,"citationHelpUrl":"https://docs.github.com/github/creating-cloning-and-archiving-repositories/creating-a-repository-on-github/about-citation-files","actionsOnboardingTip":null},"truncated":false,"viewable":true,"workflowRedirectUrl":null,"symbols":{"timed_out":false,"not_analyzed":true,"symbols":[]}},"copilotInfo":null,"copilotAccessAllowed":false,"modelsAccessAllowed":false,"csrf_tokens":{"/python/peps/branches":{"post":"tsTFXRsxHd9J7KuHRZ_oFypdvTfYIhaxndv7XYtcd7c-Dkj0wPPgAFxa7hY9cORZ2E_ONxnYHH2NaYjbttnaZw"},"/repos/preferences":{"post":"pHx77bfen9-dHjlKcqztAfC35mho43jIAo-2l1YQW0xy1RPT68uvB1PPa9_yNqvO-FXfPFAuJDRuCoCWm8BOgw"}}},"title":"peps/peps/pep-0667.rst at main · python/peps","appPayload":{"helpUrl":"https://docs.github.com","findFileWorkerPath":"/assets-cdn/worker/find-file-worker-9f8a877aa99f.js","findInFileWorkerPath":"/assets-cdn/worker/find-in-file-worker-96e76d5fdb2c.js","githubDevUrl":null,"enabled_features":{"code_nav_ui_events":false,"overview_shared_code_dropdown_button":false,"react_blob_overlay":false,"copilot_conversational_ux_embedding_update":false,"copilot_smell_icebreaker_ux":true,"accessible_code_button":true}}}</script> <div data-target="react-app.reactRoot"><style data-styled="true" data-styled-version="5.3.11">.hOfjFo{padding:0;}/*!sc*/ .oDGAe{max-width:100%;margin-left:auto;margin-right:auto;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;}/*!sc*/ .kowOcT{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:1 1 100%;-ms-flex:1 1 100%;flex:1 1 100%;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;max-width:100%;}/*!sc*/ .gISSDQ{width:100%;}/*!sc*/ @media screen and (min-width:544px){.gISSDQ{width:100%;}}/*!sc*/ @media screen and (min-width:768px){.gISSDQ{width:auto;}}/*!sc*/ .cEmWSE{display:none;-webkit-order:1;-ms-flex-order:1;order:1;width:100%;margin-left:0;margin-right:0;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse;margin-bottom:0;min-width:0;}/*!sc*/ @media screen and (min-width:768px){.cEmWSE{width:auto;margin-top:0 !important;margin-bottom:0 !important;position:-webkit-sticky;position:sticky;top:0px;max-height:100vh !important;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;margin-right:0;height:100vh;}}/*!sc*/ @media print,screen and (max-width:1011px) and (min-width:768px){.cEmWSE{display:none;}}/*!sc*/ .hPvFuC{margin-left:0;margin-right:0;display:none;margin-top:0;}/*!sc*/ @media screen and (min-width:768px){.hPvFuC{margin-left:0 !important;margin-right:0 !important;}}/*!sc*/ .fFSoPl{--pane-min-width:256px;--pane-max-width-diff:511px;--pane-max-width:calc(100vw - var(--pane-max-width-diff));width:100%;padding:0;}/*!sc*/ @media screen and (min-width:544px){}/*!sc*/ @media screen and (min-width:768px){.fFSoPl{width:clamp(var(--pane-min-width),var(--pane-width),var(--pane-max-width));overflow:auto;}}/*!sc*/ @media screen and (min-width:1280px){.fFSoPl{--pane-max-width-diff:959px;}}/*!sc*/ .bTBnTW{height:100%;position:relative;display:none;margin-left:0;}/*!sc*/ .bHLmSv{position:absolute;inset:0 -2px;cursor:col-resize;background-color:transparent;-webkit-transition-delay:0.1s;transition-delay:0.1s;}/*!sc*/ .bHLmSv:hover{background-color:var(--bgColor-neutral-muted,var(--color-neutral-muted,rgba(175,184,193,0.2)));}/*!sc*/ .iKqMNA{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-order:2;-ms-flex-order:2;order:2;-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;-webkit-flex-shrink:1;-ms-flex-negative:1;flex-shrink:1;min-width:1px;margin-right:auto;}/*!sc*/ @media print{.iKqMNA{display:-webkit-box !important;display:-webkit-flex !important;display:-ms-flexbox !important;display:flex !important;}}/*!sc*/ .FxAyp{width:100%;max-width:100%;margin-left:auto;margin-right:auto;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;padding:0;}/*!sc*/ .leYMvG{margin-left:auto;margin-right:auto;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;padding-bottom:40px;max-width:100%;margin-top:0;}/*!sc*/ .KMPzq{display:inherit;}/*!sc*/ .hfKjHv{width:100%;}/*!sc*/ .gZWyZE{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;gap:8px;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;width:100%;}/*!sc*/ .dwYKDk{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:start;-webkit-box-align:start;-ms-flex-align:start;align-items:start;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;gap:8px;}/*!sc*/ .ibcGmb{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:start;-webkit-box-align:start;-ms-flex-align:start;align-items:start;min-width:0;}/*!sc*/ .hKaEJF{display:block;margin-right:8px;}/*!sc*/ @media screen and (min-width:1360px){.hKaEJF{display:block;}}/*!sc*/ .XosP{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;font-size:14px;}/*!sc*/ .bCKfWo[data-size="medium"]{color:var(--fgColor-muted,var(--color-fg-muted,#656d76));padding-left:8px;padding-right:8px;display:none;}/*!sc*/ @media screen and (max-width:768px){.bCKfWo[data-size="medium"]{display:block;}}/*!sc*/ .gUkoLg{-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;}/*!sc*/ .dmxRgG[data-size="medium"]{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;}/*!sc*/ .dmxRgG[data-size="medium"] svg{color:var(--fgColor-muted,var(--color-fg-muted,#656d76));}/*!sc*/ .dmxRgG[data-size="medium"] > span{width:inherit;}/*!sc*/ .bZBlpz{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:100%;}/*!sc*/ .lhTYNA{margin-right:4px;color:var(--fgColor-muted,var(--color-fg-muted,#656d76));}/*!sc*/ .dbrgmi{font-size:14px;min-width:0;max-width:125px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}/*!sc*/ .dHJiml{-webkit-align-self:center;-ms-flex-item-align:center;align-self:center;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;padding-left:8px;padding-right:8px;min-width:0;}/*!sc*/ .cEytCf{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;font-size:16px;min-width:0;-webkit-flex-shrink:1;-ms-flex-negative:1;flex-shrink:1;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;max-width:100%;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}/*!sc*/ .fzFXnm{max-width:100%;}/*!sc*/ .iMnkmv{max-width:100%;list-style:none;display:inline-block;}/*!sc*/ .ghzDag{display:inline-block;max-width:100%;}/*!sc*/ .kHuKdh{font-weight:600;}/*!sc*/ .kgiVEz{font-weight:400;}/*!sc*/ .jGhzSQ{font-weight:600;display:inline-block;max-width:100%;font-size:16px;}/*!sc*/ .faNtbn{min-height:32px;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:start;-webkit-box-align:start;-ms-flex-align:start;align-items:start;}/*!sc*/ .fmQaBv{margin-left:4px;margin-right:4px;}/*!sc*/ .dwNhzn[data-size="medium"][data-no-visuals]{border-top-left-radius:0;border-bottom-left-radius:0;display:none;}/*!sc*/ .fGwBZA[data-size="medium"][data-no-visuals]{color:var(--fgColor-muted,var(--color-fg-muted,#656d76));}/*!sc*/ .dJxjrT{margin-left:16px;margin-right:16px;}/*!sc*/ .eFxKDQ{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;}/*!sc*/ .dzCJzi{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;gap:8px;min-width:273px;padding:8px;}/*!sc*/ @media screen and (min-width:544px){.dzCJzi{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;}}/*!sc*/ .ldRxiI{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;}/*!sc*/ .fVkfyA{width:100%;height:-webkit-fit-content;height:-moz-fit-content;height:fit-content;min-width:0;margin-right:0;}/*!sc*/ .gNAmSV{height:40px;padding-left:4px;padding-bottom:16px;}/*!sc*/ .jNEwzY{-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}/*!sc*/ .bsDwxw{font-size:12px;-webkit-flex:auto;-ms-flex:auto;flex:auto;padding-right:16px;color:var(--fgColor-muted,var(--color-fg-muted,#656d76));min-width:0;}/*!sc*/ .jdLMhu{top:0px;z-index:4;background:var(--bgColor-default,var(--color-canvas-default));position:-webkit-sticky;position:sticky;}/*!sc*/ .tOISc{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;width:100%;position:absolute;}/*!sc*/ .hqwSEx{display:none;min-width:0;padding-top:8px;padding-bottom:8px;}/*!sc*/ .bDVoEr{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;overflow:hidden;margin-left:8px;margin-right:8px;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;width:100%;}/*!sc*/ .kYLlPM{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}/*!sc*/ .gYjEmn{margin-left:4px;margin-right:8px;}/*!sc*/ .kGqOLL{text-overflow:ellipsis;overflow:hidden;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;}/*!sc*/ .fHind{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;font-size:14px;min-width:0;-webkit-flex-shrink:1;-ms-flex-negative:1;flex-shrink:1;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;max-width:100%;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}/*!sc*/ .dnZoUW{font-weight:600;display:inline-block;max-width:100%;font-size:14px;}/*!sc*/ .jRZWlf[data-size="small"]{color:var(--fgColor-default,var(--color-fg-default,#1F2328));margin-left:8px;}/*!sc*/ .kTvpNk{padding-left:8px;padding-top:8px;padding-bottom:8px;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:1;-ms-flex:1;flex:1;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;background-color:var(--bgColor-muted,var(--color-canvas-subtle,#f6f8fa));border:1px solid var(--borderColor-default,var(--color-border-default));border-radius:6px 6px 0px 0px;}/*!sc*/ .iNMjfP{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;gap:8px;min-width:0;}/*!sc*/ .fefCSX{display:block;position:relative;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;margin-top:-1px;margin-bottom:-1px;--separator-color:transparent;}/*!sc*/ .fefCSX:not(:last-child){margin-right:1px;}/*!sc*/ .fefCSX:not(:last-child):after{background-color:var(--separator-color);content:"";position:absolute;right:-2px;top:8px;bottom:8px;width:1px;}/*!sc*/ .fefCSX:focus-within:has(:focus-visible){--separator-color:transparent;}/*!sc*/ .fefCSX:first-child{margin-left:-1px;}/*!sc*/ .fefCSX:last-child{margin-right:-1px;}/*!sc*/ .idgUkN{display:block;position:relative;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;margin-top:-1px;margin-bottom:-1px;--separator-color:var(--borderColor-default,var(--color-border-default,#d0d7de));}/*!sc*/ .idgUkN:not(:last-child){margin-right:1px;}/*!sc*/ .idgUkN:not(:last-child):after{background-color:var(--separator-color);content:"";position:absolute;right:-2px;top:8px;bottom:8px;width:1px;}/*!sc*/ .idgUkN:focus-within:has(:focus-visible){--separator-color:transparent;}/*!sc*/ .idgUkN:first-child{margin-left:-1px;}/*!sc*/ .idgUkN:last-child{margin-right:-1px;}/*!sc*/ .kcLCKF{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;gap:8px;margin-right:8px;}/*!sc*/ .kVWtTz{gap:8px;}/*!sc*/ .gWqxTd{padding-left:8px;padding-right:8px;}/*!sc*/ .gWqxTd linkButtonSx:hover:not([disabled]){-webkit-text-decoration:none;text-decoration:none;}/*!sc*/ .gWqxTd linkButtonSx:focus:not([disabled]){-webkit-text-decoration:none;text-decoration:none;}/*!sc*/ .gWqxTd linkButtonSx:active:not([disabled]){-webkit-text-decoration:none;text-decoration:none;}/*!sc*/ .ivobqY[data-size="small"][data-no-visuals]{border-top-left-radius:0;border-bottom-left-radius:0;}/*!sc*/ .iNRSob[data-size="small"][data-no-visuals]{color:var(--fgColor-muted,var(--color-fg-muted));margin-right:8px;}/*!sc*/ .ffkqe[data-size="small"][data-no-visuals]{color:var(--fgColor-muted,var(--color-fg-muted,#656d76));}/*!sc*/ .hGyMdv{border:1px solid;border-top:none;border-color:var(--borderColor-default,var(--color-border-default,#d0d7de));border-radius:0px 0px 6px 6px;min-width:273px;}/*!sc*/ .fGqKFv{background-color:var(--bgColor-default,var(--color-canvas-default));border:0px;border-width:0;border-radius:0px 0px 6px 6px;padding:0;min-width:0;margin-top:46px;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;}/*!sc*/ .eoaCFS{border-bottom-left-radius:6px;border-bottom-right-radius:6px;padding:32px;min-width:0;}/*!sc*/ .cCoXib{position:fixed;top:0;right:0;height:100%;width:15px;-webkit-transition:-webkit-transform 0.3s;-webkit-transition:transform 0.3s;transition:transform 0.3s;z-index:1;}/*!sc*/ .cCoXib:hover{-webkit-transform:scaleX(1.5);-ms-transform:scaleX(1.5);transform:scaleX(1.5);}/*!sc*/ data-styled.g1[id="Box-sc-g0xbh4-0"]{content:"hOfjFo,oDGAe,kowOcT,gISSDQ,cEmWSE,hPvFuC,fFSoPl,bTBnTW,bHLmSv,iKqMNA,FxAyp,leYMvG,KMPzq,hfKjHv,gZWyZE,dwYKDk,ibcGmb,hKaEJF,XosP,bCKfWo,gUkoLg,dmxRgG,bZBlpz,lhTYNA,dbrgmi,dHJiml,cEytCf,fzFXnm,iMnkmv,ghzDag,kHuKdh,kgiVEz,jGhzSQ,faNtbn,fmQaBv,dwNhzn,fGwBZA,dJxjrT,eFxKDQ,dzCJzi,ldRxiI,fVkfyA,gNAmSV,jNEwzY,bsDwxw,jdLMhu,tOISc,hqwSEx,bDVoEr,kYLlPM,gYjEmn,kGqOLL,fHind,dnZoUW,jRZWlf,kTvpNk,iNMjfP,fefCSX,idgUkN,kcLCKF,kVWtTz,gWqxTd,ivobqY,iNRSob,ffkqe,hGyMdv,fGqKFv,eoaCFS,cCoXib,"}/*!sc*/ .eMMFM{min-width:0;}/*!sc*/ .eMMFM:where([data-size='small']){font-size:var(--text-body-size-small,0.75rem);line-height:var(--text-body-lineHeight-small,1.6666);}/*!sc*/ .eMMFM:where([data-size='medium']){font-size:var(--text-body-size-medium,0.875rem);line-height:var(--text-body-lineHeight-medium,1.4285);}/*!sc*/ .eMMFM:where([data-size='large']){font-size:var(--text-body-size-large,1rem);line-height:var(--text-body-lineHeight-large,1.5);}/*!sc*/ .eMMFM:where([data-weight='light']){font-weight:var(--base-text-weight-light,300);}/*!sc*/ .eMMFM:where([data-weight='normal']){font-weight:var(--base-text-weight-normal,400);}/*!sc*/ .eMMFM:where([data-weight='medium']){font-weight:var(--base-text-weight-medium,500);}/*!sc*/ .eMMFM:where([data-weight='semibold']){font-weight:var(--base-text-weight-semibold,600);}/*!sc*/ .HlHVj{padding-left:4px;padding-right:4px;font-weight:400;color:var(--fgColor-muted,var(--color-fg-muted,#656d76));font-size:16px;}/*!sc*/ .HlHVj:where([data-size='small']){font-size:var(--text-body-size-small,0.75rem);line-height:var(--text-body-lineHeight-small,1.6666);}/*!sc*/ .HlHVj:where([data-size='medium']){font-size:var(--text-body-size-medium,0.875rem);line-height:var(--text-body-lineHeight-medium,1.4285);}/*!sc*/ .HlHVj:where([data-size='large']){font-size:var(--text-body-size-large,1rem);line-height:var(--text-body-lineHeight-large,1.5);}/*!sc*/ .HlHVj:where([data-weight='light']){font-weight:var(--base-text-weight-light,300);}/*!sc*/ .HlHVj:where([data-weight='normal']){font-weight:var(--base-text-weight-normal,400);}/*!sc*/ .HlHVj:where([data-weight='medium']){font-weight:var(--base-text-weight-medium,500);}/*!sc*/ .HlHVj:where([data-weight='semibold']){font-weight:var(--base-text-weight-semibold,600);}/*!sc*/ .lauzFl{padding-left:4px;padding-right:4px;font-weight:400;color:var(--fgColor-muted,var(--color-fg-muted,#656d76));font-size:14px;}/*!sc*/ .lauzFl:where([data-size='small']){font-size:var(--text-body-size-small,0.75rem);line-height:var(--text-body-lineHeight-small,1.6666);}/*!sc*/ .lauzFl:where([data-size='medium']){font-size:var(--text-body-size-medium,0.875rem);line-height:var(--text-body-lineHeight-medium,1.4285);}/*!sc*/ .lauzFl:where([data-size='large']){font-size:var(--text-body-size-large,1rem);line-height:var(--text-body-lineHeight-large,1.5);}/*!sc*/ .lauzFl:where([data-weight='light']){font-weight:var(--base-text-weight-light,300);}/*!sc*/ .lauzFl:where([data-weight='normal']){font-weight:var(--base-text-weight-normal,400);}/*!sc*/ .lauzFl:where([data-weight='medium']){font-weight:var(--base-text-weight-medium,500);}/*!sc*/ .lauzFl:where([data-weight='semibold']){font-weight:var(--base-text-weight-semibold,600);}/*!sc*/ data-styled.g3[id="Text__StyledText-sc-17v1xeu-0"]{content:"eMMFM,HlHVj,lauzFl,"}/*!sc*/ .jkNcAv{border:0;font-size:inherit;font-family:inherit;background-color:transparent;-webkit-appearance:none;color:inherit;width:100%;}/*!sc*/ .jkNcAv:focus{outline:0;}/*!sc*/ data-styled.g13[id="UnstyledTextInput__ToggledUnstyledTextInput-sc-14ypya-0"]{content:"jkNcAv,"}/*!sc*/ .hLzFvi{font-size:14px;line-height:var(--base-size-20);color:var(--fgColor-default,var(--color-fg-default,#1F2328));vertical-align:middle;background-color:var(--bgColor-default,var(--color-canvas-default,#ffffff));border:1px solid var(--control-borderColor-rest,var(--borderColor-default,var(--color-border-default,#d0d7de)));border-radius:6px;outline:none;box-shadow:var(--shadow-inset,var(--color-primer-shadow-inset,inset 0 1px 0 rgba(208,215,222,0.2)));display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-align-items:stretch;-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;min-height:var(--base-size-32);overflow:hidden;--inner-action-size:var(--base-size-24);}/*!sc*/ .hLzFvi input,.hLzFvi textarea{cursor:text;}/*!sc*/ .hLzFvi select{cursor:pointer;}/*!sc*/ .hLzFvi input::-webkit-input-placeholder,.hLzFvi textarea::-webkit-input-placeholder,.hLzFvi select::-webkit-input-placeholder{color:var(---control-fgColor-placeholder,var(--fgColor-muted,var(--color-fg-muted,#656d76)));}/*!sc*/ .hLzFvi input::-moz-placeholder,.hLzFvi textarea::-moz-placeholder,.hLzFvi select::-moz-placeholder{color:var(---control-fgColor-placeholder,var(--fgColor-muted,var(--color-fg-muted,#656d76)));}/*!sc*/ .hLzFvi input:-ms-input-placeholder,.hLzFvi textarea:-ms-input-placeholder,.hLzFvi select:-ms-input-placeholder{color:var(---control-fgColor-placeholder,var(--fgColor-muted,var(--color-fg-muted,#656d76)));}/*!sc*/ .hLzFvi input::placeholder,.hLzFvi textarea::placeholder,.hLzFvi select::placeholder{color:var(---control-fgColor-placeholder,var(--fgColor-muted,var(--color-fg-muted,#656d76)));}/*!sc*/ .hLzFvi:where([data-trailing-action][data-focused]),.hLzFvi:where(:not([data-trailing-action]):focus-within){border-color:var(--fgColor-accent,var(--color-accent-fg,#0969da));outline:2px solid var(--fgColor-accent,var(--color-accent-fg,#0969da));outline-offset:-1px;}/*!sc*/ .hLzFvi > textarea{padding:var(--base-size-12);}/*!sc*/ .hLzFvi:where([data-contrast]){background-color:var(--bgColor-inset,var(--color-canvas-inset,#f6f8fa));}/*!sc*/ .hLzFvi:where([data-disabled]){color:var(--fgColor-disabled,var(--color-primer-fg-disabled,#8c959f));background-color:var(--control-bgColor-disabled,var(--color-input-disabled-bg,rgba(175,184,193,0.2)));box-shadow:none;border-color:var(--control-borderColor-disabled,var(--borderColor-default,var(--color-border-default,#d0d7de)));}/*!sc*/ .hLzFvi:where([data-disabled]) input,.hLzFvi:where([data-disabled]) textarea,.hLzFvi:where([data-disabled]) select{cursor:not-allowed;}/*!sc*/ .hLzFvi:where([data-monospace]){font-family:var(--fontStack-monospace,SFMono-Regular,Consolas,"Liberation Mono",Menlo,Courier,monospace);}/*!sc*/ .hLzFvi:where([data-validation='error']){border-color:var(--borderColor-danger-emphasis,var(--color-danger-emphasis,#cf222e));}/*!sc*/ .hLzFvi:where([data-validation='error']):where([data-trailing-action][data-focused]),.hLzFvi:where([data-validation='error']):where(:not([data-trailing-action])):focus-within{border-color:var(--fgColor-accent,var(--color-accent-fg,#0969da));outline:2px solid var(--fgColor-accent,var(--color-accent-fg,#0969da));outline-offset:-1px;}/*!sc*/ .hLzFvi:where([data-validation='success']){border-color:var(--bgColor-success-emphasis,var(--color-success-emphasis,#1f883d));}/*!sc*/ .hLzFvi:where([data-block]){width:100%;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-self:stretch;-ms-flex-item-align:stretch;align-self:stretch;}/*!sc*/ @media (min-width:768px){.hLzFvi{font-size:var(--text-body-size-medium);}}/*!sc*/ .hLzFvi:where([data-size='small']){--inner-action-size:var(--base-size-20);min-height:var(--base-size-28);padding-top:3px;padding-right:var(--base-size-8);padding-bottom:3px;padding-left:var(--base-size-8);font-size:var(--text-body-size-small);line-height:var(--base-size-20);}/*!sc*/ .hLzFvi:where([data-size='large']){--inner-action-size:var(--base-size-28);height:var(--base-size-40);padding-top:10px;padding-right:var(--base-size-8);padding-bottom:10px;padding-left:var(--base-size-8);}/*!sc*/ .hLzFvi:where([data-variant='small']){min-height:28px;padding-top:3px;padding-right:var(--base-size-8);padding-bottom:3px;padding-left:var(--base-size-8);font-size:(--text-body-size-small);line-height:var(--base-size-20);}/*!sc*/ .hLzFvi:where([data-variant='large']){padding-top:10px;padding-right:var(--base-size-8);padding-bottom:10px;padding-left:var(--base-size-8);font-size:var(--text-title-size-medium);}/*!sc*/ .hLzFvi{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;min-width:160px;}/*!sc*/ data-styled.g14[id="TextInputWrapper__StyledTextInputBaseWrapper-sc-1mqhpbi-0"]{content:"hLzFvi,"}/*!sc*/ .iHYdQq{background-repeat:no-repeat;background-position:right 8px center;padding-right:0;padding-left:0;}/*!sc*/ .iHYdQq > :not(:last-child){margin-right:8px;}/*!sc*/ .iHYdQq .TextInput-icon,.iHYdQq .TextInput-action{-webkit-align-self:center;-ms-flex-item-align:center;align-self:center;color:var(--fgColor-muted,var(--color-fg-muted,#656d76));-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;}/*!sc*/ .iHYdQq > input,.iHYdQq > select{padding-right:0;padding-left:0;}/*!sc*/ .iHYdQq:where([data-leading-visual]){padding-left:var(--base-size-12);}/*!sc*/ .iHYdQq:where([data-trailing-visual]:not([data-trailing-action])){padding-right:var(--base-size-12);}/*!sc*/ .iHYdQq:where(:not([data-leading-visual])) > input,.iHYdQq:where(:not([data-leading-visual])) > select{padding-left:var(--base-size-12);}/*!sc*/ .iHYdQq:where(:not([data-trailing-visual]):not([data-trailing-action])) > input,.iHYdQq:where(:not([data-trailing-visual]):not([data-trailing-action])) > select{padding-right:var(--base-size-12);}/*!sc*/ .iHYdQq{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;min-width:160px;}/*!sc*/ data-styled.g15[id="TextInputWrapper__StyledTextInputWrapper-sc-1mqhpbi-1"]{content:"iHYdQq,"}/*!sc*/ .jOyaRH{display:none;}/*!sc*/ .jOyaRH[popover]{position:absolute;padding:0.5em 0.75em;width:-webkit-max-content;width:-moz-max-content;width:max-content;margin:auto;-webkit-clip:auto;clip:auto;white-space:normal;font:normal normal 11px/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI","Noto Sans",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";-webkit-font-smoothing:subpixel-antialiased;color:var(--tooltip-fgColor,var(--fgColor-onEmphasis,var(--color-fg-on-emphasis,#ffffff)));text-align:center;word-wrap:break-word;background:var(--tooltip-bgColor,var(--bgColor-emphasis,var(--color-neutral-emphasis-plus,#24292f)));border-radius:6px;border:0;opacity:0;max-width:250px;inset:auto;overflow:visible;}/*!sc*/ .jOyaRH[popover]:popover-open{display:block;}/*!sc*/ .jOyaRH[popover].\:popover-open{display:block;}/*!sc*/ @media (forced-colors:active){.jOyaRH{outline:1px solid transparent;}}/*!sc*/ .jOyaRH::after{position:absolute;display:block;right:0;left:0;height:var(--overlay-offset,0.25rem);content:'';}/*!sc*/ .jOyaRH[data-direction='n']::after,.jOyaRH[data-direction='ne']::after,.jOyaRH[data-direction='nw']::after{top:100%;}/*!sc*/ .jOyaRH[data-direction='s']::after,.jOyaRH[data-direction='se']::after,.jOyaRH[data-direction='sw']::after{bottom:100%;}/*!sc*/ .jOyaRH[data-direction='w']::after{position:absolute;display:block;height:100%;width:8px;content:'';bottom:0;left:100%;}/*!sc*/ .jOyaRH[data-direction='e']::after{position:absolute;display:block;height:100%;width:8px;content:'';bottom:0;right:100%;margin-left:-8px;}/*!sc*/ @-webkit-keyframes tooltip-appear{from{opacity:0;}to{opacity:1;}}/*!sc*/ @keyframes tooltip-appear{from{opacity:0;}to{opacity:1;}}/*!sc*/ .jOyaRH:popover-open,.jOyaRH:popover-open::before{-webkit-animation-name:tooltip-appear;animation-name:tooltip-appear;-webkit-animation-duration:0.1s;animation-duration:0.1s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in;-webkit-animation-delay:0s;animation-delay:0s;}/*!sc*/ .jOyaRH.\:popover-open,.jOyaRH.\:popover-open::before{-webkit-animation-name:tooltip-appear;animation-name:tooltip-appear;-webkit-animation-duration:0.1s;animation-duration:0.1s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in;-webkit-animation-delay:0s;animation-delay:0s;}/*!sc*/ data-styled.g16[id="Tooltip__StyledTooltip-sc-e45c7z-0"]{content:"jOyaRH,"}/*!sc*/ .hWlpPn{position:relative;display:inline-block;}/*!sc*/ .hWlpPn::after{position:absolute;z-index:1000000;display:none;padding:0.5em 0.75em;font:normal normal 11px/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI","Noto Sans",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";-webkit-font-smoothing:subpixel-antialiased;color:var(--tooltip-fgColor,var(--fgColor-onEmphasis,var(--color-fg-on-emphasis,#ffffff)));text-align:center;-webkit-text-decoration:none;text-decoration:none;text-shadow:none;text-transform:none;-webkit-letter-spacing:normal;-moz-letter-spacing:normal;-ms-letter-spacing:normal;letter-spacing:normal;word-wrap:break-word;white-space:pre;pointer-events:none;content:attr(aria-label);background:var(--tooltip-bgColor,var(--bgColor-emphasis,var(--color-neutral-emphasis-plus,#24292f)));border-radius:6px;opacity:0;}/*!sc*/ @-webkit-keyframes tooltip-appear{from{opacity:0;}to{opacity:1;}}/*!sc*/ @keyframes tooltip-appear{from{opacity:0;}to{opacity:1;}}/*!sc*/ .hWlpPn:hover::after,.hWlpPn:active::after,.hWlpPn:focus::after,.hWlpPn:focus-within::after{display:inline-block;-webkit-text-decoration:none;text-decoration:none;-webkit-animation-name:tooltip-appear;animation-name:tooltip-appear;-webkit-animation-duration:0.1s;animation-duration:0.1s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in;-webkit-animation-delay:0s;animation-delay:0s;}/*!sc*/ .hWlpPn.tooltipped-no-delay:hover::after,.hWlpPn.tooltipped-no-delay:active::after,.hWlpPn.tooltipped-no-delay:focus::after,.hWlpPn.tooltipped-no-delay:focus-within::after{-webkit-animation-delay:0s;animation-delay:0s;}/*!sc*/ .hWlpPn.tooltipped-multiline:hover::after,.hWlpPn.tooltipped-multiline:active::after,.hWlpPn.tooltipped-multiline:focus::after,.hWlpPn.tooltipped-multiline:focus-within::after{display:table-cell;}/*!sc*/ .hWlpPn.tooltipped-s::after,.hWlpPn.tooltipped-se::after,.hWlpPn.tooltipped-sw::after{top:100%;right:50%;margin-top:6px;}/*!sc*/ .hWlpPn.tooltipped-se::after{right:auto;left:50%;margin-left:-16px;}/*!sc*/ .hWlpPn.tooltipped-sw::after{margin-right:-16px;}/*!sc*/ .hWlpPn.tooltipped-n::after,.hWlpPn.tooltipped-ne::after,.hWlpPn.tooltipped-nw::after{right:50%;bottom:100%;margin-bottom:6px;}/*!sc*/ .hWlpPn.tooltipped-ne::after{right:auto;left:50%;margin-left:-16px;}/*!sc*/ .hWlpPn.tooltipped-nw::after{margin-right:-16px;}/*!sc*/ .hWlpPn.tooltipped-s::after,.hWlpPn.tooltipped-n::after{-webkit-transform:translateX(50%);-ms-transform:translateX(50%);transform:translateX(50%);}/*!sc*/ .hWlpPn.tooltipped-w::after{right:100%;bottom:50%;margin-right:6px;-webkit-transform:translateY(50%);-ms-transform:translateY(50%);transform:translateY(50%);}/*!sc*/ .hWlpPn.tooltipped-e::after{bottom:50%;left:100%;margin-left:6px;-webkit-transform:translateY(50%);-ms-transform:translateY(50%);transform:translateY(50%);}/*!sc*/ .hWlpPn.tooltipped-multiline::after{width:-webkit-max-content;width:-moz-max-content;width:max-content;max-width:250px;word-wrap:break-word;white-space:pre-line;border-collapse:separate;}/*!sc*/ .hWlpPn.tooltipped-multiline.tooltipped-s::after,.hWlpPn.tooltipped-multiline.tooltipped-n::after{right:auto;left:50%;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%);}/*!sc*/ .hWlpPn.tooltipped-multiline.tooltipped-w::after,.hWlpPn.tooltipped-multiline.tooltipped-e::after{right:100%;}/*!sc*/ .hWlpPn.tooltipped-align-right-2::after{right:0;margin-right:0;}/*!sc*/ .hWlpPn.tooltipped-align-left-2::after{left:0;margin-left:0;}/*!sc*/ data-styled.g17[id="Tooltip__TooltipBase-sc-17tf59c-0"]{content:"hWlpPn,"}/*!sc*/ .eAtkQz{display:inline-block;overflow:hidden;text-overflow:ellipsis;vertical-align:top;white-space:nowrap;max-width:125px;max-width:100%;}/*!sc*/ data-styled.g19[id="Truncate__StyledTruncate-sc-23o1d2-0"]{content:"eAtkQz,"}/*!sc*/ .dwImxt{--segmented-control-button-inner-padding:12px;--segmented-control-button-bg-inset:4px;--segmented-control-outer-radius:6px;background-color:transparent;border-color:transparent;border-radius:var(--segmented-control-outer-radius);border-width:0;color:currentColor;cursor:pointer;font-family:inherit;font-size:inherit;font-weight:600;padding:0;height:100%;width:100%;}/*!sc*/ .dwImxt:focus:not(:disabled){box-shadow:none;outline:2px solid var(--fgColor-accent,var(--color-accent-fg,#0969da));outline-offset:-1px;}/*!sc*/ .dwImxt:focus:not(:disabled):not(:focus-visible){outline:solid 1px transparent;}/*!sc*/ .dwImxt:focus-visible:not(:disabled){box-shadow:none;outline:2px solid var(--fgColor-accent,var(--color-accent-fg,#0969da));outline-offset:-1px;}/*!sc*/ .dwImxt .segmentedControl-content{-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;background-color:var(--controlKnob-bgColor-rest,var(--color-segmented-control-button-bg,#ffffff));border-color:var(--controlKnob-borderColor-rest,var(--color-segmented-control-button-hover-active-selected-border,#8c959f));border-style:solid;border-width:1px;border-radius:var(--segmented-control-outer-radius);display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;height:100%;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;padding-left:var(--segmented-control-button-inner-padding);padding-right:var(--segmented-control-button-inner-padding);}/*!sc*/ .dwImxt svg{fill:var(--fgColor-muted,var(--color-fg-muted,#656d76));}/*!sc*/ .dwImxt:focus:focus-visible:not(:last-child):after{width:0;}/*!sc*/ .dwImxt .segmentedControl-text:after{content:"Preview";display:block;font-weight:600;height:0;overflow:hidden;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;visibility:hidden;}/*!sc*/ @media (pointer:coarse){.dwImxt:before{content:"";position:absolute;left:0;right:0;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%);top:50%;min-height:44px;}}/*!sc*/ .iFTkun{--segmented-control-button-inner-padding:12px;--segmented-control-button-bg-inset:4px;--segmented-control-outer-radius:6px;background-color:transparent;border-color:transparent;border-radius:var(--segmented-control-outer-radius);border-width:0;color:currentColor;cursor:pointer;font-family:inherit;font-size:inherit;font-weight:400;padding:var(--segmented-control-button-bg-inset);height:100%;width:100%;}/*!sc*/ .iFTkun:focus:not(:disabled){box-shadow:none;outline:2px solid var(--fgColor-accent,var(--color-accent-fg,#0969da));outline-offset:-1px;}/*!sc*/ .iFTkun:focus:not(:disabled):not(:focus-visible){outline:solid 1px transparent;}/*!sc*/ .iFTkun:focus-visible:not(:disabled){box-shadow:none;outline:2px solid var(--fgColor-accent,var(--color-accent-fg,#0969da));outline-offset:-1px;}/*!sc*/ .iFTkun .segmentedControl-content{-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;background-color:transparent;border-color:transparent;border-style:solid;border-width:1px;border-radius:calc(var(--segmented-control-outer-radius) - var(--segmented-control-button-bg-inset) / 2);display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;height:100%;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;padding-left:calc(var(--segmented-control-button-inner-padding) - var(--segmented-control-button-bg-inset));padding-right:calc(var(--segmented-control-button-inner-padding) - var(--segmented-control-button-bg-inset));}/*!sc*/ .iFTkun svg{fill:var(--fgColor-muted,var(--color-fg-muted,#656d76));}/*!sc*/ .iFTkun:hover .segmentedControl-content{background-color:var(--controlTrack-bgColor-hover,var(--color-segmented-control-button-hover-bg,rgba(175,184,193,0.2)));}/*!sc*/ .iFTkun:active .segmentedControl-content{background-color:var(--controlTrack-bgColor-active,var(--color-segmented-control-button-hover-active-bg,rgba(175,184,193,0.4)));}/*!sc*/ .iFTkun:focus:focus-visible:not(:last-child):after{width:0;}/*!sc*/ .iFTkun .segmentedControl-text:after{content:"Code";display:block;font-weight:600;height:0;overflow:hidden;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;visibility:hidden;}/*!sc*/ @media (pointer:coarse){.iFTkun:before{content:"";position:absolute;left:0;right:0;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%);top:50%;min-height:44px;}}/*!sc*/ .bHmvop{--segmented-control-button-inner-padding:12px;--segmented-control-button-bg-inset:4px;--segmented-control-outer-radius:6px;background-color:transparent;border-color:transparent;border-radius:var(--segmented-control-outer-radius);border-width:0;color:currentColor;cursor:pointer;font-family:inherit;font-size:inherit;font-weight:400;padding:var(--segmented-control-button-bg-inset);height:100%;width:100%;}/*!sc*/ .bHmvop:focus:not(:disabled){box-shadow:none;outline:2px solid var(--fgColor-accent,var(--color-accent-fg,#0969da));outline-offset:-1px;}/*!sc*/ .bHmvop:focus:not(:disabled):not(:focus-visible){outline:solid 1px transparent;}/*!sc*/ .bHmvop:focus-visible:not(:disabled){box-shadow:none;outline:2px solid var(--fgColor-accent,var(--color-accent-fg,#0969da));outline-offset:-1px;}/*!sc*/ .bHmvop .segmentedControl-content{-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;background-color:transparent;border-color:transparent;border-style:solid;border-width:1px;border-radius:calc(var(--segmented-control-outer-radius) - var(--segmented-control-button-bg-inset) / 2);display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;height:100%;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;padding-left:calc(var(--segmented-control-button-inner-padding) - var(--segmented-control-button-bg-inset));padding-right:calc(var(--segmented-control-button-inner-padding) - var(--segmented-control-button-bg-inset));}/*!sc*/ .bHmvop svg{fill:var(--fgColor-muted,var(--color-fg-muted,#656d76));}/*!sc*/ .bHmvop:hover .segmentedControl-content{background-color:var(--controlTrack-bgColor-hover,var(--color-segmented-control-button-hover-bg,rgba(175,184,193,0.2)));}/*!sc*/ .bHmvop:active .segmentedControl-content{background-color:var(--controlTrack-bgColor-active,var(--color-segmented-control-button-hover-active-bg,rgba(175,184,193,0.4)));}/*!sc*/ .bHmvop:focus:focus-visible:not(:last-child):after{width:0;}/*!sc*/ .bHmvop .segmentedControl-text:after{content:"Blame";display:block;font-weight:600;height:0;overflow:hidden;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;visibility:hidden;}/*!sc*/ @media (pointer:coarse){.bHmvop:before{content:"";position:absolute;left:0;right:0;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%);top:50%;min-height:44px;}}/*!sc*/ data-styled.g105[id="SegmentedControlButton__SegmentedControlButtonStyled-sc-8lkgxl-0"]{content:"dwImxt,iFTkun,bHmvop,"}/*!sc*/ .lawgDG{background-color:var(--controlTrack-bgColor-rest,var(--color-segmented-control-bg,#eaeef2));border-radius:6px;border:1px solid;border-color:var(--controlTrack-borderColor-rest,transparent);display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;font-size:14px;height:28px;margin:0;padding:0;}/*!sc*/ data-styled.g107[id="SegmentedControl__SegmentedControlList-sc-1rzig82-0"]{content:"lawgDG,"}/*!sc*/ body[data-page-layout-dragging="true"]{cursor:col-resize;}/*!sc*/ body[data-page-layout-dragging="true"] *{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;}/*!sc*/ data-styled.g108[id="sc-global-gbKrvU1"]{content:"sc-global-gbKrvU1,"}/*!sc*/ </style><meta data-hydrostats="publish"/> <!-- --> <!-- --> <button hidden="" data-testid="header-permalink-button" data-hotkey-scope="read-only-cursor-text-area"></button><button hidden=""></button><div><div style="--sticky-pane-height:100vh;--spacing:var(--spacing-none)" class="Box-sc-g0xbh4-0 hOfjFo"><div class="Box-sc-g0xbh4-0 oDGAe"><div class="Box-sc-g0xbh4-0 kowOcT"><div tabindex="0" class="Box-sc-g0xbh4-0 gISSDQ"><div class="Box-sc-g0xbh4-0 cEmWSE"><div class="Box-sc-g0xbh4-0 hPvFuC"></div><div style="--pane-width:320px" class="Box-sc-g0xbh4-0 fFSoPl"></div><div class="Box-sc-g0xbh4-0 bTBnTW"><div role="slider" aria-label="Draggable pane splitter" aria-valuemin="0" aria-valuemax="0" aria-valuenow="0" aria-valuetext="Pane width 0 pixels" tabindex="0" class="Box-sc-g0xbh4-0 bHLmSv"></div></div></div></div><div class="Box-sc-g0xbh4-0 iKqMNA"><div class="Box-sc-g0xbh4-0"></div><div class="Box-sc-g0xbh4-0 FxAyp"><div data-selector="repos-split-pane-content" tabindex="0" class="Box-sc-g0xbh4-0 leYMvG"><div class="Box-sc-g0xbh4-0 KMPzq"><div class="Box-sc-g0xbh4-0 hfKjHv container"><div class="px-3 pt-3 pb-0" id="StickyHeader"><div class="Box-sc-g0xbh4-0 gZWyZE"><div class="Box-sc-g0xbh4-0 dwYKDk"><div class="Box-sc-g0xbh4-0 ibcGmb react-code-view-header-wrap--narrow"><div class="Box-sc-g0xbh4-0 hKaEJF"><h2 class="Box-sc-g0xbh4-0 XosP prc-Heading-Heading-6CmGO"><button style="--button-color:fg.muted" type="button" aria-label="Expand file tree" data-testid="expand-file-tree-button-mobile" class="Box-sc-g0xbh4-0 bCKfWo prc-Button-ButtonBase-c50BI" data-loading="false" data-size="medium" data-variant="invisible" aria-describedby=":Rld9lab:-loading-announcement"><span data-component="buttonContent" class="Box-sc-g0xbh4-0 gUkoLg prc-Button-ButtonContent-HKbr-"><span data-component="leadingVisual" class="prc-Button-Visual-2epfX prc-Button-VisualWrap-Db-eB"><svg aria-hidden="true" focusable="false" class="octicon octicon-arrow-left" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" style="display:inline-block;user-select:none;vertical-align:text-bottom;overflow:visible"><path d="M7.78 12.53a.75.75 0 0 1-1.06 0L2.47 8.28a.75.75 0 0 1 0-1.06l4.25-4.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042L4.81 7h7.44a.75.75 0 0 1 0 1.5H4.81l2.97 2.97a.75.75 0 0 1 0 1.06Z"></path></svg></span><span data-component="text" class="prc-Button-Label-pTQ3x">Files</span></span></button><span role="tooltip" aria-label="Expand file tree" id="expand-button-file-tree-button" class="Tooltip__TooltipBase-sc-17tf59c-0 hWlpPn tooltipped-se"><button data-component="IconButton" type="button" data-testid="expand-file-tree-button" aria-controls="repos-file-tree" class="prc-Button-ButtonBase-c50BI position-relative ExpandFileTreeButton-module__expandButton--gL4is ExpandFileTreeButton-module__filesButtonBreakpoint--WfX9t fgColor-muted prc-Button-IconButton-szpyj" data-loading="false" data-no-visuals="true" data-size="medium" data-variant="invisible" aria-describedby=":R35d9lab:-loading-announcement" aria-labelledby="expand-button-file-tree-button"><svg aria-hidden="true" focusable="false" class="octicon octicon-sidebar-collapse" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" style="display:inline-block;user-select:none;vertical-align:text-bottom;overflow:visible"><path d="M6.823 7.823a.25.25 0 0 1 0 .354l-2.396 2.396A.25.25 0 0 1 4 10.396V5.604a.25.25 0 0 1 .427-.177Z"></path><path d="M1.75 0h12.5C15.216 0 16 .784 16 1.75v12.5A1.75 1.75 0 0 1 14.25 16H1.75A1.75 1.75 0 0 1 0 14.25V1.75C0 .784.784 0 1.75 0ZM1.5 1.75v12.5c0 .138.112.25.25.25H9.5v-13H1.75a.25.25 0 0 0-.25.25ZM11 14.5h3.25a.25.25 0 0 0 .25-.25V1.75a.25.25 0 0 0-.25-.25H11Z"></path></svg></button></span><button hidden="" data-testid="" data-hotkey-scope="read-only-cursor-text-area"></button></h2></div><div class="react-code-view-header-mb--narrow mr-2"><button type="button" aria-haspopup="true" aria-expanded="false" tabindex="0" aria-label="main branch" data-testid="anchor-button" class="Box-sc-g0xbh4-0 dmxRgG prc-Button-ButtonBase-c50BI ref-selector-class" data-loading="false" data-size="medium" data-variant="default" aria-describedby="branch-picker-repos-header-ref-selector-wide-loading-announcement" id="branch-picker-repos-header-ref-selector-wide"><span data-component="buttonContent" class="Box-sc-g0xbh4-0 gUkoLg prc-Button-ButtonContent-HKbr-"><span data-component="text" class="prc-Button-Label-pTQ3x"><div class="Box-sc-g0xbh4-0 bZBlpz"><div class="Box-sc-g0xbh4-0 lhTYNA"><svg aria-hidden="true" focusable="false" class="octicon octicon-git-branch" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" style="display:inline-block;user-select:none;vertical-align:text-bottom;overflow:visible"><path d="M9.5 3.25a2.25 2.25 0 1 1 3 2.122V6A2.5 2.5 0 0 1 10 8.5H6a1 1 0 0 0-1 1v1.128a2.251 2.251 0 1 1-1.5 0V5.372a2.25 2.25 0 1 1 1.5 0v1.836A2.493 2.493 0 0 1 6 7h4a1 1 0 0 0 1-1v-.628A2.25 2.25 0 0 1 9.5 3.25Zm-6 0a.75.75 0 1 0 1.5 0 .75.75 0 0 0-1.5 0Zm8.25-.75a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5ZM4.25 12a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Z"></path></svg></div><div class="Box-sc-g0xbh4-0 dbrgmi ref-selector-button-text-container"><span class="Text__StyledText-sc-17v1xeu-0 eMMFM"> <!-- -->main</span></div></div></span><span data-component="trailingVisual" class="prc-Button-Visual-2epfX prc-Button-VisualWrap-Db-eB"><svg aria-hidden="true" focusable="false" class="octicon octicon-triangle-down" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" style="display:inline-block;user-select:none;vertical-align:text-bottom;overflow:visible"><path d="m4.427 7.427 3.396 3.396a.25.25 0 0 0 .354 0l3.396-3.396A.25.25 0 0 0 11.396 7H4.604a.25.25 0 0 0-.177.427Z"></path></svg></span></span></button><button hidden="" data-hotkey-scope="read-only-cursor-text-area"></button></div><div class="Box-sc-g0xbh4-0 dHJiml react-code-view-header-mb--narrow"><div class="Box-sc-g0xbh4-0 cEytCf"><nav data-testid="breadcrumbs" aria-labelledby="repos-header-breadcrumb-heading" id="repos-header-breadcrumb" class="Box-sc-g0xbh4-0 fzFXnm"><h2 class="sr-only ScreenReaderHeading-module__userSelectNone--vW4Cq prc-Heading-Heading-6CmGO" data-testid="screen-reader-heading" id="repos-header-breadcrumb-heading">Breadcrumbs</h2><ol class="Box-sc-g0xbh4-0 iMnkmv"><li class="Box-sc-g0xbh4-0 ghzDag"><a class="Box-sc-g0xbh4-0 kHuKdh prc-Link-Link-85e08" sx="[object Object]" data-testid="breadcrumbs-repo-link" href="/python/peps/tree/main">peps</a></li><li class="Box-sc-g0xbh4-0 ghzDag"><span class="Text__StyledText-sc-17v1xeu-0 HlHVj" aria-hidden="true">/</span><a class="Box-sc-g0xbh4-0 kgiVEz prc-Link-Link-85e08" sx="[object Object]" href="/python/peps/tree/main/peps">peps</a></li></ol></nav><div data-testid="breadcrumbs-filename" class="Box-sc-g0xbh4-0 ghzDag"><span class="Text__StyledText-sc-17v1xeu-0 HlHVj" aria-hidden="true">/</span><h1 class="Box-sc-g0xbh4-0 jGhzSQ prc-Heading-Heading-6CmGO" tabindex="-1" id="file-name-id">pep-0667.rst</h1></div><button data-component="IconButton" type="button" class="prc-Button-ButtonBase-c50BI ml-2 prc-Button-IconButton-szpyj" data-loading="false" data-no-visuals="true" data-size="small" data-variant="invisible" aria-describedby=":Rftd9lab:-loading-announcement" aria-labelledby=":R1td9lab:"><svg aria-hidden="true" focusable="false" class="octicon octicon-copy" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" style="display:inline-block;user-select:none;vertical-align:text-bottom;overflow:visible"><path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path></svg></button><span class="Tooltip__StyledTooltip-sc-e45c7z-0 jOyaRH CopyToClipboardButton-module__tooltip--Dq1IB" data-direction="nw" aria-label="Copy path" aria-hidden="true" id=":R1td9lab:">Copy path</span></div></div></div><div class="react-code-view-header-element--wide"><div class="Box-sc-g0xbh4-0 faNtbn"><div class="d-flex gap-2"> <div><div class="Box-sc-g0xbh4-0 fmQaBv"><span class="TextInputWrapper__StyledTextInputBaseWrapper-sc-1mqhpbi-0 hLzFvi TextInputWrapper__StyledTextInputWrapper-sc-1mqhpbi-1 iHYdQq TextInput-wrapper" data-leading-visual="true" data-trailing-visual="true" aria-busy="false"><span class="TextInput-icon" id=":R5j6d9lab:" aria-hidden="true"><svg aria-hidden="true" focusable="false" class="octicon octicon-search" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" style="display:inline-block;user-select:none;vertical-align:text-bottom;overflow:visible"><path d="M10.68 11.74a6 6 0 0 1-7.922-8.982 6 6 0 0 1 8.982 7.922l3.04 3.04a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215ZM11.5 7a4.499 4.499 0 1 0-8.997 0A4.499 4.499 0 0 0 11.5 7Z"></path></svg></span><input type="text" aria-label="Go to file" role="combobox" aria-controls="file-results-list" aria-expanded="false" aria-haspopup="dialog" autoCorrect="off" spellcheck="false" placeholder="Go to file" aria-describedby=":R5j6d9lab: :R5j6d9labH1:" data-component="input" class="UnstyledTextInput__ToggledUnstyledTextInput-sc-14ypya-0 jkNcAv" value=""/><span class="TextInput-icon" id=":R5j6d9labH1:" aria-hidden="true"></span></span></div><button hidden="" data-testid="" data-hotkey-scope="read-only-cursor-text-area"></button><button hidden=""></button></div><button type="button" class="Box-sc-g0xbh4-0 dwNhzn prc-Button-ButtonBase-c50BI" data-loading="false" data-no-visuals="true" data-size="medium" data-variant="default" aria-describedby=":R2l6d9lab:-loading-announcement"><span data-component="buttonContent" class="Box-sc-g0xbh4-0 gUkoLg prc-Button-ButtonContent-HKbr-"><span data-component="text" class="prc-Button-Label-pTQ3x">Blame</span></span></button><button hidden="" data-testid="" data-hotkey-scope="read-only-cursor-text-area"></button><button data-component="IconButton" type="button" aria-label="More file actions" title="More file actions" data-testid="more-file-actions-button-nav-menu-wide" aria-haspopup="true" aria-expanded="false" tabindex="0" class="Box-sc-g0xbh4-0 fGwBZA prc-Button-ButtonBase-c50BI js-blob-dropdown-click prc-Button-IconButton-szpyj" data-loading="false" data-no-visuals="true" data-size="medium" data-variant="default" aria-describedby=":R156d9lab:-loading-announcement" id=":R156d9lab:"><svg aria-hidden="true" focusable="false" class="octicon octicon-kebab-horizontal" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" style="display:inline-block;user-select:none;vertical-align:text-bottom;overflow:visible"><path d="M8 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3ZM1.5 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Zm13 0a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path></svg></button> </div></div></div><div class="react-code-view-header-element--narrow"><div class="Box-sc-g0xbh4-0 faNtbn"><div class="d-flex gap-2"> <button type="button" class="Box-sc-g0xbh4-0 dwNhzn prc-Button-ButtonBase-c50BI" data-loading="false" data-no-visuals="true" data-size="medium" data-variant="default" aria-describedby=":R2l7d9lab:-loading-announcement"><span data-component="buttonContent" class="Box-sc-g0xbh4-0 gUkoLg prc-Button-ButtonContent-HKbr-"><span data-component="text" class="prc-Button-Label-pTQ3x">Blame</span></span></button><button hidden="" data-testid="" data-hotkey-scope="read-only-cursor-text-area"></button><button data-component="IconButton" type="button" aria-label="More file actions" title="More file actions" data-testid="more-file-actions-button-nav-menu-narrow" aria-haspopup="true" aria-expanded="false" tabindex="0" class="Box-sc-g0xbh4-0 fGwBZA prc-Button-ButtonBase-c50BI js-blob-dropdown-click prc-Button-IconButton-szpyj" data-loading="false" data-no-visuals="true" data-size="medium" data-variant="default" aria-describedby=":R157d9lab:-loading-announcement" id=":R157d9lab:"><svg aria-hidden="true" focusable="false" class="octicon octicon-kebab-horizontal" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" style="display:inline-block;user-select:none;vertical-align:text-bottom;overflow:visible"><path d="M8 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3ZM1.5 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Zm13 0a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path></svg></button> </div></div></div></div></div></div></div></div><div class="Box-sc-g0xbh4-0 dJxjrT react-code-view-bottom-padding"> <div class="Box-sc-g0xbh4-0 eFxKDQ"></div> <!-- --> <!-- --> </div><div class="Box-sc-g0xbh4-0 dJxjrT"> <!-- --> <!-- --> <div class="d-flex flex-column border rounded-2 mb-3 pl-1"><div class="Box-sc-g0xbh4-0 dzCJzi"><h2 class="sr-only ScreenReaderHeading-module__userSelectNone--vW4Cq prc-Heading-Heading-6CmGO" data-testid="screen-reader-heading">Latest commit</h2><div style="width:120px" class="Skeleton Skeleton--text" data-testid="loading"> </div><div class="d-flex flex-shrink-0 gap-2"><div data-testid="latest-commit-details" class="d-none d-sm-flex flex-items-center"></div><div class="d-flex gap-2"><h2 class="sr-only ScreenReaderHeading-module__userSelectNone--vW4Cq prc-Heading-Heading-6CmGO" data-testid="screen-reader-heading">History</h2><a href="/python/peps/commits/main/peps/pep-0667.rst" class="prc-Button-ButtonBase-c50BI d-none d-lg-flex LinkButton-module__code-view-link-button--xvCGA flex-items-center fgColor-default" data-loading="false" data-size="small" data-variant="invisible" aria-describedby=":R5dlal9lab:-loading-announcement"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-HKbr-"><span data-component="leadingVisual" class="prc-Button-Visual-2epfX prc-Button-VisualWrap-Db-eB"><svg aria-hidden="true" focusable="false" class="octicon octicon-history" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" style="display:inline-block;user-select:none;vertical-align:text-bottom;overflow:visible"><path d="m.427 1.927 1.215 1.215a8.002 8.002 0 1 1-1.6 5.685.75.75 0 1 1 1.493-.154 6.5 6.5 0 1 0 1.18-4.458l1.358 1.358A.25.25 0 0 1 3.896 6H.25A.25.25 0 0 1 0 5.75V2.104a.25.25 0 0 1 .427-.177ZM7.75 4a.75.75 0 0 1 .75.75v2.992l2.028.812a.75.75 0 0 1-.557 1.392l-2.5-1A.751.751 0 0 1 7 8.25v-3.5A.75.75 0 0 1 7.75 4Z"></path></svg></span><span data-component="text" class="prc-Button-Label-pTQ3x"><span class="fgColor-default">History</span></span></span></a><div class="d-sm-none"></div><div class="d-flex d-lg-none"><span role="tooltip" aria-label="History" id="history-icon-button-tooltip" class="Tooltip__TooltipBase-sc-17tf59c-0 hWlpPn tooltipped-n"><a href="/python/peps/commits/main/peps/pep-0667.rst" class="prc-Button-ButtonBase-c50BI LinkButton-module__code-view-link-button--xvCGA flex-items-center fgColor-default" data-loading="false" data-size="small" data-variant="invisible" aria-describedby=":Rpdlal9lab:-loading-announcement history-icon-button-tooltip"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-HKbr-"><span data-component="leadingVisual" class="prc-Button-Visual-2epfX prc-Button-VisualWrap-Db-eB"><svg aria-hidden="true" focusable="false" class="octicon octicon-history" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" style="display:inline-block;user-select:none;vertical-align:text-bottom;overflow:visible"><path d="m.427 1.927 1.215 1.215a8.002 8.002 0 1 1-1.6 5.685.75.75 0 1 1 1.493-.154 6.5 6.5 0 1 0 1.18-4.458l1.358 1.358A.25.25 0 0 1 3.896 6H.25A.25.25 0 0 1 0 5.75V2.104a.25.25 0 0 1 .427-.177ZM7.75 4a.75.75 0 0 1 .75.75v2.992l2.028.812a.75.75 0 0 1-.557 1.392l-2.5-1A.751.751 0 0 1 7 8.25v-3.5A.75.75 0 0 1 7.75 4Z"></path></svg></span></span></a></span></div></div></div></div></div><div class="Box-sc-g0xbh4-0 ldRxiI"><div class="Box-sc-g0xbh4-0 fVkfyA container"><div class="Box-sc-g0xbh4-0 gNAmSV react-code-size-details-banner"><div class="Box-sc-g0xbh4-0 jNEwzY react-code-size-details-banner"><div class="Box-sc-g0xbh4-0 bsDwxw text-mono"><div title="31.2 KB" data-testid="blob-size" class="Truncate__StyledTruncate-sc-23o1d2-0 eAtkQz"><span>832 lines (644 loc) · 31.2 KB</span></div></div></div></div><div class="Box-sc-g0xbh4-0 jdLMhu react-blob-view-header-sticky" id="repos-sticky-header"><div class="Box-sc-g0xbh4-0 tOISc"><div class="react-blob-sticky-header"><div class="Box-sc-g0xbh4-0 hqwSEx"><div class="Box-sc-g0xbh4-0 bDVoEr"><div class="Box-sc-g0xbh4-0 kYLlPM"><div class="Box-sc-g0xbh4-0 gYjEmn"><button type="button" aria-haspopup="true" aria-expanded="false" tabindex="0" aria-label="main branch" data-testid="anchor-button" class="Box-sc-g0xbh4-0 dmxRgG prc-Button-ButtonBase-c50BI ref-selector-class" data-loading="false" data-size="medium" data-variant="default" aria-describedby="branch-picker-repos-header-ref-selector-loading-announcement" id="branch-picker-repos-header-ref-selector"><span data-component="buttonContent" class="Box-sc-g0xbh4-0 gUkoLg prc-Button-ButtonContent-HKbr-"><span data-component="text" class="prc-Button-Label-pTQ3x"><div class="Box-sc-g0xbh4-0 bZBlpz"><div class="Box-sc-g0xbh4-0 lhTYNA"><svg aria-hidden="true" focusable="false" class="octicon octicon-git-branch" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" style="display:inline-block;user-select:none;vertical-align:text-bottom;overflow:visible"><path d="M9.5 3.25a2.25 2.25 0 1 1 3 2.122V6A2.5 2.5 0 0 1 10 8.5H6a1 1 0 0 0-1 1v1.128a2.251 2.251 0 1 1-1.5 0V5.372a2.25 2.25 0 1 1 1.5 0v1.836A2.493 2.493 0 0 1 6 7h4a1 1 0 0 0 1-1v-.628A2.25 2.25 0 0 1 9.5 3.25Zm-6 0a.75.75 0 1 0 1.5 0 .75.75 0 0 0-1.5 0Zm8.25-.75a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5ZM4.25 12a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Z"></path></svg></div><div class="Box-sc-g0xbh4-0 dbrgmi ref-selector-button-text-container"><span class="Text__StyledText-sc-17v1xeu-0 eMMFM"> <!-- -->main</span></div></div></span><span data-component="trailingVisual" class="prc-Button-Visual-2epfX prc-Button-VisualWrap-Db-eB"><svg aria-hidden="true" focusable="false" class="octicon octicon-triangle-down" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" style="display:inline-block;user-select:none;vertical-align:text-bottom;overflow:visible"><path d="m4.427 7.427 3.396 3.396a.25.25 0 0 0 .354 0l3.396-3.396A.25.25 0 0 0 11.396 7H4.604a.25.25 0 0 0-.177.427Z"></path></svg></span></span></button><button hidden="" data-hotkey-scope="read-only-cursor-text-area"></button></div><div class="Box-sc-g0xbh4-0 kGqOLL"><div class="Box-sc-g0xbh4-0 fHind"><nav data-testid="breadcrumbs" aria-labelledby="sticky-breadcrumb-heading" id="sticky-breadcrumb" class="Box-sc-g0xbh4-0 fzFXnm"><h2 class="sr-only ScreenReaderHeading-module__userSelectNone--vW4Cq prc-Heading-Heading-6CmGO" data-testid="screen-reader-heading" id="sticky-breadcrumb-heading">Breadcrumbs</h2><ol class="Box-sc-g0xbh4-0 iMnkmv"><li class="Box-sc-g0xbh4-0 ghzDag"><a class="Box-sc-g0xbh4-0 kHuKdh prc-Link-Link-85e08" sx="[object Object]" data-testid="breadcrumbs-repo-link" href="/python/peps/tree/main">peps</a></li><li class="Box-sc-g0xbh4-0 ghzDag"><span class="Text__StyledText-sc-17v1xeu-0 lauzFl" aria-hidden="true">/</span><a class="Box-sc-g0xbh4-0 kgiVEz prc-Link-Link-85e08" sx="[object Object]" href="/python/peps/tree/main/peps">peps</a></li></ol></nav><div data-testid="breadcrumbs-filename" class="Box-sc-g0xbh4-0 ghzDag"><span class="Text__StyledText-sc-17v1xeu-0 lauzFl" aria-hidden="true">/</span><h1 class="Box-sc-g0xbh4-0 dnZoUW prc-Heading-Heading-6CmGO" tabindex="-1" id="sticky-file-name-id">pep-0667.rst</h1></div></div></div></div><button style="--button-color:fg.default" type="button" class="Box-sc-g0xbh4-0 jRZWlf prc-Button-ButtonBase-c50BI" data-loading="false" data-size="small" data-variant="invisible" aria-describedby=":Riptal9lab:-loading-announcement"><span data-component="buttonContent" class="Box-sc-g0xbh4-0 gUkoLg prc-Button-ButtonContent-HKbr-"><span data-component="leadingVisual" class="prc-Button-Visual-2epfX prc-Button-VisualWrap-Db-eB"><svg aria-hidden="true" focusable="false" class="octicon octicon-arrow-up" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" style="display:inline-block;user-select:none;vertical-align:text-bottom;overflow:visible"><path d="M3.47 7.78a.75.75 0 0 1 0-1.06l4.25-4.25a.75.75 0 0 1 1.06 0l4.25 4.25a.751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018L9 4.81v7.44a.75.75 0 0 1-1.5 0V4.81L4.53 7.78a.75.75 0 0 1-1.06 0Z"></path></svg></span><span data-component="text" class="prc-Button-Label-pTQ3x">Top</span></span></button></div></div></div><div class="Box-sc-g0xbh4-0 kTvpNk"><h2 class="sr-only ScreenReaderHeading-module__userSelectNone--vW4Cq prc-Heading-Heading-6CmGO" data-testid="screen-reader-heading">File metadata and controls</h2><div class="Box-sc-g0xbh4-0 iNMjfP"><ul aria-label="File view" class="SegmentedControl__SegmentedControlList-sc-1rzig82-0 lawgDG" data-size="small"><li class="Box-sc-g0xbh4-0 fefCSX" data-selected="true"><button aria-current="true" class="SegmentedControlButton__SegmentedControlButtonStyled-sc-8lkgxl-0 dwImxt" type="button"><span class="segmentedControl-content"><div class="Box-sc-g0xbh4-0 segmentedControl-text" data-text="Preview">Preview</div></span></button></li><li class="Box-sc-g0xbh4-0 idgUkN"><button aria-current="false" class="SegmentedControlButton__SegmentedControlButtonStyled-sc-8lkgxl-0 iFTkun" type="button"><span class="segmentedControl-content"><div class="Box-sc-g0xbh4-0 segmentedControl-text" data-text="Code">Code</div></span></button></li><li class="Box-sc-g0xbh4-0 idgUkN"><button aria-current="false" class="SegmentedControlButton__SegmentedControlButtonStyled-sc-8lkgxl-0 bHmvop" type="button"><span class="segmentedControl-content"><div class="Box-sc-g0xbh4-0 segmentedControl-text" data-text="Blame">Blame</div></span></button></li></ul><button hidden="" data-testid="" data-hotkey-scope="read-only-cursor-text-area"></button><button hidden="" data-testid="" data-hotkey-scope="read-only-cursor-text-area"></button><button hidden="" data-testid="" data-hotkey-scope="read-only-cursor-text-area"></button><div class="Box-sc-g0xbh4-0 jNEwzY react-code-size-details-in-header"><div class="Box-sc-g0xbh4-0 bsDwxw text-mono"><div title="31.2 KB" data-testid="blob-size" class="Truncate__StyledTruncate-sc-23o1d2-0 eAtkQz"><span>832 lines (644 loc) · 31.2 KB</span></div></div></div></div><div class="Box-sc-g0xbh4-0 kcLCKF"><div class="Box-sc-g0xbh4-0 kVWtTz react-blob-header-edit-and-raw-actions"><div class="Box-sc-g0xbh4-0 prc-ButtonGroup-ButtonGroup-vcMeG"><div><a href="https://github.com/python/peps/raw/refs/heads/main/peps/pep-0667.rst" data-testid="raw-button" class="Box-sc-g0xbh4-0 gWqxTd prc-Button-ButtonBase-c50BI" data-loading="false" data-no-visuals="true" data-size="small" data-variant="default" aria-describedby=":R5csptal9lab:-loading-announcement"><span data-component="buttonContent" class="Box-sc-g0xbh4-0 gUkoLg prc-Button-ButtonContent-HKbr-"><span data-component="text" class="prc-Button-Label-pTQ3x">Raw</span></span></a></div><div><button data-component="IconButton" type="button" aria-label="Copy raw content" data-testid="copy-raw-button" class="prc-Button-ButtonBase-c50BI prc-Button-IconButton-szpyj" data-loading="false" data-no-visuals="true" data-size="small" data-variant="default" aria-describedby=":Rpcsptal9lab:-loading-announcement"><svg aria-hidden="true" focusable="false" class="octicon octicon-copy" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" style="display:inline-block;user-select:none;vertical-align:text-bottom;overflow:visible"><path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path></svg></button></div><div><span role="tooltip" aria-label="Download raw file" id=":Rdcsptal9lab:" class="Tooltip__TooltipBase-sc-17tf59c-0 hWlpPn tooltipped-n"><button data-component="IconButton" type="button" aria-label="Download raw content" data-testid="download-raw-button" class="Box-sc-g0xbh4-0 ivobqY prc-Button-ButtonBase-c50BI prc-Button-IconButton-szpyj" data-loading="false" data-no-visuals="true" data-size="small" data-variant="default" aria-describedby=":Rtcsptal9lab:-loading-announcement"><svg aria-hidden="true" focusable="false" class="octicon octicon-download" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" style="display:inline-block;user-select:none;vertical-align:text-bottom;overflow:visible"><path d="M2.75 14A1.75 1.75 0 0 1 1 12.25v-2.5a.75.75 0 0 1 1.5 0v2.5c0 .138.112.25.25.25h10.5a.25.25 0 0 0 .25-.25v-2.5a.75.75 0 0 1 1.5 0v2.5A1.75 1.75 0 0 1 13.25 14Z"></path><path d="M7.25 7.689V2a.75.75 0 0 1 1.5 0v5.689l1.97-1.969a.749.749 0 1 1 1.06 1.06l-3.25 3.25a.749.749 0 0 1-1.06 0L4.22 6.78a.749.749 0 1 1 1.06-1.06l1.97 1.969Z"></path></svg></button></span></div></div><button hidden="" data-testid="raw-button-shortcut" data-hotkey-scope="read-only-cursor-text-area"></button><button hidden="" data-testid="copy-raw-button-shortcut" data-hotkey-scope="read-only-cursor-text-area"></button><button hidden="" data-testid="download-raw-button-shortcut" data-hotkey-scope="read-only-cursor-text-area"></button></div><button data-component="IconButton" type="button" aria-label="Outline" aria-pressed="false" class="Box-sc-g0xbh4-0 iNRSob prc-Button-ButtonBase-c50BI prc-Button-IconButton-szpyj" data-loading="false" data-no-visuals="true" data-size="small" data-variant="invisible" aria-describedby=":R6sptal9lab:-loading-announcement"><svg aria-hidden="true" focusable="false" class="octicon octicon-list-unordered" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" style="display:inline-block;user-select:none;vertical-align:text-bottom;overflow:visible"><path d="M5.75 2.5h8.5a.75.75 0 0 1 0 1.5h-8.5a.75.75 0 0 1 0-1.5Zm0 5h8.5a.75.75 0 0 1 0 1.5h-8.5a.75.75 0 0 1 0-1.5Zm0 5h8.5a.75.75 0 0 1 0 1.5h-8.5a.75.75 0 0 1 0-1.5ZM2 14a1 1 0 1 1 0-2 1 1 0 0 1 0 2Zm1-6a1 1 0 1 1-2 0 1 1 0 0 1 2 0ZM2 4a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"></path></svg></button><div class="react-blob-header-edit-and-raw-actions-combined"><button data-component="IconButton" type="button" aria-label="Edit and raw actions" title="More file actions" data-testid="more-file-actions-button" aria-haspopup="true" aria-expanded="false" tabindex="0" class="Box-sc-g0xbh4-0 ffkqe prc-Button-ButtonBase-c50BI js-blob-dropdown-click prc-Button-IconButton-szpyj" data-loading="false" data-no-visuals="true" data-size="small" data-variant="invisible" aria-describedby=":Rnsptal9lab:-loading-announcement" id=":Rnsptal9lab:"><svg aria-hidden="true" focusable="false" class="octicon octicon-kebab-horizontal" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" style="display:inline-block;user-select:none;vertical-align:text-bottom;overflow:visible"><path d="M8 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3ZM1.5 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Zm13 0a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path></svg></button></div></div></div></div><div></div></div><div class="Box-sc-g0xbh4-0 hGyMdv"><section aria-labelledby="file-name-id-wide file-name-id-mobile" class="Box-sc-g0xbh4-0 fGqKFv"><div class="Box-sc-g0xbh4-0 eoaCFS js-snippet-clipboard-copy-unpositioned undefined" data-hpc="true"><article class="markdown-body entry-content container-lg" itemprop="text"><p dir="auto">PEP: 667 Title: Consistent views of namespaces Author: Mark Shannon <<a href="mailto:mark@hotpy.org">mark@hotpy.org</a>>,</p> <blockquote> Tian Gao <<a href="mailto:gaogaotiantian@hotmail.com">gaogaotiantian@hotmail.com</a>></blockquote> <p dir="auto">Discussions-To: <a href="https://discuss.python.org/t/46631" rel="nofollow">https://discuss.python.org/t/46631</a> Status: Final Type: Standards Track Created: 30-Jul-2021 Python-Version: 3.13 Post-History: 20-Aug-2021, 22-Feb-2024 Resolution: <a href="https://discuss.python.org/t/46631/25" rel="nofollow">25-Apr-2024</a></p> <pre>.. canonical-doc:: :external+py3.13:func:`locals` </pre> <a name="user-content-abstract"></a> <div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Abstract</h2><a id="user-content-abstract" class="anchor" aria-label="Permalink: Abstract" href="#abstract"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">In early versions of Python all namespaces, whether in functions, classes or modules, were all implemented the same way: as a dictionary.</p> <p dir="auto">For performance reasons, the implementation of function namespaces was changed. Unfortunately this meant that accessing these namespaces through <code>locals()</code> and <code>frame.f_locals</code> ceased to be consistent and some odd bugs crept in over the years as threads, generators and coroutines were added.</p> <p dir="auto">This PEP proposes making these namespaces consistent once more. Modifications to <code>frame.f_locals</code> will always be visible in the underlying variables. Modifications to local variables will immediately be visible in <code>frame.f_locals</code>, and they will be consistent regardless of threading or coroutines.</p> <p dir="auto">The <code>locals()</code> function will act the same as it does now for class and modules scopes. For function scopes it will return an instantaneous snapshot of the underlying <code>frame.f_locals</code> rather than implicitly refreshing a single shared dictionary cached on the frame object.</p> <a name="user-content-motivation"></a> <div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Motivation</h2><a id="user-content-motivation" class="anchor" aria-label="Permalink: Motivation" href="#motivation"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">The implementation of <code>locals()</code> and <code>frame.f_locals</code> in releases up to and including Python 3.12 is slow, inconsistent and buggy. We want to make it faster, consistent, and most importantly fix the bugs.</p> <p dir="auto">For example, when attempting to manipulate local variables via frame objects:</p> <pre>class C: x = 1 sys._getframe().f_locals['x'] = 2 print(x) </pre> <p dir="auto">prints <code>2</code>, but:</p> <pre>def f(): x = 1 sys._getframe().f_locals['x'] = 2 print(x) f() </pre> <p dir="auto">prints <code>1</code>.</p> <p dir="auto">This is inconsistent, and confusing. Worse than that, the Python 3.12 behavior can result in strange <a href="https://github.com/python/cpython/issues/74929" data-hovercard-type="issue" data-hovercard-url="/python/cpython/issues/74929/hovercard">bugs</a>.</p> <p dir="auto">With this PEP both examples would print <code>2</code> as the function level change would be written directly to the optimized local variables in the frame rather than to a cached dictionary snapshot.</p> <p dir="auto">There are no compensating advantages for the Python 3.12 behavior; it is unreliable and slow.</p> <p dir="auto">The <code>locals()</code> builtin has its own undesirable behaviours. Refer to <a href="http://www.python.org/dev/peps/pep-0558" rel="nofollow">PEP 558</a> for additional details on those concerns.</p> <a name="user-content-rationale"></a> <div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Rationale</h2><a id="user-content-rationale" class="anchor" aria-label="Permalink: Rationale" href="#rationale"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <a name="user-content-making-the-frame-f-locals-attribute-a-write-through-proxy"></a> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Making the <code>frame.f_locals</code> attribute a write-through proxy</h3><a id="user-content-making-the-framef_locals-attribute-a-write-through-proxy" class="anchor" aria-label="Permalink: Making the frame.f_locals attribute a write-through proxy" href="#making-the-framef_locals-attribute-a-write-through-proxy"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">The Python 3.12 implementation of <code>frame.f_locals</code> returns a dictionary that is created on the fly from the array of local variables. The <code>PyFrame_LocalsToFast()</code> C API is then called by debuggers and trace functions that want to write their changes back to the array (until Python 3.11, this API was called implicitly after every trace function invocation rather than being called explicitly by the trace functions).</p> <p dir="auto">This can result in the array and dictionary getting out of sync with each other. Writes to the <code>f_locals</code> frame attribute may not show up as modifications to local variables if <code>PyFrame_LocalsToFast()</code> is never called. Writes to local variables can get lost if a dictionary snapshot created before the variables were modified is written back to the frame (since <em>every</em> known variable stored in the snapshot is written back to the frame, even if the value stored on the frame had changed since the snapshot was taken).</p> <p dir="auto">By making <code>frame.f_locals</code> return a view on the underlying frame, these problems go away. <code>frame.f_locals</code> is always in sync with the frame because it is a view of it, not a copy of it.</p> <a name="user-content-making-the-locals-builtin-return-independent-snapshots"></a> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Making the <code>locals()</code> builtin return independent snapshots</h3><a id="user-content-making-the-locals-builtin-return-independent-snapshots" class="anchor" aria-label="Permalink: Making the locals() builtin return independent snapshots" href="#making-the-locals-builtin-return-independent-snapshots"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto"><a href="http://www.python.org/dev/peps/pep-0558" rel="nofollow">PEP 558</a> considered three potential options for standardising the behavior of the <code>locals()</code> builtin in <a href="#id1"><span id="user-content-id2">:term:`optimized scopes <py3.13:optimized scope>`</span></a>:</p> <ul dir="auto"> <li>retain the historical behaviour of having each call to <code>locals()</code> on a given frame update a single shared snapshot of the local variables</li> <li>make <code>locals()</code> return write-through proxy instances (similar to <code>frame.f_locals</code>)</li> <li>make <code>locals()</code> return genuinely independent snapshots so that attempts to change the values of local variables via <code>exec()</code> would be <em>consistently</em> ignored rather than being accepted in some circumstances</li> </ul> <p dir="auto">The last option was chosen as the one which could most easily be explained in the language reference, and memorised by users:</p> <ul dir="auto"> <li>the <code>locals()</code> builtin gives an instantaneous snapshot of the local variables in optimized scopes, and read/write access in other scopes; and</li> <li><code>frame.f_locals</code> gives read/write access to the local variables in all scopes, including optimized scopes</li> </ul> <p dir="auto">This approach allows the intent of a piece of code to be clearer than it would be if both APIs granted full read/write access in optimized scopes, even when write access wasn't needed or desired. For additional details on this design decision, refer to <a href="http://www.python.org/dev/peps/pep-0558" rel="nofollow">PEP 558</a>, especially the <a href="#id3"><span id="user-content-id4">:ref:`pep-558-motivation`</span></a> section and <a href="#id5"><span id="user-content-id6">:ref:`pep-558-exec-eval-impact`</span></a>.</p> <p dir="auto">This approach is not without its drawbacks, which are covered in the Backwards Compatibility section below.</p> <a name="user-content-specification"></a> <div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Specification</h2><a id="user-content-specification" class="anchor" aria-label="Permalink: Specification" href="#specification"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <a name="user-content-python-api"></a> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Python API</h3><a id="user-content-python-api" class="anchor" aria-label="Permalink: Python API" href="#python-api"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <a name="user-content-the-frame-f-locals-attribute"></a> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">The <code>frame.f_locals</code> attribute</h4><a id="user-content-the-framef_locals-attribute" class="anchor" aria-label="Permalink: The frame.f_locals attribute" href="#the-framef_locals-attribute"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">For module and class scopes (including <code>exec()</code> and <code>eval()</code> invocations), <code>frame.f_locals</code> is a direct reference to the local variable namespace used in code execution.</p> <p dir="auto">For function scopes (and other <a href="#id7"><span id="user-content-id8">:term:`optimized scopes <py3.13:optimized scope>`</span></a>) it will be an instance of a new write-through proxy type that can directly modify the optimized local variable storage array in the underlying frame, as well as the contents of any cell references to non-local variables.</p> <p dir="auto">The view objects fully implement the <code>collections.abc.Mapping</code> interface, and also implement the following mutable mapping operations:</p> <ul dir="auto"> <li>using assignment to add new key/value pairs</li> <li>using assignment to update the value associated with a key</li> <li>conditional assignment via the <code>setdefault()</code> method</li> <li>bulk updates via the <code>update()</code> method</li> </ul> <p dir="auto">Views of different frames compare unequal even if they have the same contents.</p> <p dir="auto">All writes to the <code>f_locals</code> mapping will be immediately visible in the underlying variables. All changes to the underlying variables will be immediately visible in the mapping.</p> <p dir="auto">The <code>f_locals</code> object will be a full mapping, and can have arbitrary key-value pairs added to it. New names added via the proxies will be stored in a dedicated shared dictionary stored on the underlying frame object (so all proxy instances for a given frame will be able to access any names added this way).</p> <p dir="auto">Extra keys (which do not correspond to local variables on the underlying frame) may be removed as usual with <code>del</code> statements or the <code>pop()</code> method.</p> <p dir="auto">Using <code>del</code>, or the <code>pop()</code> method, to remove keys that correspond to local variables on the underlying frame is NOT supported, and attempting to do so will raise <code>ValueError</code>. Local variables can only be set to <code>None</code> (or some other value) via the proxy, they cannot be unbound completely.</p> <p dir="auto">The <code>clear()</code> method is NOT implemented on the write-through proxies, as it is unclear how it should handle the inability to delete entries corresponding to local variables.</p> <p dir="auto">To maintain backwards compatibility, proxy APIs that need to produce a new mapping (such as <code>copy()</code>) will produce regular builtin <code>dict</code> instances, rather than write-through proxy instances.</p> <p dir="auto">To avoid introducing a circular reference between frame objects and the write-through proxies, each access to <code>frame.f_locals</code> returns a <em>new</em> write-through proxy instance.</p> <a name="user-content-the-locals-builtin"></a> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">The <code>locals()</code> builtin</h4><a id="user-content-the-locals-builtin" class="anchor" aria-label="Permalink: The locals() builtin" href="#the-locals-builtin"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto"><code>locals()</code> will be defined as:</p> <pre>def locals(): frame = sys._getframe(1) f_locals = frame.f_locals if frame._is_optimized(): # Not an actual frame method f_locals = dict(f_locals) return f_locals </pre> <p dir="auto">For module and class scopes (including <code>exec()</code> and <code>eval()</code> invocations), <code>locals()</code> continues to return a direct reference to the local variable namespace used in code execution (which is also the same value reported by <code>frame.f_locals</code>).</p> <p dir="auto">In <a href="#id9"><span id="user-content-id10">:term:`optimized scopes <py3.13:optimized scope>`</span></a>, each call to <code>locals()</code> will produce an <em>independent</em> snapshot of the local variables.</p> <a name="user-content-the-eval-and-exec-builtins"></a> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">The <code>eval()</code> and <code>exec()</code> builtins</h4><a id="user-content-the-eval-and-exec-builtins" class="anchor" aria-label="Permalink: The eval() and exec() builtins" href="#the-eval-and-exec-builtins"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">Because this PEP changes the behavior of <code>locals()</code>, the behavior of <code>eval()</code> and <code>exec()</code> also changes.</p> <p dir="auto">Assuming a function <code>_eval()</code> which performs the job of <code>eval()</code> with explicit namespace arguments, <code>eval()</code> can be defined as follows:</p> <pre>FrameProxyType = type((lambda: sys._getframe().f_locals)()) def eval(expression, /, globals=None, locals=None): if globals is None: # No globals -> use calling frame's globals _calling_frame = sys._getframe(1) globals = _calling_frame.f_globals if locals is None: # No globals or locals -> use calling frame's locals locals = _calling_frame.f_locals if isinstance(locals, FrameProxyType): # Align with locals() builtin in optimized frame locals = dict(locals) elif locals is None: # Globals but no locals -> use same namespace for both locals = globals return _eval(expression, globals, locals) </pre> <p dir="auto">The specified argument handling for <code>exec()</code> is similarly updated.</p> <p dir="auto">(In Python 3.12 and earlier, it was not possible to provide <code>locals</code> to <code>eval()</code> or <code>exec()</code> without also providing <code>globals</code> as these were previously positional-only arguments. Independently of this PEP, Python 3.13 updated these builtins to accept keyword arguments)</p> <a name="user-content-c-api"></a> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">C API</h3><a id="user-content-c-api" class="anchor" aria-label="Permalink: C API" href="#c-api"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <a name="user-content-additions-to-the-pyeval-c-api"></a> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">Additions to the <code>PyEval</code> C API</h4><a id="user-content-additions-to-the-pyeval-c-api" class="anchor" aria-label="Permalink: Additions to the PyEval C API" href="#additions-to-the-pyeval-c-api"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">Three new C-API functions will be added:</p> <pre>PyObject *PyEval_GetFrameLocals(void) PyObject *PyEval_GetFrameGlobals(void) PyObject *PyEval_GetFrameBuiltins(void) </pre> <p dir="auto"><code>PyEval_GetFrameLocals()</code> is equivalent to: <code>locals()</code>. <code>PyEval_GetFrameGlobals()</code> is equivalent to: <code>globals()</code>.</p> <p dir="auto">All of these functions will return a new reference.</p> <a name="user-content-pyframe-getlocals-c-api"></a> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto"><code>PyFrame_GetLocals</code> C API</h4><a id="user-content-pyframe_getlocals-c-api" class="anchor" aria-label="Permalink: PyFrame_GetLocals C API" href="#pyframe_getlocals-c-api"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">The existing <code>PyFrame_GetLocals(f)</code> C API is equivalent to <code>f.f_locals</code>. Its return value will be as described above for accessing <code>f.f_locals</code>.</p> <p dir="auto">This function returns a new reference, so it is able to accommodate the creation of a new write-through proxy instance on each call in an optimized scope.</p> <a name="user-content-deprecated-c-apis"></a> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">Deprecated C APIs</h4><a id="user-content-deprecated-c-apis" class="anchor" aria-label="Permalink: Deprecated C APIs" href="#deprecated-c-apis"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">The following C API functions will be deprecated, as they return borrowed references:</p> <pre>PyEval_GetLocals() PyEval_GetGlobals() PyEval_GetBuiltins() </pre> <p dir="auto">The following functions (which return new references) should be used instead:</p> <pre>PyEval_GetFrameLocals() PyEval_GetFrameGlobals() PyEval_GetFrameBuiltins() </pre> <p dir="auto">The following C API functions will become no-ops, and will be deprecated without replacement:</p> <pre>PyFrame_FastToLocalsWithError() PyFrame_FastToLocals() PyFrame_LocalsToFast() </pre> <p dir="auto">All of the deprecated functions will be marked as deprecated in the Python 3.13 documentation.</p> <p dir="auto">Of these functions, only <code>PyEval_GetLocals()</code> poses any significant maintenance burden. Accordingly, calls to <code>PyEval_GetLocals()</code> will emit <code>DeprecationWarning</code> in Python 3.14, with a target removal date of Python 3.16 (two releases after Python 3.14). Alternatives are recommended as described in <a href="#id11"><span id="user-content-id12">:ref:`pep-667-pyeval-getlocals-compatibility`</span></a>.</p> <a name="user-content-summary-of-changes"></a> <div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Summary of Changes</h2><a id="user-content-summary-of-changes" class="anchor" aria-label="Permalink: Summary of Changes" href="#summary-of-changes"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">This section summarises how the specified behaviour in Python 3.13 and later differs from the historical behaviour in Python 3.12 and earlier versions.</p> <a name="user-content-python-api-changes"></a> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Python API changes</h3><a id="user-content-python-api-changes" class="anchor" aria-label="Permalink: Python API changes" href="#python-api-changes"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <a name="user-content-frame-f-locals-changes"></a> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto"><code>frame.f_locals</code> changes</h4><a id="user-content-framef_locals-changes" class="anchor" aria-label="Permalink: frame.f_locals changes" href="#framef_locals-changes"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">Consider the following example:</p> <pre>def l(): "Get the locals of caller" return sys._getframe(1).f_locals def test(): if 0: y = 1 # Make 'y' a local variable x = 1 l()['x'] = 2 l()['y'] = 4 l()['z'] = 5 y print(locals(), x) </pre> <p dir="auto">Given the changes in this PEP, <code>test()</code> will print <code>{'x': 2, 'y': 4, 'z': 5} 2</code>.</p> <p dir="auto">In Python 3.12, this example will fail with an <code>UnboundLocalError</code>, as the definition of <code>y</code> by <code>l()['y'] = 4</code> is lost.</p> <p dir="auto">If the second-to-last line were changed from <code>y</code> to <code>z</code>, this will still raise <code>NameError</code>, as it does in Python 3.12. Keys added to <code>frame.f_locals</code> that are not lexically local variables remain visible in <code>frame.f_locals</code>, but do not dynamically become local variables.</p> <a name="user-content-locals-changes"></a> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto"><code>locals()</code> changes</h4><a id="user-content-locals-changes" class="anchor" aria-label="Permalink: locals() changes" href="#locals-changes"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">Consider the following example:</p> <pre>def f(): exec("x = 1") print(locals().get("x")) f() </pre> <p dir="auto">Given the changes in this PEP, this will <em>always</em> print <code>None</code> (regardless of whether <code>x</code> is a defined local variable in the function), as the explicit call to <code>locals()</code> produces a distinct snapshot from the one implicitly used in the <code>exec()</code> call.</p> <p dir="auto">In Python 3.12, the exact example shown would print <code>1</code>, but seemingly unrelated changes to the definition of the function involved could make it print <code>None</code> instead (<a href="#id13"><span id="user-content-id14">:ref:`pep-558-exec-eval-impact`</span></a> in PEP 558 goes into more detail on that topic).</p> <a name="user-content-eval-and-exec-changes"></a> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto"><code>eval()</code> and <code>exec()</code> changes</h4><a id="user-content-eval-and-exec-changes" class="anchor" aria-label="Permalink: eval() and exec() changes" href="#eval-and-exec-changes"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">The primary change affecting <code>eval()</code> and <code>exec()</code> is shown in the "<a href="#id15"><span id="user-content-id16">:ref:`pep-667-locals-changes`</span></a>" example: repeatedly accessing <code>locals()</code> in an optimized scope will no longer implicitly share a common underlying namespace.</p> <a name="user-content-c-api-changes"></a> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">C API changes</h3><a id="user-content-c-api-changes" class="anchor" aria-label="Permalink: C API changes" href="#c-api-changes"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <a name="user-content-pyframe-getlocals-change"></a> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto"><code>PyFrame_GetLocals</code> change</h4><a id="user-content-pyframe_getlocals-change" class="anchor" aria-label="Permalink: PyFrame_GetLocals change" href="#pyframe_getlocals-change"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto"><code>PyFrame_GetLocals</code> can already return arbitrary mappings in Python 3.12, as <code>exec()</code> and <code>eval()</code> accept arbitrary mappings as their <code>locals</code> argument, and metaclasses may return arbitrary mappings from their <code>__prepare__</code> methods.</p> <p dir="auto">Returning a frame locals proxy in optimized scopes just adds another case where something other than a builtin dictionary will be returned.</p> <a name="user-content-pyeval-getlocals-change"></a> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto"><code>PyEval_GetLocals</code> change</h4><a id="user-content-pyeval_getlocals-change" class="anchor" aria-label="Permalink: PyEval_GetLocals change" href="#pyeval_getlocals-change"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">The semantics of <code>PyEval_GetLocals()</code> are technically unchanged, but they do change in practice as the dictionary cached on optimized frames is no longer shared with other mechanisms for accessing the frame locals (<code>locals()</code> builtin, <code>PyFrame_GetLocals</code> function, frame <code>f_locals</code> attributes).</p> <a name="user-content-backwards-compatibility"></a> <div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Backwards Compatibility</h2><a id="user-content-backwards-compatibility" class="anchor" aria-label="Permalink: Backwards Compatibility" href="#backwards-compatibility"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <a name="user-content-python-api-compatibility"></a> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Python API compatibility</h3><a id="user-content-python-api-compatibility" class="anchor" aria-label="Permalink: Python API compatibility" href="#python-api-compatibility"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">The implementation used in versions up to and including Python 3.12 has many corner cases and oddities. Code that works around those may need to be changed. Code that uses <code>locals()</code> for simple templating, or print debugging, will continue to work correctly. Debuggers and other tools that use <code>f_locals</code> to modify local variables, will now work correctly, even in the presence of threaded code, coroutines and generators.</p> <a name="user-content-frame-f-locals-compatibility"></a> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto"><code>frame.f_locals</code> compatibility</h3><a id="user-content-framef_locals-compatibility" class="anchor" aria-label="Permalink: frame.f_locals compatibility" href="#framef_locals-compatibility"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">Although <code>f.f_locals</code> behaves as if it were the namespace of the function, there will be some observable differences. For example, <code>f.f_locals is f.f_locals</code> will be <code>False</code> for optimized frames, as each access to the attribute produces a new write-through proxy instance.</p> <p dir="auto">However <code>f.f_locals == f.f_locals</code> will be <code>True</code>, and all changes to the underlying variables, by any means, including the addition of new variable names as mapping keys, will always be visible.</p> <a name="user-content-locals-compatibility"></a> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto"><code>locals()</code> compatibility</h4><a id="user-content-locals-compatibility" class="anchor" aria-label="Permalink: locals() compatibility" href="#locals-compatibility"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto"><code>locals() is locals()</code> will be <code>False</code> for optimized frames, so code like the following will raise <code>KeyError</code> instead of returning <code>1</code>:</p> <pre>def f(): locals()["x"] = 1 return locals()["x"] </pre> <p dir="auto">To continue working, such code will need to explicitly store the namespace to be modified in a local variable, rather than relying on the previous implicit caching on the frame object:</p> <pre>def f(): ns = {} ns["x"] = 1 return ns["x"] </pre> <p dir="auto">While this technically isn't a formal backwards compatibility break (since the behaviour of writing back to <code>locals()</code> was explicitly documented as undefined), there is definitely some code that relies on the existing behaviour. Accordingly, the updated behaviour will be explicitly noted in the documentation as a change and it will be covered in the Python 3.13 porting guide.</p> <p dir="auto">To work with a copy of <code>locals()</code> in optimized scopes on all versions without making redundant copies on Python 3.13+, users will need to define a version-dependent helper function that only makes an explicit copy on Python versions prior to Python 3.13:</p> <pre>if sys.version_info >= (3, 13): def _ensure_func_snapshot(d): return d # 3.13+ locals() already returns a snapshot else: def _ensure_func_snapshot(d): return dict(d) # Create snapshot on older versions def f(): ns = _ensure_func_snapshot(locals()) ns["x"] = 1 return ns </pre> <p dir="auto">In other scopes, <code>locals().copy()</code> can continue to be called unconditionally without introducing any redundant copies.</p> <a name="user-content-impact-on-exec-and-eval"></a> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">Impact on <code>exec()</code> and <code>eval()</code></h4><a id="user-content-impact-on-exec-and-eval" class="anchor" aria-label="Permalink: Impact on exec() and eval()" href="#impact-on-exec-and-eval"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">Even though this PEP does not modify <code>exec()</code> or <code>eval()</code> directly, the semantic change to <code>locals()</code> impacts the behavior of <code>exec()</code> and <code>eval()</code> as they default to running code in the calling namespace.</p> <p dir="auto">This poses a potential compatibility issue for some code, as with the previous implementation that returns the same dict when <code>locals()</code> is called multiple times in function scope, the following code usually worked due to the implicitly shared local variable namespace:</p> <pre>def f(): exec('a = 0') # equivalent to exec('a = 0', globals(), locals()) exec('print(a)') # equivalent to exec('print(a)', globals(), locals()) print(locals()) # {'a': 0} # However, print(a) will not work here f() </pre> <p dir="auto">With the semantic changes to <code>locals()</code> in this PEP, the <code>exec('print(a)')'</code> call will fail with <code>NameError</code>, and <code>print(locals())</code> will report an empty dictionary, as each line will be using its own distinct snapshot of the local variables rather than implicitly sharing a single cached snapshot stored on the frame object.</p> <p dir="auto">A shared namespace across <code>exec()</code> calls can still be obtained by using explicit namespaces rather than relying on the previously implicitly shared frame namespace:</p> <pre>def f(): ns = {} exec('a = 0', locals=ns) exec('print(a)', locals=ns) # 0 f() </pre> <p dir="auto">You can even reliably change the variables in the local scope by explicitly using <code>frame.f_locals</code>, which was not possible before (even using <code>ctypes</code> to invoke <code>PyFrame_LocalsToFast</code> was subject to the state inconsistency problems discussed elsewhere in this PEP):</p> <pre>def f(): a = None exec('a = 0', locals=sys._getframe().f_locals) print(a) # 0 f() </pre> <p dir="auto">The behavior of <code>exec()</code> and <code>eval()</code> for module and class scopes (including nested invocations) is not changed, as the behaviour of <code>locals()</code> in those scopes is not changing.</p> <a name="user-content-impact-on-other-code-execution-apis-in-the-standard-library"></a> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">Impact on other code execution APIs in the standard library</h4><a id="user-content-impact-on-other-code-execution-apis-in-the-standard-library" class="anchor" aria-label="Permalink: Impact on other code execution APIs in the standard library" href="#impact-on-other-code-execution-apis-in-the-standard-library"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto"><code>pdb</code> and <code>bdb</code> use the <code>frame.f_locals</code> API, and hence will be able to reliably update local variables even in optimized frames. Implementing this PEP will resolve several longstanding bugs in these modules relating to threads, generators, coroutines, and other mechanisms that allow concurrent code execution while the debugger is active.</p> <p dir="auto">Other code execution APIs in the standard library (such as the <code>code</code> module) do not implicitly access <code>locals()</code> <em>or</em> <code>frame.f_locals</code>, but the behaviour of explicitly passing these namespaces will change as described in the rest of this PEP (passing <code>locals()</code> in optimized scopes will no longer implicitly share the code execution namespace across calls, passing <code>frame.f_locals</code> in optimized scopes will allow reliable modification of local variables and nonlocal cell references).</p> <a name="user-content-c-api-compatibility"></a> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">C API compatibility</h3><a id="user-content-c-api-compatibility" class="anchor" aria-label="Permalink: C API compatibility" href="#c-api-compatibility"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <a name="user-content-pyeval-getlocals-compatibility"></a> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto"><code>PyEval_GetLocals</code> compatibility</h4><a id="user-content-pyeval_getlocals-compatibility" class="anchor" aria-label="Permalink: PyEval_GetLocals compatibility" href="#pyeval_getlocals-compatibility"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto"><code>PyEval_GetLocals()</code> has never historically distinguished between whether it was emulating <code>locals()</code> or <code>sys._getframe().f_locals</code> at the Python level, as they all returned references to the same shared cache of the local variable bindings.</p> <p dir="auto">With this PEP, <code>locals()</code> changes to return independent snapshots on each call for optimized frames, and <code>frame.f_locals</code> (along with <code>PyFrame_GetLocals</code>) changes to return new write-through proxy instances.</p> <p dir="auto">Because <code>PyEval_GetLocals()</code> returns a borrowed reference, it isn't possible to update its semantics to align with either of those alternatives, leaving it as the only remaining API that requires a shared cache dictionary stored on the frame object.</p> <p dir="auto">While this technically leaves the semantics of the function unchanged, it no longer allows extra dict entries to be made visible to users of the other APIs, as those APIs are no longer accessing the same underlying cache dictionary.</p> <p dir="auto">When <code>PyEval_GetLocals()</code> is being used as an equivalent to the Python <code>locals()</code> builtin, <code>PyEval_GetFrameLocals()</code> should be used instead.</p> <p dir="auto">This code:</p> <pre>locals = PyEval_GetLocals(); if (locals == NULL) { goto error_handler; } Py_INCREF(locals); </pre> <p dir="auto">should be replaced with:</p> <pre>// Equivalent to "locals()" in Python code locals = PyEval_GetFrameLocals(); if (locals == NULL) { goto error_handler; } </pre> <p dir="auto">When <code>PyEval_GetLocals()</code> is being used as an equivalent to calling <code>sys._getframe().f_locals</code> in Python, it should be replaced by calling <code>PyFrame_GetLocals()</code> on the result of <code>PyEval_GetFrame()</code>.</p> <p dir="auto">In these cases, the original code should be replaced with:</p> <pre>// Equivalent to "sys._getframe()" in Python code frame = PyEval_GetFrame(); if (frame == NULL) { goto error_handler; } // Equivalent to "frame.f_locals" in Python code locals = PyFrame_GetLocals(frame); frame = NULL; // Minimise visibility of borrowed reference if (locals == NULL) { goto error_handler; } </pre> <a name="user-content-impact-on-pep-709-inlined-comprehensions"></a> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Impact on PEP 709 inlined comprehensions</h3><a id="user-content-impact-on-pep-709-inlined-comprehensions" class="anchor" aria-label="Permalink: Impact on PEP 709 inlined comprehensions" href="#impact-on-pep-709-inlined-comprehensions"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">For inlined comprehensions within a function, <code>locals()</code> currently behaves the same inside or outside of the comprehension, and this will not change. The behavior of <code>locals()</code> inside functions will generally change as specified in the rest of this PEP.</p> <p dir="auto">For inlined comprehensions at module or class scope, calling <code>locals()</code> within the inlined comprehension returns a new dictionary for each call. This PEP will make <code>locals()</code> within a function also always return a new dictionary for each call, improving consistency; class or module scope inlined comprehensions will appear to behave as if the inlined comprehension is still a distinct function.</p> <a name="user-content-implementation"></a> <div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Implementation</h2><a id="user-content-implementation" class="anchor" aria-label="Permalink: Implementation" href="#implementation"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">Each read of <code>frame.f_locals</code> will create a new proxy object that gives the appearance of being the mapping of local (including cell and free) variable names to the values of those local variables.</p> <p dir="auto">A possible implementation is sketched out below. All attributes that start with an underscore are invisible and cannot be accessed directly. They serve only to illustrate the proposed design.</p> <pre>NULL: Object # NULL is a singleton representing the absence of a value. class CodeType: _name_to_offset_mapping_impl: dict | NULL _cells: frozenset # Set of indexes of cell and free variables ... def __init__(self, ...): self._name_to_offset_mapping_impl = NULL self._variable_names = deduplicate( self.co_varnames + self.co_cellvars + self.co_freevars ) ... @property def _name_to_offset_mapping(self): "Mapping of names to offsets in local variable array." if self._name_to_offset_mapping_impl is NULL: self._name_to_offset_mapping_impl = { name: index for (index, name) in enumerate(self._variable_names) } return self._name_to_offset_mapping_impl class FrameType: _locals : array[Object] # The values of the local variables, items may be NULL. _extra_locals: dict | NULL # Dictionary for storing extra locals not in _locals. _locals_cache: FrameLocalsProxy | NULL # required to support PyEval_GetLocals() def __init__(self, ...): self._extra_locals = NULL self._locals_cache = NULL ... @property def f_locals(self): return FrameLocalsProxy(self) class FrameLocalsProxy: "Implements collections.MutableMapping." __slots__ = ("_frame", ) def __init__(self, frame:FrameType): self._frame = frame def __getitem__(self, name): f = self._frame co = f.f_code if name in co._name_to_offset_mapping: index = co._name_to_offset_mapping[name] val = f._locals[index] if val is NULL: raise KeyError(name) if index in co._cells val = val.cell_contents if val is NULL: raise KeyError(name) return val else: if f._extra_locals is NULL: raise KeyError(name) return f._extra_locals[name] def __setitem__(self, name, value): f = self._frame co = f.f_code if name in co._name_to_offset_mapping: index = co._name_to_offset_mapping[name] kind = co._local_kinds[index] if index in co._cells cell = f._locals[index] cell.cell_contents = val else: f._locals[index] = val else: if f._extra_locals is NULL: f._extra_locals = {} f._extra_locals[name] = val def __iter__(self): f = self._frame co = f.f_code yield from iter(f._extra_locals) for index, name in enumerate(co._variable_names): val = f._locals[index] if val is NULL: continue if index in co._cells: val = val.cell_contents if val is NULL: continue yield name def __contains__(self, item): f = self._frame if item in f._extra_locals: return True return item in co._variable_names def __len__(self): f = self._frame co = f.f_code res = 0 for index, _ in enumerate(co._variable_names): val = f._locals[index] if val is NULL: continue if index in co._cells: if val.cell_contents is NULL: continue res += 1 return len(self._extra_locals) + res </pre> <a name="user-content-id17"></a> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">C API</h3><a id="user-content-c-api-1" class="anchor" aria-label="Permalink: C API" href="#c-api-1"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto"><code>PyEval_GetLocals()</code> will be implemented roughly as follows:</p> <pre>PyObject *PyEval_GetLocals(void) { PyFrameObject * = ...; // Get the current frame. if (frame->_locals_cache == NULL) { frame->_locals_cache = PyEval_GetFrameLocals(); } else { PyDict_Update(frame->_locals_cache, PyFrame_GetLocals(frame)); } return frame->_locals_cache; } </pre> <p dir="auto">As with all functions that return a borrowed reference, care must be taken to ensure that the reference is not used beyond the lifetime of the object.</p> <a name="user-content-implementation-notes"></a> <div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Implementation Notes</h2><a id="user-content-implementation-notes" class="anchor" aria-label="Permalink: Implementation Notes" href="#implementation-notes"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">When accepted, the PEP text suggested that <code>PyEval_GetLocals</code> would start returning a cached instance of the new write-through proxy, while the implementation sketch indicated it would continue to return a dictionary snapshot cached on the frame instance. This discrepancy was identified while implementing the PEP, and <a href="https://github.com/python/steering-council/issues/245#issuecomment-2179005461" data-hovercard-type="issue" data-hovercard-url="/python/steering-council/issues/245/hovercard">resolved by the Steering Council</a> in favour of retaining the Python 3.12 behaviour of returning a dictionary snapshot cached on the frame instance. The PEP text has been updated accordingly.</p> <p dir="auto">During the discussions of the C API clarification, it also became apparent that the rationale behind <code>locals()</code> being updated to return independent snapshots in <a href="#id18"><span id="user-content-id19">:term:`optimized scopes <py3.13:optimized scope>`</span></a> wasn't clear, as it had been inherited from the original <a href="http://www.python.org/dev/peps/pep-0558" rel="nofollow">PEP 558</a> discussions rather than being independently covered in this PEP. The PEP text has been updated to better cover this change, with additional updates to the Specification and Backwards Compatibility sections to cover the impact on code execution APIs that default to executing code in the <code>locals()</code> namespace. Additional motivation and rationale details have also been added to <a href="http://www.python.org/dev/peps/pep-0558" rel="nofollow">PEP 558</a>.</p> <p dir="auto">In 3.13.0, the write-through proxies did not allow deletion of even extra variables with <code>del</code> and <code>pop()</code>. This was subsequently reported as a <a href="https://github.com/python/cpython/issues/125590" data-hovercard-type="issue" data-hovercard-url="/python/cpython/issues/125590/hovercard">compatibility regression</a>, and <a href="https://github.com/python/cpython/pull/125616" data-hovercard-type="pull_request" data-hovercard-url="/python/cpython/pull/125616/hovercard">resolved</a> as now described in <a href="#id20"><span id="user-content-id21">:ref:`pep-667-f_locals-spec`</span></a>.</p> <a name="user-content-comparison-with-pep-558"></a> <div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Comparison with PEP 558</h2><a id="user-content-comparison-with-pep-558" class="anchor" aria-label="Permalink: Comparison with PEP 558" href="#comparison-with-pep-558"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">This PEP and <a href="http://www.python.org/dev/peps/pep-0558" rel="nofollow">PEP 558</a> shared a common goal: to make the semantics of <code>locals()</code> and <code>frame.f_locals()</code> intelligible, and their operation reliable.</p> <p dir="auto">The key difference between this PEP and PEP 558 is that PEP 558 attempted to store extra variables inside a full internal dictionary copy of the local variables in an effort to improve backwards compatibility with the legacy <code>PyEval_GetLocals()</code> API, whereas this PEP does not (it stores the extra local variables in a dedicated dictionary accessed solely via the new frame proxy objects, and copies them to the <code>PyEval_GetLocals()</code> shared dict only when requested).</p> <p dir="auto">PEP 558 did not specify exactly when that internal copy was updated, making the behavior of PEP 558 impossible to reason about in several cases where this PEP remains well specified.</p> <p dir="auto">PEP 558 also proposed the introduction of some additional Python scope introspection interfaces to the C API that would allow extension modules to more easily determine whether the currently active Python scope is optimized or not, and hence whether the C API's <code>locals()</code> equivalent returns a direct reference to the frame's local execution namespace or a shallow copy of the frame's local variables and nonlocal cell references. Whether or not to add such introspection APIs is independent of the proposed changes to <code>locals()</code> and <code>frame.f_locals</code> and hence no such proposals have been included in this PEP.</p> <p dir="auto">PEP 558 was <a href="#id22"><span id="user-content-id23">:pep:`ultimately withdrawn <558#pep-withdrawal>`</span></a> in favour of this PEP.</p> <a name="user-content-reference-implementation"></a> <div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Reference Implementation</h2><a id="user-content-reference-implementation" class="anchor" aria-label="Permalink: Reference Implementation" href="#reference-implementation"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">The implementation is in development as a <a href="https://github.com/python/cpython/pull/115153" data-hovercard-type="pull_request" data-hovercard-url="/python/cpython/pull/115153/hovercard">draft pull request on GitHub</a>.</p> <a name="user-content-copyright"></a> <div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Copyright</h2><a id="user-content-copyright" class="anchor" aria-label="Permalink: Copyright" href="#copyright"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">This document is placed in the public domain or under the CC0-1.0-Universal license, whichever is more permissive.</p> </article></div><button hidden=""></button></section></div></div></div> <!-- --> <!-- --> </div></div></div><div class="Box-sc-g0xbh4-0"></div></div></div></div></div><div id="find-result-marks-container" class="Box-sc-g0xbh4-0 cCoXib"></div><button hidden="" data-testid="" data-hotkey-scope="read-only-cursor-text-area"></button><button hidden=""></button></div> <!-- --> <!-- --> <script type="application/json" id="__PRIMER_DATA_:R0:__">{"resolvedServerColorMode":"day"}</script></div> </react-app> </turbo-frame> </div> </turbo-frame> </main> </div> </div> <footer class="footer pt-8 pb-6 f6 color-fg-muted p-responsive" role="contentinfo" > <h2 class='sr-only'>Footer</h2> <div class="d-flex flex-justify-center flex-items-center flex-column-reverse flex-lg-row flex-wrap flex-lg-nowrap"> <div class="d-flex flex-items-center flex-shrink-0 mx-2"> <a aria-label="Homepage" title="GitHub" class="footer-octicon mr-2" href="https://github.com"> <svg aria-hidden="true" height="24" viewBox="0 0 24 24" version="1.1" width="24" data-view-component="true" class="octicon octicon-mark-github"> <path d="M12.5.75C6.146.75 1 5.896 1 12.25c0 5.089 3.292 9.387 7.863 10.91.575.101.79-.244.79-.546 0-.273-.014-1.178-.014-2.142-2.889.532-3.636-.704-3.866-1.35-.13-.331-.69-1.352-1.18-1.625-.402-.216-.977-.748-.014-.762.906-.014 1.553.834 1.769 1.179 1.035 1.74 2.688 1.25 3.349.948.1-.747.402-1.25.733-1.538-2.559-.287-5.232-1.279-5.232-5.678 0-1.25.445-2.285 1.178-3.09-.115-.288-.517-1.467.115-3.048 0 0 .963-.302 3.163 1.179.92-.259 1.897-.388 2.875-.388.977 0 1.955.13 2.875.388 2.2-1.495 3.162-1.179 3.162-1.179.633 1.581.23 2.76.115 3.048.733.805 1.179 1.825 1.179 3.09 0 4.413-2.688 5.39-5.247 5.678.417.36.776 1.05.776 2.128 0 1.538-.014 2.774-.014 3.162 0 .302.216.662.79.547C20.709 21.637 24 17.324 24 12.25 24 5.896 18.854.75 12.5.75Z"></path> </svg> </a> <span> © 2025 GitHub, Inc. </span> </div> <nav aria-label="Footer"> <h3 class="sr-only" id="sr-footer-heading">Footer navigation</h3> <ul class="list-style-none d-flex flex-justify-center flex-wrap mb-2 mb-lg-0" aria-labelledby="sr-footer-heading"> <li class="mx-2"> <a data-analytics-event="{"category":"Footer","action":"go to Terms","label":"text:terms"}" href="https://docs.github.com/site-policy/github-terms/github-terms-of-service" data-view-component="true" class="Link--secondary Link">Terms</a> </li> <li class="mx-2"> <a data-analytics-event="{"category":"Footer","action":"go to privacy","label":"text:privacy"}" href="https://docs.github.com/site-policy/privacy-policies/github-privacy-statement" data-view-component="true" class="Link--secondary Link">Privacy</a> </li> <li class="mx-2"> <a data-analytics-event="{"category":"Footer","action":"go to security","label":"text:security"}" href="https://github.com/security" data-view-component="true" class="Link--secondary Link">Security</a> </li> <li class="mx-2"> <a data-analytics-event="{"category":"Footer","action":"go to status","label":"text:status"}" href="https://www.githubstatus.com/" data-view-component="true" class="Link--secondary Link">Status</a> </li> <li class="mx-2"> <a data-analytics-event="{"category":"Footer","action":"go to docs","label":"text:docs"}" href="https://docs.github.com/" data-view-component="true" class="Link--secondary Link">Docs</a> </li> <li class="mx-2"> <a data-analytics-event="{"category":"Footer","action":"go to contact","label":"text:contact"}" href="https://support.github.com?tags=dotcom-footer" data-view-component="true" class="Link--secondary Link">Contact</a> </li> <li class="mx-2" > <cookie-consent-link> <button type="button" class="Link--secondary underline-on-hover border-0 p-0 color-bg-transparent" data-action="click:cookie-consent-link#showConsentManagement" data-analytics-event="{"location":"footer","action":"cookies","context":"subfooter","tag":"link","label":"cookies_link_subfooter_footer"}" > Manage cookies </button> </cookie-consent-link> </li> <li class="mx-2"> <cookie-consent-link> <button type="button" class="Link--secondary underline-on-hover border-0 p-0 color-bg-transparent" data-action="click:cookie-consent-link#showConsentManagement" data-analytics-event="{"location":"footer","action":"dont_share_info","context":"subfooter","tag":"link","label":"dont_share_info_link_subfooter_footer"}" > Do not share my personal information </button> </cookie-consent-link> </li> </ul> </nav> </div> </footer> <ghcc-consent id="ghcc" class="position-fixed bottom-0 left-0" style="z-index: 999999" data-initial-cookie-consent-allowed="" data-cookie-consent-required="false"></ghcc-consent> <div id="ajax-error-message" class="ajax-error-message flash flash-error" hidden> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-alert"> <path d="M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path> </svg> <button type="button" class="flash-close js-ajax-error-dismiss" aria-label="Dismiss error"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-x"> <path d="M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734L9.06 8l3.22 3.22a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L8 9.06l-3.22 3.22a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06Z"></path> </svg> </button> You can’t perform that action at this time. </div> <template id="site-details-dialog"> <details class="details-reset details-overlay details-overlay-dark lh-default color-fg-default hx_rsm" open> <summary role="button" aria-label="Close dialog"></summary> <details-dialog class="Box Box--overlay d-flex flex-column anim-fade-in fast hx_rsm-dialog hx_rsm-modal"> <button class="Box-btn-octicon m-0 btn-octicon position-absolute right-0 top-0" type="button" aria-label="Close dialog" data-close-dialog> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-x"> <path d="M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734L9.06 8l3.22 3.22a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L8 9.06l-3.22 3.22a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06Z"></path> </svg> </button> <div class="octocat-spinner my-6 js-details-dialog-spinner"></div> </details-dialog> </details> </template> <div class="Popover js-hovercard-content position-absolute" style="display: none; outline: none;"> <div class="Popover-message Popover-message--bottom-left Popover-message--large Box color-shadow-large" style="width:360px;"> </div> </div> <template id="snippet-clipboard-copy-button"> <div class="zeroclipboard-container position-absolute right-0 top-0"> <clipboard-copy aria-label="Copy" class="ClipboardButton btn js-clipboard-copy m-2 p-0" data-copy-feedback="Copied!" data-tooltip-direction="w"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-copy js-clipboard-copy-icon m-2"> <path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path> </svg> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-check js-clipboard-check-icon color-fg-success d-none m-2"> <path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"></path> </svg> </clipboard-copy> </div> </template> <template id="snippet-clipboard-copy-button-unpositioned"> <div class="zeroclipboard-container"> <clipboard-copy aria-label="Copy" class="ClipboardButton btn btn-invisible js-clipboard-copy m-2 p-0 d-flex flex-justify-center flex-items-center" data-copy-feedback="Copied!" data-tooltip-direction="w"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-copy js-clipboard-copy-icon"> <path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path> </svg> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-check js-clipboard-check-icon color-fg-success d-none"> <path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"></path> </svg> </clipboard-copy> </div> </template> </div> <div id="js-global-screen-reader-notice" class="sr-only mt-n1" aria-live="polite" aria-atomic="true" ></div> <div id="js-global-screen-reader-notice-assertive" class="sr-only mt-n1" aria-live="assertive" aria-atomic="true"></div> </body> </html>