CINXE.COM
peps/peps/pep-0374.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_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_editor_upsells","copilot_implicit_context","copilot_no_floating_button","copilot_smell_icebreaker_ux","copilot_read_shared_conversation","dotcom_chat_client_side_skills","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_extensions_ga","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-3d3f89e95d95.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-682f1551aebf.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-17d1e0503b7c.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-9a5713772ca5.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/react-core-af33445b6fc3.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-c47b35ea29c3.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/ui_packages_ref-selector_RefSelector_tsx-7496afc3784d.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/ui_packages_diffs_diff-parts_ts-555a13945c12.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/ui_packages_code-view-shared_worker-jobs_debounced-worker-manager_ts-ui_packages_commit-attri-896a5d-3d08bda096d3.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-51fe787d3cdc.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-ad58d952149e.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-10aa1d2ed72d.js"></script> <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react.e159a7f290fa5e4dd43e.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-4a07d5e6bdd6.js"></script> <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react.e159a7f290fa5e4dd43e.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-0374.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="966C:3B1FAD:10F43:167C7:67B78A47" data-pjax-transient="true"/><meta name="html-safe-nonce" content="6931cc67920292e1fee1f02a80262c4aae0541ac7bdc30fb5b65bfdf3c17897e" data-pjax-transient="true"/><meta name="visitor-payload" content="eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiI5NjZDOjNCMUZBRDoxMEY0MzoxNjdDNzo2N0I3OEE0NyIsInZpc2l0b3JfaWQiOiI4OTc2NzQ4NzI4NjI2NDE2MTk5IiwicmVnaW9uX2VkZ2UiOiJzb3V0aGVhc3Rhc2lhIiwicmVnaW9uX3JlbmRlciI6InNvdXRoZWFzdGFzaWEifQ==" data-pjax-transient="true"/><meta name="visitor-hmac" content="d41d75cc87d5a62e905f28051a464c33251d96ff73c1c4c725fb26d249d558b0" 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-0374.rst" /> <meta name="twitter:image" content="https://opengraph.githubassets.com/ddbbc3f5e8e69425caadc39aef960ad67eab3be36e655a2ebca7a72a9651316f/python/peps" /><meta name="twitter:site" content="@github" /><meta name="twitter:card" content="summary_large_image" /><meta name="twitter:title" content="peps/peps/pep-0374.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/ddbbc3f5e8e69425caadc39aef960ad67eab3be36e655a2ebca7a72a9651316f/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-0374.rst at main · python/peps" /><meta property="og:url" content="https://github.com/python/peps/blob/main/peps/pep-0374.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="792f22f6cf8a98d50b0a408d8ffad1fcd10092d5996451b87544c701b763fe5e" 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="906f8b575274e25e783db88760074d5acd5e2e47c7346dafe39509555b31e8a6" 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-97496b0f52ba.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/keyboard-shortcuts-dialog-c79a97a16b04.js"></script> <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react.e159a7f290fa5e4dd43e.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-0374.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-0374.rst","user_id":null}}" data-hydro-click-hmac="3e92bccef24104e8cca7940c68e174c2e9d763eb38e248ed3e633cd45eb3890a" 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":"events_amp_webinars","context":"resources","tag":"link","label":"events_amp_webinars_link_resources_navbar"}" href="https://resources.github.com"> Events & 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":"ebooks_amp_whitepapers","context":"resources","tag":"link","label":"ebooks_amp_whitepapers_link_resources_navbar"}" href="https://github.com/resources/whitepapers"> Ebooks & Whitepapers </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="QlQbdP21TPfjobc6QaU0Cl4ni_jsGGeQ-arwxVoili3A1y7jrLo4mNEdxhX6YVIM095WV1ik15jN1PmbSC3sjQ" 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-252fa7e7-9cab-4d42-8974-8ae281b8bd25" 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-252fa7e7-9cab-4d42-8974-8ae281b8bd25" 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="SPFOmMxNc4+Oj1pzas674JzptR/QY2idoAL8kCrIVvF5FQLolQ2UO0DDm9+JIvel9O8VeTkkfNM92zSG7f4y1g==" /> <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="rctRBn3WrKRKMxzjBqIJJRLp3cFp1IveMeRPqUuVq8BdJjvyqV6uPvTdKkPKfqqgz+rl/q0ygAqXgFOYRtRA6A==" /> <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="lFPenEgLviCsCJ5Ll6A15Ho6EVsD5T58IZjgm/YbZ0h98uVRchwNBtjxJK9HYunEbB5W7M5Ss7ROrbLl+zdXOw==" /> </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-0374.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-0374.rst","user_id":null}}" data-hydro-click-hmac="3e92bccef24104e8cca7940c68e174c2e9d763eb38e248ed3e633cd45eb3890a" 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-0374.rst","user_id":null}}" data-hydro-click-hmac="3e92bccef24104e8cca7940c68e174c2e9d763eb38e248ed3e633cd45eb3890a" 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-52f271ca-1a50-4e64-ab31-8dcc21a1a637" aria-labelledby="tooltip-b562e562-0ff1-42a1-aff4-01556e853c12" 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-b562e562-0ff1-42a1-aff4-01556e853c12" for="icon-button-52f271ca-1a50-4e64-ab31-8dcc21a1a637" 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-0374.rst","user_id":null}}" data-hydro-click-hmac="608c9423d744597f6d40b335e36b71f5dc89cbc826775dcc32779365b2d503f3" 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-f51fb67c-0b35-4064-9969-c9437cd6b3ac" 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-0374.rst","user_id":null}}" data-hydro-click-hmac="5c82f0d5f556d7ef26ebadf0f0891b8b99a734771279531b756c67968af0727c" 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-0374.rst","user_id":null}}" data-hydro-click-hmac="088c14a57b5119fd40deee5dfad05ad6557160e72d456caa29b15180d662a560" 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="4530 users starred this repository" data-singular-suffix="user starred this repository" data-plural-suffix="users starred this repository" data-turbo-replace="true" title="4,530" 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="20" data-view-component="true" class="Counter">20</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="25" data-view-component="true" class="Counter">25</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-8daeb3b5-0eb5-4c78-88c3-d5dcd255099a-button" popovertarget="action-menu-8daeb3b5-0eb5-4c78-88c3-d5dcd255099a-overlay" aria-controls="action-menu-8daeb3b5-0eb5-4c78-88c3-d5dcd255099a-list" aria-haspopup="true" aria-labelledby="tooltip-82390fa5-dbf3-4757-bbda-6d8a44d36ca2" 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-82390fa5-dbf3-4757-bbda-6d8a44d36ca2" for="action-menu-8daeb3b5-0eb5-4c78-88c3-d5dcd255099a-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-8daeb3b5-0eb5-4c78-88c3-d5dcd255099a-overlay" anchor="action-menu-8daeb3b5-0eb5-4c78-88c3-d5dcd255099a-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-8daeb3b5-0eb5-4c78-88c3-d5dcd255099a-button" id="action-menu-8daeb3b5-0eb5-4c78-88c3-d5dcd255099a-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-696848e6-b1fc-4be0-9732-d50d6c840d82" 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-5b519c2c-194f-4f9f-9002-f031dedcae86" 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-1b1ac098-bd71-484c-bcfd-7146603b88bd" 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-93954d03-d8f7-43cb-a129-03bad59270f8" 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-23a80ed0-cb2a-428c-b388-8507a4e1d4ca" 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-a88610b4-a057-4372-8525-e61394cd8ccd" 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-0374.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":190.833212,"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":"93e9cc38fcf623cfe6ce47673fc4fcbc08290577"},"path":"peps/pep-0374.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-0374.rst","displayUrl":"https://github.com/python/peps/blob/main/peps/pep-0374.rst?raw=true","headerInfo":{"blobSize":"53 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":"33fe03e","siteNavLoginPath":"/login?return_to=https%3A%2F%2Fgithub.com%2Fpython%2Fpeps%2Fblob%2Fmain%2Fpeps%2Fpep-0374.rst","isCSV":false,"isRichtext":true,"toc":[{"level":2,"text":"Rationale","anchor":"rationale","htmlText":"Rationale"},{"level":2,"text":"Terminology","anchor":"terminology","htmlText":"Terminology"},{"level":2,"text":"Typical Workflow","anchor":"typical-workflow","htmlText":"Typical Workflow"},{"level":2,"text":"Contenders","anchor":"contenders","htmlText":"Contenders"},{"level":2,"text":"Interoperability","anchor":"interoperability","htmlText":"Interoperability"},{"level":2,"text":"Usage Scenarios","anchor":"usage-scenarios","htmlText":"Usage Scenarios"},{"level":3,"text":"Initial Setup","anchor":"initial-setup","htmlText":"Initial Setup"},{"level":4,"text":"svn","anchor":"svn","htmlText":"svn"},{"level":4,"text":"bzr","anchor":"bzr","htmlText":"bzr"},{"level":4,"text":"hg","anchor":"hg","htmlText":"hg"},{"level":4,"text":"git","anchor":"git","htmlText":"git"},{"level":3,"text":"One-Off Checkout","anchor":"one-off-checkout","htmlText":"One-Off Checkout"},{"level":4,"text":"svn","anchor":"svn-1","htmlText":"svn"},{"level":4,"text":"bzr","anchor":"bzr-1","htmlText":"bzr"},{"level":4,"text":"hg","anchor":"hg-1","htmlText":"hg"},{"level":4,"text":"git","anchor":"git-1","htmlText":"git"},{"level":3,"text":"Backing Out Changes","anchor":"backing-out-changes","htmlText":"Backing Out Changes"},{"level":4,"text":"svn","anchor":"svn-2","htmlText":"svn"},{"level":4,"text":"bzr","anchor":"bzr-2","htmlText":"bzr"},{"level":4,"text":"hg","anchor":"hg-2","htmlText":"hg"},{"level":4,"text":"git","anchor":"git-2","htmlText":"git"},{"level":3,"text":"Patch Review","anchor":"patch-review","htmlText":"Patch Review"},{"level":4,"text":"svn","anchor":"svn-3","htmlText":"svn"},{"level":4,"text":"bzr","anchor":"bzr-3","htmlText":"bzr"},{"level":4,"text":"hg","anchor":"hg-3","htmlText":"hg"},{"level":4,"text":"git","anchor":"git-3","htmlText":"git"},{"level":3,"text":"Backport","anchor":"backport","htmlText":"Backport"},{"level":4,"text":"svn","anchor":"svn-4","htmlText":"svn"},{"level":4,"text":"bzr","anchor":"bzr-4","htmlText":"bzr"},{"level":4,"text":"hg","anchor":"hg-4","htmlText":"hg"},{"level":4,"text":"git","anchor":"git-4","htmlText":"git"},{"level":3,"text":"Coordinated Development of a New Feature","anchor":"coordinated-development-of-a-new-feature","htmlText":"Coordinated Development of a New Feature"},{"level":4,"text":"svn","anchor":"svn-5","htmlText":"svn"},{"level":3,"text":"Separation of Issue Dependencies","anchor":"separation-of-issue-dependencies","htmlText":"Separation of Issue Dependencies"},{"level":4,"text":"svn","anchor":"svn-6","htmlText":"svn"},{"level":4,"text":"bzr","anchor":"bzr-5","htmlText":"bzr"},{"level":4,"text":"hg","anchor":"hg-5","htmlText":"hg"},{"level":4,"text":"git","anchor":"git-5","htmlText":"git"},{"level":3,"text":"Doing a Python Release","anchor":"doing-a-python-release","htmlText":"Doing a Python Release"},{"level":4,"text":"bzr","anchor":"bzr-6","htmlText":"bzr"},{"level":4,"text":"hg","anchor":"hg-6","htmlText":"hg"},{"level":4,"text":"git","anchor":"git-6","htmlText":"git"},{"level":2,"text":"Platform/Tool Support","anchor":"platformtool-support","htmlText":"Platform/Tool Support"},{"level":3,"text":"Operating Systems","anchor":"operating-systems","htmlText":"Operating Systems"},{"level":3,"text":"CRLF -\u003e LF Support","anchor":"crlf---lf-support","htmlText":"CRLF -\u0026gt; LF Support"},{"level":3,"text":"Case-insensitive filesystem support","anchor":"case-insensitive-filesystem-support","htmlText":"Case-insensitive filesystem support"},{"level":3,"text":"Tools","anchor":"tools","htmlText":"Tools"},{"level":2,"text":"Usage On Top Of Subversion","anchor":"usage-on-top-of-subversion","htmlText":"Usage On Top Of Subversion"},{"level":2,"text":"Server Support","anchor":"server-support","htmlText":"Server Support"},{"level":2,"text":"Development","anchor":"development","htmlText":"Development"},{"level":2,"text":"Special Features","anchor":"special-features","htmlText":"Special Features"},{"level":3,"text":"bzr","anchor":"bzr-7","htmlText":"bzr"},{"level":3,"text":"hg","anchor":"hg-7","htmlText":"hg"},{"level":3,"text":"git","anchor":"git-7","htmlText":"git"},{"level":2,"text":"Tests/Impressions","anchor":"testsimpressions","htmlText":"Tests/Impressions"},{"level":3,"text":"Barrier to Entry","anchor":"barrier-to-entry","htmlText":"Barrier to Entry"},{"level":3,"text":"Performance of basic information functionality","anchor":"performance-of-basic-information-functionality","htmlText":"Performance of basic information functionality"},{"level":3,"text":"Figuring out what command to use from built-in help","anchor":"figuring-out-what-command-to-use-from-built-in-help","htmlText":"Figuring out what command to use from built-in help"},{"level":3,"text":"Updating a checkout","anchor":"updating-a-checkout","htmlText":"Updating a checkout"},{"level":2,"text":"Decision","anchor":"decision","htmlText":"Decision"},{"level":3,"text":"Why Mercurial over Subversion","anchor":"why-mercurial-over-subversion","htmlText":"Why Mercurial over Subversion"},{"level":3,"text":"Why Mercurial over other DVCSs","anchor":"why-mercurial-over-other-dvcss","htmlText":"Why Mercurial over other DVCSs"},{"level":2,"text":"Transition Plan","anchor":"transition-plan","htmlText":"Transition Plan"},{"level":2,"text":"Copyright","anchor":"copyright","htmlText":"Copyright"}],"lineInfo":{"truncatedLoc":"1514","truncatedSloc":"1200"},"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-0374.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-0374.rst","renderImageOrRaw":false,"richText":"\u003carticle class=\"markdown-body entry-content container-lg\" itemprop=\"text\"\u003e\u003cp dir=\"auto\"\u003ePEP: 374\nTitle: Choosing a distributed VCS for the Python project\nAuthor: Brett Cannon \u0026lt;\u003ca href=\"mailto:brett@python.org\"\u003ebrett@python.org\u003c/a\u003e\u0026gt;,\u003c/p\u003e\n\u003cblockquote\u003e\nStephen J. Turnbull \u0026lt;\u003ca href=\"mailto:stephen@xemacs.org\"\u003estephen@xemacs.org\u003c/a\u003e\u0026gt;,\nAlexandre Vassalotti \u0026lt;\u003ca href=\"mailto:alexandre@peadrop.com\"\u003ealexandre@peadrop.com\u003c/a\u003e\u0026gt;,\nBarry Warsaw \u0026lt;\u003ca href=\"mailto:barry@python.org\"\u003ebarry@python.org\u003c/a\u003e\u0026gt;,\nDirkjan Ochtman \u0026lt;\u003ca href=\"mailto:dirkjan@ochtman.nl\"\u003edirkjan@ochtman.nl\u003c/a\u003e\u0026gt;\u003c/blockquote\u003e\n\u003cp dir=\"auto\"\u003eStatus: Final\nType: Process\nCreated: 07-Nov-2008\nPost-History: 07-Nov-2008,\u003c/p\u003e\n\u003cblockquote\u003e\n22-Jan-2009\u003c/blockquote\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\u003cp dir=\"auto\"\u003ePython has been using a centralized version control system (VCS;\nfirst CVS, now Subversion) for years to great effect. Having a master\ncopy of the official version of Python provides people with a single\nplace to always get the official Python source code. It has also\nallowed for the storage of the history of the language, mostly for\nhelp with development, but also for posterity. And of course the V in\nVCS is very helpful when developing.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eBut a centralized version control system has its drawbacks. First and\nforemost, in order to have the benefits of version control with\nPython in a seamless fashion, one must be a \"core developer\" (i.e.\nsomeone with commit privileges on the master copy of Python). People\nwho are not core developers but who wish to work with Python's\nrevision tree, e.g. anyone writing a patch for Python or creating a\ncustom version, do not have direct tool support for revisions. This\ncan be quite a limitation, since these non-core developers cannot\neasily do basic tasks such as reverting changes to a previously\nsaved state, creating branches, publishing one's changes with full\nrevision history, etc. For non-core developers, the last safe tree\nstate is one the Python developers happen to set, and this prevents\nsafe development. This second-class citizenship is a hindrance to\npeople who wish to contribute to Python with a patch of any\ncomplexity and want a way to incrementally save their progress to\nmake their development lives easier.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThere is also the issue of having to be online to be able to commit\none's work. Because centralized VCSs keep a central copy that stores\nall revisions, one must have Internet access in order for their\nrevisions to be stored; no Net, no commit. This can be annoying if\nyou happen to be traveling and lack any Internet. There is also the\nsituation of someone wishing to contribute to Python but having a\nbad Internet connection where committing is time-consuming and\nexpensive and it might work out better to do it in a single step.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eAnother drawback to a centralized VCS is that a common use case is\nfor a developer to revise patches in response to review comments.\nThis is more difficult with a centralized model because there's no\nplace to contain intermediate work. It's either all checked in or\nnone of it is checked in. In the centralized VCS, it's also very\ndifficult to track changes to the trunk as they are committed, while\nyou're working on your feature or bug fix branch. This increases\nthe risk that such branches will grow stale, out-dated, or that\nmerging them into the trunk will generate too may conflicts to be\neasily resolved.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eLastly, there is the issue of maintenance of Python. At any one time\nthere is at least one major version of Python under development (at\nthe time of this writing there are two). For each major version of\nPython under development there is at least the maintenance version\nof the last minor version and the in-development minor version (e.g.\nwith 2.6 just released, that means that both 2.6 and 2.7 are being\nworked on). Once a release is done, a branch is created between the\ncode bases where changes in one version do not (but could) belong in\nthe other version. As of right now there is no natural support for\nthis branch in time in central VCSs; you must use tools that\nsimulate the branching. Tracking merges is similarly painful for\ndevelopers, as revisions often need to be merged between four active\nbranches (e.g. 2.6 maintenance, 3.0 maintenance, 2.7 development,\n3.1 development). In this case, VCSs such as Subversion only handle\nthis through arcane third party tools.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eDistributed VCSs (DVCSs) solve all of these problems. While one can\nkeep a master copy of a revision tree, anyone is free to copy that\ntree for their own use. This gives everyone the power to commit\nchanges to their copy, online or offline. It also more naturally\nties into the idea of branching in the history of a revision tree\nfor maintenance and the development of new features bound for\nPython. DVCSs also provide a great many additional features that\ncentralized VCSs don't or can't provide.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThis PEP explores the possibility of changing Python's use of Subversion\nto any of the currently popular DVCSs, in order to gain\nthe benefits outlined above. This PEP does not guarantee that a switch\nto a DVCS will occur at the conclusion of this PEP. It is quite\npossible that no clear winner will be found and that svn will continue\nto be used. If this happens, this PEP will be revisited and revised in\nthe future as the state of DVCSs evolves.\u003c/p\u003e\n\u003ca name=\"user-content-terminology\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eTerminology\u003c/h2\u003e\u003ca id=\"user-content-terminology\" class=\"anchor\" aria-label=\"Permalink: Terminology\" href=\"#terminology\"\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\"\u003eAgreeing on a common terminology is surprisingly difficult,\nprimarily because each VCS uses these terms when describing subtly\ndifferent tasks, objects, and concepts. Where possible, we try to\nprovide a generic definition of the concepts, but you should consult\nthe individual system's glossaries for details. Here are some basic\nreferences for terminology, from some of the standard web-based\nreferences on each VCS. You can also refer to glossaries for each\nDVCS:\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eSubversion : \u003ca href=\"http://svnbook.red-bean.com/en/1.5/svn.basic.html\" rel=\"nofollow\"\u003ehttp://svnbook.red-bean.com/en/1.5/svn.basic.html\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eBazaar : \u003ca href=\"http://bazaar-vcs.org/BzrGlossary\" rel=\"nofollow\"\u003ehttp://bazaar-vcs.org/BzrGlossary\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eMercurial : \u003ca href=\"http://www.selenic.com/mercurial/wiki/index.cgi/UnderstandingMercurial\" rel=\"nofollow\"\u003ehttp://www.selenic.com/mercurial/wiki/index.cgi/UnderstandingMercurial\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003egit : \u003ca href=\"http://book.git-scm.com/1_the_git_object_model.html\" rel=\"nofollow\"\u003ehttp://book.git-scm.com/1_the_git_object_model.html\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdl\u003e\n\u003cdt\u003ebranch\u003c/dt\u003e\n\u003cdd\u003eA line of development; a collection of revisions, ordered by\ntime.\u003c/dd\u003e\n\u003cdt\u003echeckout/working copy/working tree\u003c/dt\u003e\n\u003cdd\u003eA tree of code the developer can edit, linked to a branch.\u003c/dd\u003e\n\u003cdt\u003eindex\u003c/dt\u003e\n\u003cdd\u003eA \"staging area\" where a revision is built (unique to git).\u003c/dd\u003e\n\u003cdt\u003erepository\u003c/dt\u003e\n\u003cdd\u003eA collection of revisions, organized into branches.\u003c/dd\u003e\n\u003cdt\u003eclone\u003c/dt\u003e\n\u003cdd\u003eA complete copy of a branch or repository.\u003c/dd\u003e\n\u003cdt\u003ecommit\u003c/dt\u003e\n\u003cdd\u003eTo record a revision in a repository.\u003c/dd\u003e\n\u003cdt\u003emerge\u003c/dt\u003e\n\u003cdd\u003eApplying all the changes and history from one branch/repository\nto another.\u003c/dd\u003e\n\u003cdt\u003epull\u003c/dt\u003e\n\u003cdd\u003eTo update a checkout/clone from the original branch/repository,\nwhich can be remote or local\u003c/dd\u003e\n\u003cdt\u003epush/publish\u003c/dt\u003e\n\u003cdd\u003eTo copy a revision, and all revisions it depends on, from a one\nrepository to another.\u003c/dd\u003e\n\u003cdt\u003echerry-pick\u003c/dt\u003e\n\u003cdd\u003eTo merge one or more specific revisions from one branch to\nanother, possibly in a different repository, possibly without its\ndependent revisions.\u003c/dd\u003e\n\u003cdt\u003erebase\u003c/dt\u003e\n\u003cdd\u003eTo \"detach\" a branch, and move it to a new branch point; move\ncommits to the beginning of a branch instead of where they\nhappened in time.\u003c/dd\u003e\n\u003c/dl\u003e\n\u003ca name=\"user-content-typical-workflow\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eTypical Workflow\u003c/h2\u003e\u003ca id=\"user-content-typical-workflow\" class=\"anchor\" aria-label=\"Permalink: Typical Workflow\" href=\"#typical-workflow\"\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\"\u003eAt the moment, the typical workflow for a Python core developer is:\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eEdit code in a checkout until it is stable enough to commit/push.\u003c/li\u003e\n\u003cli\u003eCommit to the master repository.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003eIt is a rather simple workflow, but it has drawbacks. For one,\nbecause any work that involves the repository takes time thanks to\nthe network, commits/pushes tend to not necessarily be as atomic as\npossible. There is also the drawback of there not being a\nnecessarily cheap way to create new checkouts beyond a recursive\ncopy of the checkout directory.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eA DVCS would lead to a workflow more like this:\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eBranch off of a local clone of the master repository.\u003c/li\u003e\n\u003cli\u003eEdit code, committing in atomic pieces.\u003c/li\u003e\n\u003cli\u003eMerge the branch into the mainline, and\u003c/li\u003e\n\u003cli\u003ePush all commits to the master repository.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003eWhile there are more possible steps, the workflow is much more\nindependent of the master repository than is currently possible. By\nbeing able to commit locally at the speed of your disk, a core\ndeveloper is able to do atomic commits much more frequently,\nminimizing having commits that do multiple things to the code. Also\nby using a branch, the changes are isolated (if desired) from other\nchanges being made by other developers. Because branches are cheap,\nit is easy to create and maintain many smaller branches that address\none specific issue, e.g. one bug or one new feature. More\nsophisticated features of DVCSs allow the developer to more easily\ntrack long running development branches as the official mainline\nprogresses.\u003c/p\u003e\n\u003ca name=\"user-content-contenders\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eContenders\u003c/h2\u003e\u003ca id=\"user-content-contenders\" class=\"anchor\" aria-label=\"Permalink: Contenders\" href=\"#contenders\"\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\u003cmarkdown-accessiblity-table\u003e\u003ctable\u003e\n\n\n\n\n\n\n\n\u003cthead valign=\"bottom\"\u003e\n\u003ctr\u003e\u003cth\u003eName\u003c/th\u003e\n\u003cth\u003eShort Name\u003c/th\u003e\n\u003cth\u003eVersion\u003c/th\u003e\n\u003cth\u003e2.x Trunk Mirror\u003c/th\u003e\n\u003cth\u003e3.x Trunk Mirror\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody valign=\"top\"\u003e\n\u003ctr\u003e\u003ctd\u003e\u003ca href=\"http://bazaar-vcs.org/\" rel=\"nofollow\"\u003eBazaar\u003c/a\u003e\u003c/td\u003e\n\u003ctd\u003ebzr\u003c/td\u003e\n\u003ctd\u003e1.12\u003c/td\u003e\n\u003ctd\u003e\u003ca href=\"http://code.python.org/python/trunk\" rel=\"nofollow\"\u003ehttp://code.python.org/python/trunk\u003c/a\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ca href=\"http://code.python.org/python/3.0\" rel=\"nofollow\"\u003ehttp://code.python.org/python/3.0\u003c/a\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003ca href=\"http://www.selenic.com/mercurial/\" rel=\"nofollow\"\u003eMercurial\u003c/a\u003e\u003c/td\u003e\n\u003ctd\u003ehg\u003c/td\u003e\n\u003ctd\u003e1.2.0\u003c/td\u003e\n\u003ctd\u003e\u003ca href=\"http://code.python.org/hg/trunk/\" rel=\"nofollow\"\u003ehttp://code.python.org/hg/trunk/\u003c/a\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ca href=\"http://code.python.org/hg/branches/py3k/\" rel=\"nofollow\"\u003ehttp://code.python.org/hg/branches/py3k/\u003c/a\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003ca href=\"http://www.git-scm.com/\" rel=\"nofollow\"\u003egit\u003c/a\u003e\u003c/td\u003e\n\u003ctd\u003eN/A\u003c/td\u003e\n\u003ctd\u003e1.6.1\u003c/td\u003e\n\u003ctd\u003egit://code.python.org/python/trunk\u003c/td\u003e\n\u003ctd\u003egit://code.python.org/python/branches/py3k\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\u003c/markdown-accessiblity-table\u003e\n\u003cp dir=\"auto\"\u003eThis PEP does not consider darcs, arch, or monotone. The main\nproblem with these DVCSs is that they are simply not popular enough\nto bother supporting when they do not provide some very compelling\nfeatures that the other DVCSs provide. Arch and darcs also have\nsignificant performance problems which seem unlikely to be addressed\nin the near future.\u003c/p\u003e\n\u003ca name=\"user-content-interoperability\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eInteroperability\u003c/h2\u003e\u003ca id=\"user-content-interoperability\" class=\"anchor\" aria-label=\"Permalink: Interoperability\" href=\"#interoperability\"\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 those who have already decided which DVCSs they want to use, and\nare willing to maintain local mirrors themselves, all three DVCSs\nsupport interchange via the git \"fast-import\" changeset format. git\ndoes so natively, of course, and native support for Bazaar is under\nactive development, and getting good early reviews as of mid-February\n2009. Mercurial has idiosyncratic support for importing via its \u003cem\u003ehg\nconvert\u003c/em\u003e command, and \u003ca href=\"http://repo.or.cz/r/fast-export.git/.git/description\" rel=\"nofollow\"\u003ethird-party fast-import support\u003c/a\u003e is available\nfor exporting. Also, the \u003ca href=\"http://progetti.arstecnica.it/tailor/\" rel=\"nofollow\"\u003eTailor\u003c/a\u003e tool supports automatic maintenance\nof mirrors based on an official repository in any of the candidate\nformats with a local mirror in any format.\u003c/p\u003e\n\u003ca name=\"user-content-usage-scenarios\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eUsage Scenarios\u003c/h2\u003e\u003ca id=\"user-content-usage-scenarios\" class=\"anchor\" aria-label=\"Permalink: Usage Scenarios\" href=\"#usage-scenarios\"\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\"\u003eProbably the best way to help decide on whether/which DVCS should\nreplace Subversion is to see what it takes to perform some\nreal-world usage scenarios that developers (core and non-core) have\nto work with. Each usage scenario outlines what it is, a bullet list\nof what the basic steps are (which can vary slightly per VCS), and\nhow to perform the usage scenario in the various VCSs\n(including Subversion).\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eEach VCS had a single author in charge of writing implementations\nfor each scenario (unless otherwise noted).\u003c/p\u003e\n\u003cmarkdown-accessiblity-table\u003e\u003ctable\u003e\n\n\n\n\n\u003cthead valign=\"bottom\"\u003e\n\u003ctr\u003e\u003cth\u003eName\u003c/th\u003e\n\u003cth\u003eVCS\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody valign=\"top\"\u003e\n\u003ctr\u003e\u003ctd\u003eBrett\u003c/td\u003e\n\u003ctd\u003esvn\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003eBarry\u003c/td\u003e\n\u003ctd\u003ebzr\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003eAlexandre\u003c/td\u003e\n\u003ctd\u003ehg\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003eStephen\u003c/td\u003e\n\u003ctd\u003egit\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\u003c/markdown-accessiblity-table\u003e\n\u003ca name=\"user-content-initial-setup\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eInitial Setup\u003c/h3\u003e\u003ca id=\"user-content-initial-setup\" class=\"anchor\" aria-label=\"Permalink: Initial Setup\" href=\"#initial-setup\"\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\"\u003eSome DVCSs have some perks if you do some initial setup upfront.\nThis section covers what can be done before any of the usage\nscenarios are run in order to take better advantage of the tools.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eAll of the DVCSs support configuring your project identification.\nUnlike the centralized systems, they use your email address to\nidentify your commits. (Access control is generally done by\nmechanisms external to the DVCS, such as ssh or console login).\nThis identity may be associated with a full name.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eAll of the DVCSs will query the system to get some approximation to\nthis information, but that may not be what you want. They also\nsupport setting this information on a per-user basis, and on a\nper-project basis. Convenience commands to set these attributes vary,\nbut all allow direct editing of configuration files.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eSome VCSs support end-of-line (EOL) conversions on checkout/checkin.\u003c/p\u003e\n\u003ca name=\"user-content-svn\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003esvn\u003c/h4\u003e\u003ca id=\"user-content-svn\" class=\"anchor\" aria-label=\"Permalink: svn\" href=\"#svn\"\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\"\u003eNone required, but it is recommended you follow the\n\u003ca href=\"http://www.python.org/dev/faq/#what-configuration-settings-should-i-use\" rel=\"nofollow\"\u003eguidelines\u003c/a\u003e\nin the dev FAQ.\u003c/p\u003e\n\u003ca name=\"user-content-bzr\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003ebzr\u003c/h4\u003e\u003ca id=\"user-content-bzr\" class=\"anchor\" aria-label=\"Permalink: bzr\" href=\"#bzr\"\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\"\u003eNo setup is required, but for much quicker and space-efficient local\nbranching, you should create a shared repository to hold all your\nPython branches. A shared repository is really just a parent\ndirectory containing a .bzr directory. When bzr commits a revision,\nit searches from the local directory on up the file system for a .bzr\ndirectory to hold the revision. By sharing revisions across multiple\nbranches, you cut down on the amount of disk space used. Do this:\u003c/p\u003e\n\u003cpre\u003ecd ~/projects\nbzr init-repo python\ncd python\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eNow, all your Python branches should be created inside of\n\u003ccode\u003e~/projects/python\u003c/code\u003e.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThere are also some settings you can put in your\n\u003ccode\u003e~/.bzr/bazaar.conf\u003c/code\u003e\nand \u003ccode\u003e~/.bzr/locations.conf\u003c/code\u003e file to set up defaults for interacting\nwith Python code. None of them are required, although some are\nrecommended. E.g. I would suggest gpg signing all commits, but that\nmight be too high a barrier for developers. Also, you can set up\ndefault push locations depending on where you want to push branches\nby default. If you have write access to the master branches, that\npush location could be code.python.org. Otherwise, it might be a\nfree Bazaar code hosting service such as Launchpad. If Bazaar is\nchosen, we should decide what the policies and recommendations are.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eAt a minimum, I would set up your email address:\u003c/p\u003e\n\u003cpre\u003ebzr whoami \"Firstname Lastname \u0026lt;email.address@example.com\u0026gt;\"\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eAs with hg and git below, there are ways to set your email address (or really,\njust about any parameter) on a\nper-repository basis. You do this with settings in your\n\u003ccode\u003e$HOME/.bazaar/locations.conf\u003c/code\u003e file, which has an ini-style format as does\nthe other DVCSs. See the Bazaar documentation for details,\nwhich mostly aren't relevant for this discussion.\u003c/p\u003e\n\u003ca name=\"user-content-hg\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003ehg\u003c/h4\u003e\u003ca id=\"user-content-hg\" class=\"anchor\" aria-label=\"Permalink: hg\" href=\"#hg\"\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\"\u003eMinimally, you should set your user name. To do so, create the file\n\u003ccode\u003e.hgrc\u003c/code\u003e in your home directory and add the following:\u003c/p\u003e\n\u003cpre\u003e[ui]\nusername = Firstname Lastname \u0026lt;email.address@example.com\u0026gt;\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eIf you are using Windows and your tools do not support Unix-style newlines,\nyou can enable automatic newline translation by adding to your configuration:\u003c/p\u003e\n\u003cpre\u003e[extensions]\nwin32text =\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eThese options can also be set locally to a given repository by\ncustomizing \u003ccode\u003e\u0026lt;repo\u0026gt;/.hg/hgrc\u003c/code\u003e, instead of \u003ccode\u003e~/.hgrc\u003c/code\u003e.\u003c/p\u003e\n\u003ca name=\"user-content-id1\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003egit\u003c/h4\u003e\u003ca id=\"user-content-git\" class=\"anchor\" aria-label=\"Permalink: git\" href=\"#git\"\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\"\u003eNone needed. However, git supports a number of features that can\nsmooth your work, with a little preparation. git supports setting\ndefaults at the workspace, user, and system levels. The system\nlevel is out of scope of this PEP. The user configuration file is\n\u003ccode\u003e$HOME/.gitconfig\u003c/code\u003e on Unix-like systems, and the workspace\nconfiguration file is \u003ccode\u003e$REPOSITORY/.git/config\u003c/code\u003e.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eYou can use the \u003ccode\u003egit-config\u003c/code\u003e tool to set preferences for user.name and\nuser.email either globally (for your system login account) or\nlocally (to a given git working copy), or you can edit the\nconfiguration files (which have the same format as shown in the\nMercurial section above).:\u003c/p\u003e\n\u003cpre\u003e# my full name doesn't change\n# note \"--global\" flag means per user\n# (system-wide configuration is set with \"--system\")\ngit config --global user.name 'Firstname Lastname'\n# but use my Pythonic email address\ncd /path/to/python/repository\ngit config user.email email.address@python.example.com\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eIf you are using Windows, you probably want to set the core.autocrlf\nand core.safecrlf preferences to true using \u003ccode\u003egit-config\u003c/code\u003e.:\u003c/p\u003e\n\u003cpre\u003e# check out files with CRLF line endings rather than Unix-style LF only\ngit config --global core.autocrlf true\n# scream if a transformation would be ambiguous\n# (eg, a working file contains both naked LF and CRLF)\n# and check them back in with the reverse transformation\ngit config --global core.safecrlf true\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eAlthough the repository will usually contain a .gitignore file\nspecifying file names that rarely if ever should be registered in the\nVCS, you may have personal conventions (e.g., always editing log\nmessages in a temporary file named \".msg\") that you may wish to\nspecify.:\u003c/p\u003e\n\u003cpre\u003e# tell git where my personal ignores are\ngit config --global core.excludesfile ~/.gitignore\n# I use .msg for my long commit logs, and Emacs makes backups in\n# files ending with ~\n# these are globs, not regular expressions\necho '*~' \u0026gt;\u0026gt; ~/.gitignore\necho '.msg' \u0026gt;\u0026gt; ~/.gitignore\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eIf you use multiple branches, as with the other VCSes, you can save a\nlot of space by putting all objects in a common object store. This\nalso can save download time, if the origins of the branches were in\ndifferent repositories, because objects are shared across branches in\nyour repository even if they were not present in the upstream\nrepositories. git is very space- and time-efficient and applies a\nnumber of optimizations automatically, so this configuration is\noptional. (Examples are omitted.)\u003c/p\u003e\n\u003ca name=\"user-content-one-off-checkout\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eOne-Off Checkout\u003c/h3\u003e\u003ca id=\"user-content-one-off-checkout\" class=\"anchor\" aria-label=\"Permalink: One-Off Checkout\" href=\"#one-off-checkout\"\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\"\u003eAs a non-core developer, I want to create and publish a one-off patch\nthat fixes a bug, so that a core developer can review it for\ninclusion in the mainline.\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eCheckout/branch/clone trunk.\u003c/li\u003e\n\u003cli\u003eEdit some code.\u003c/li\u003e\n\u003cli\u003eGenerate a patch (based on what is best supported by the VCS, e.g.\nbranch history).\u003c/li\u003e\n\u003cli\u003eReceive reviewer comments and address the issues.\u003c/li\u003e\n\u003cli\u003eGenerate a second patch for the core developer to commit.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ca name=\"user-content-id2\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003esvn\u003c/h4\u003e\u003ca id=\"user-content-svn-1\" class=\"anchor\" aria-label=\"Permalink: svn\" href=\"#svn-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\u003cpre\u003esvn checkout http://svn.python.org/projects/python/trunk\ncd trunk\n# Edit some code.\necho \"The cake is a lie!\" \u0026gt; README\n# Since svn lacks support for local commits, we fake it with patches.\nsvn diff \u0026gt;\u0026gt; commit-1.diff\nsvn diff \u0026gt;\u0026gt; patch-1.diff\n# Upload the patch-1 to bugs.python.org.\n# Receive reviewer comments.\n# Edit some code.\necho \"The cake is real!\" \u0026gt; README\n# Since svn lacks support for local commits, we fake it with patches.\nsvn diff \u0026gt;\u0026gt; commit-2.diff\nsvn diff \u0026gt;\u0026gt; patch-2.diff\n# Upload patch-2 to bugs.python.org\n\u003c/pre\u003e\n\u003ca name=\"user-content-id3\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003ebzr\u003c/h4\u003e\u003ca id=\"user-content-bzr-1\" class=\"anchor\" aria-label=\"Permalink: bzr\" href=\"#bzr-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\u003cpre\u003ebzr branch http://code.python.org/python/trunk\ncd trunk\n# Edit some code.\nbzr commit -m 'Stuff I did'\nbzr send -o bundle\n# Upload bundle to bugs.python.org\n# Receive reviewer comments\n# Edit some code\nbzr commit -m 'Respond to reviewer comments'\nbzr send -o bundle\n# Upload updated bundle to bugs.python.org\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003ebundle\u003c/code\u003e file is like a super-patch. It can be read by \u003ccode\u003epatch(1)\u003c/code\u003e but\nit contains additional metadata so that it can be fed to \u003ccode\u003ebzr merge\u003c/code\u003e to\nproduce a fully usable branch completely with history. See \u003ca href=\"#patch-review\"\u003ePatch Review\u003c/a\u003e\nsection below.\u003c/p\u003e\n\u003ca name=\"user-content-id4\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003ehg\u003c/h4\u003e\u003ca id=\"user-content-hg-1\" class=\"anchor\" aria-label=\"Permalink: hg\" href=\"#hg-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\u003cpre\u003ehg clone http://code.python.org/hg/trunk\ncd trunk\n# Edit some code.\nhg commit -m \"Stuff I did\"\nhg outgoing -p \u0026gt; fixes.patch\n# Upload patch to bugs.python.org\n# Receive reviewer comments\n# Edit some code\nhg commit -m \"Address reviewer comments.\"\nhg outgoing -p \u0026gt; additional-fixes.patch\n# Upload patch to bugs.python.org\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eWhile \u003ccode\u003ehg outgoing\u003c/code\u003e does not have the flag for it, most Mercurial\ncommands support git's extended patch format through a \u003ccode\u003e--git\u003c/code\u003e\ncommand. This can be set in one's \u003ccode\u003e.hgrc\u003c/code\u003e file so that all commands\nthat generate a patch use the extended format.\u003c/p\u003e\n\u003ca name=\"user-content-id5\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003egit\u003c/h4\u003e\u003ca id=\"user-content-git-1\" class=\"anchor\" aria-label=\"Permalink: git\" href=\"#git-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\"\u003eThe patches could be created with\n\u003ccode\u003egit diff master \u0026gt; stuff-i-did.patch\u003c/code\u003e, too, but\n\u003ccode\u003egit format-patch | git am\u003c/code\u003e knows some tricks\n(empty files, renames, etc) that ordinary patch can't handle. git\ngrabs \"Stuff I did\" out of the commit message to create the file\nname 0001-Stuff-I-did.patch. See Patch Review below for a\ndescription of the git-format-patch format.\u003c/p\u003e\n\u003cpre\u003e# Get the mainline code.\ngit clone git://code.python.org/python/trunk\ncd trunk\n# Edit some code.\ngit commit -a -m 'Stuff I did.'\n# Create patch for my changes (i.e, relative to master).\ngit format-patch master\ngit tag stuff-v1\n# Upload 0001-Stuff-I-did.patch to bugs.python.org.\n# Time passes ... receive reviewer comments.\n# Edit more code.\ngit commit -a -m 'Address reviewer comments.'\n# Make an add-on patch to apply on top of the original.\ngit format-patch stuff-v1\n# Upload 0001-Address-reviewer-comments.patch to bugs.python.org.\n\u003c/pre\u003e\n\u003ca name=\"user-content-backing-out-changes\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eBacking Out Changes\u003c/h3\u003e\u003ca id=\"user-content-backing-out-changes\" class=\"anchor\" aria-label=\"Permalink: Backing Out Changes\" href=\"#backing-out-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\"\u003eAs a core developer, I want to undo a change that was not ready for\ninclusion in the mainline.\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eBack out the unwanted change.\u003c/li\u003e\n\u003cli\u003ePush patch to server.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ca name=\"user-content-id6\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003esvn\u003c/h4\u003e\u003ca id=\"user-content-svn-2\" class=\"anchor\" aria-label=\"Permalink: svn\" href=\"#svn-2\"\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\u003cpre\u003e# Assume the change to revert is in revision 40\nsvn merge -c -40 .\n# Resolve conflicts, if any.\nsvn commit -m \"Reverted revision 40\"\n\u003c/pre\u003e\n\u003ca name=\"user-content-id7\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003ebzr\u003c/h4\u003e\u003ca id=\"user-content-bzr-2\" class=\"anchor\" aria-label=\"Permalink: bzr\" href=\"#bzr-2\"\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\u003cpre\u003e# Assume the change to revert is in revision 40\nbzr merge -r 40..39\n# Resolve conflicts, if any.\nbzr commit -m \"Reverted revision 40\"\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eNote that if the change you want revert is the last one that was\nmade, you can just use \u003ccode\u003ebzr uncommit\u003c/code\u003e.\u003c/p\u003e\n\u003ca name=\"user-content-id8\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003ehg\u003c/h4\u003e\u003ca id=\"user-content-hg-2\" class=\"anchor\" aria-label=\"Permalink: hg\" href=\"#hg-2\"\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\u003cpre\u003e# Assume the change to revert is in revision 9150dd9c6d30\nhg backout --merge -r 9150dd9c6d30\n# Resolve conflicts, if any.\nhg commit -m \"Reverted changeset 9150dd9c6d30\"\nhg push\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eNote, you can use \"hg rollback\" and \"hg strip\" to revert changes you committed\nin your local repository, but did not yet push to other repositories.\u003c/p\u003e\n\u003ca name=\"user-content-id9\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003egit\u003c/h4\u003e\u003ca id=\"user-content-git-2\" class=\"anchor\" aria-label=\"Permalink: git\" href=\"#git-2\"\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\u003cpre\u003e# Assume the change to revert is the grandfather of a revision tagged \"newhotness\".\ngit revert newhotness~2\n# Resolve conflicts if any. If there are no conflicts, the commit\n# will be done automatically by \"git revert\", which prompts for a log.\ngit commit -m \"Reverted changeset 9150dd9c6d30.\"\ngit push\n\u003c/pre\u003e\n\u003ca name=\"user-content-patch-review\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003ePatch Review\u003c/h3\u003e\u003ca id=\"user-content-patch-review\" class=\"anchor\" aria-label=\"Permalink: Patch Review\" href=\"#patch-review\"\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\"\u003eAs a core developer, I want to review patches submitted by other\npeople, so that I can make sure that only approved changes are added\nto Python.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eCore developers have to review patches as submitted by other people.\nThis requires applying the patch, testing it, and then tossing away\nthe changes. The assumption can be made that a core developer already\nhas a checkout/branch/clone of the trunk.\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eBranch off of trunk.\u003c/li\u003e\n\u003cli\u003eApply patch w/o any comments as generated by the patch submitter.\u003c/li\u003e\n\u003cli\u003ePush patch to server.\u003c/li\u003e\n\u003cli\u003eDelete now-useless branch.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ca name=\"user-content-id10\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003esvn\u003c/h4\u003e\u003ca id=\"user-content-svn-3\" class=\"anchor\" aria-label=\"Permalink: svn\" href=\"#svn-3\"\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\"\u003eSubversion does not exactly fit into this development style very well\nas there are no such thing as a \"branch\" as has been defined in this\nPEP. Instead a developer either needs to create another checkout for\ntesting a patch or create a branch on the server. Up to this point,\ncore developers have not taken the \"branch on the server\" approach to\ndealing with individual patches. For this scenario the assumption\nwill be the developer creates a local checkout of the trunk to work\nwith.:\u003c/p\u003e\n\u003cpre\u003ecp -r trunk issue0000\ncd issue0000\npatch -p0 \u0026lt; __patch__\n# Review patch.\nsvn commit -m \"Some patch.\"\ncd ..\nrm -r issue0000\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eAnother option is to only have a single checkout running at any one\ntime and use \u003ccode\u003esvn diff\u003c/code\u003e along with \u003ccode\u003esvn revert -R\u003c/code\u003e to store away\nindependent changes you may have made.\u003c/p\u003e\n\u003ca name=\"user-content-id11\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003ebzr\u003c/h4\u003e\u003ca id=\"user-content-bzr-3\" class=\"anchor\" aria-label=\"Permalink: bzr\" href=\"#bzr-3\"\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\u003cpre\u003ebzr branch trunk issueNNNN\n# Download `patch` bundle from Roundup\nbzr merge patch\n# Review patch\nbzr commit -m'Patch NNN by So N. So' --fixes python:NNNN\nbzr push bzr+ssh://me@code.python.org/trunk\nrm -rf ../issueNNNN\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eAlternatively, since you're probably going to commit these changes to\nthe trunk, you could just do a checkout. That would give you a local\nworking tree while the branch (i.e. all revisions) would continue to\nlive on the server. This is similar to the svn model and might allow\nyou to more quickly review the patch. There's no need for the push\nin this case.:\u003c/p\u003e\n\u003cpre\u003ebzr checkout trunk issueNNNN\n# Download `patch` bundle from Roundup\nbzr merge patch\n# Review patch\nbzr commit -m'Patch NNNN by So N. So' --fixes python:NNNN\nrm -rf ../issueNNNN\n\u003c/pre\u003e\n\u003ca name=\"user-content-id12\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003ehg\u003c/h4\u003e\u003ca id=\"user-content-hg-3\" class=\"anchor\" aria-label=\"Permalink: hg\" href=\"#hg-3\"\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\u003cpre\u003ehg clone trunk issue0000\ncd issue0000\n# If the patch was generated using hg export, the user name of the\n# submitter is automatically recorded. Otherwise,\n# use hg import --no-commit submitted.diff and commit with\n# hg commit -u \"Firstname Lastname \u0026lt;email.address@example.com\u0026gt;\"\nhg import submitted.diff\n# Review patch.\nhg push ssh://alexandre@code.python.org/hg/trunk/\n\u003c/pre\u003e\n\u003ca name=\"user-content-id13\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003egit\u003c/h4\u003e\u003ca id=\"user-content-git-3\" class=\"anchor\" aria-label=\"Permalink: git\" href=\"#git-3\"\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\"\u003eWe assume a patch created by git-format-patch. This is a Unix mbox\nfile containing one or more patches, each formatted as an \u003ca href=\"http://tools.ietf.org/html/rfc2822.html\" rel=\"nofollow\"\u003eRFC 2822\u003c/a\u003e\nmessage. git-am interprets each message as a commit as follows. The\nauthor of the patch is taken from the From: header, the date from the\nDate header. The commit log is created by concatenating the content\nof the subject line, a blank line, and the message body up to the\nstart of the patch.:\u003c/p\u003e\n\u003cpre\u003ecd trunk\n# Create a branch in case we don't like the patch.\n# This checkout takes zero time, since the workspace is left in\n# the same state as the master branch.\ngit checkout -b patch-review\n# Download patch from bugs.python.org to submitted.patch.\ngit am \u0026lt; submitted.patch\n# Review and approve patch.\n# Merge into master and push.\ngit checkout master\ngit merge patch-review\ngit push\n\u003c/pre\u003e\n\u003ca name=\"user-content-backport\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eBackport\u003c/h3\u003e\u003ca id=\"user-content-backport\" class=\"anchor\" aria-label=\"Permalink: Backport\" href=\"#backport\"\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\"\u003eAs a core developer, I want to apply a patch to 2.6, 2.7, 3.0, and 3.1\nso that I can fix a problem in all three versions.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThanks to always having the cutting-edge and the latest release\nversion under development, Python currently has four branches being\nworked on simultaneously. That makes it important for a change to\npropagate easily through various branches.\u003c/p\u003e\n\u003ca name=\"user-content-id14\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003esvn\u003c/h4\u003e\u003ca id=\"user-content-svn-4\" class=\"anchor\" aria-label=\"Permalink: svn\" href=\"#svn-4\"\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 of Python's use of svnmerge, changes start with the trunk\n(2.7) and then get merged to the release version of 2.6. To get the\nchange into the 3.x series, the change is merged into 3.1, fixed up,\nand then merged into 3.0 (2.7 -\u0026gt; 2.6; 2.7 -\u0026gt; 3.1 -\u0026gt; 3.0).\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThis is in contrast to a port-forward strategy where the patch would\nhave been added to 2.6 and then pulled forward into newer versions\n(2.6 -\u0026gt; 2.7 -\u0026gt; 3.0 -\u0026gt; 3.1).\u003c/p\u003e\n\u003cpre\u003e# Assume patch applied to 2.7 in revision 0000.\ncd release26-maint\nsvnmerge merge -r 0000\n# Resolve merge conflicts and make sure patch works.\nsvn commit -F svnmerge-commit-message.txt # revision 0001.\ncd ../py3k\nsvnmerge merge -r 0000\n# Same as for 2.6, except Misc/NEWS changes are reverted.\nsvn revert Misc/NEWS\nsvn commit -F svnmerge-commit-message.txt # revision 0002.\ncd ../release30-maint\nsvnmerge merge -r 0002\nsvn commit -F svnmerge-commit-message.txt # revision 0003.\n\u003c/pre\u003e\n\u003ca name=\"user-content-id15\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003ebzr\u003c/h4\u003e\u003ca id=\"user-content-bzr-4\" class=\"anchor\" aria-label=\"Permalink: bzr\" href=\"#bzr-4\"\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\"\u003eBazaar is pretty straightforward here, since it supports cherry\npicking revisions manually. In the example below, we could have\ngiven a revision id instead of a revision number, but that's usually\nnot necessary. Martin Pool suggests \"We'd generally recommend doing\nthe fix first in the oldest supported branch, and then merging it\nforward to the later releases.\":\u003c/p\u003e\n\u003cpre\u003e# Assume patch applied to 2.7 in revision 0000\ncd release26-maint\nbzr merge ../trunk -c 0000\n# Resolve conflicts and make sure patch works\nbzr commit -m 'Back port patch NNNN'\nbzr push bzr+ssh://me@code.python.org/trunk\ncd ../py3k\nbzr merge ../trunk -r 0000\n# Same as for 2.6 except Misc/NEWS changes are reverted\nbzr revert Misc/NEWS\nbzr commit -m 'Forward port patch NNNN'\nbzr push bzr+ssh://me@code.python.org/py3k\n\u003c/pre\u003e\n\u003ca name=\"user-content-id16\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003ehg\u003c/h4\u003e\u003ca id=\"user-content-hg-4\" class=\"anchor\" aria-label=\"Permalink: hg\" href=\"#hg-4\"\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\"\u003eMercurial, like other DVCS, does not well support the current\nworkflow used by Python core developers to backport patches. Right\nnow, bug fixes are first applied to the development mainline\n(i.e., trunk), then back-ported to the maintenance branches and\nforward-ported, as necessary, to the py3k branch. This workflow\nrequires the ability to cherry-pick individual changes. Mercurial's\ntransplant extension provides this ability. Here is an example of\nthe scenario using this workflow:\u003c/p\u003e\n\u003cpre\u003ecd release26-maint\n# Assume patch applied to 2.7 in revision 0000\nhg transplant -s ../trunk 0000\n# Resolve conflicts, if any.\ncd ../py3k\nhg pull ../trunk\nhg merge\nhg revert Misc/NEWS\nhg commit -m \"Merged trunk\"\nhg push\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eIn the above example, transplant acts much like the current svnmerge\ncommand. When transplant is invoked without the revision, the command\nlaunches an interactive loop useful for transplanting multiple\nchanges. Another useful feature is the --filter option which can be\nused to modify changesets programmatically (e.g., it could be used\nfor removing changes to Misc/NEWS automatically).\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eAlternatively to the traditional workflow, we could avoid\ntransplanting changesets by committing bug fixes to the oldest\nsupported release, then merge these fixes upward to the more recent\nbranches.\u003c/p\u003e\n\u003cpre\u003ecd release25-maint\nhg import fix_some_bug.diff\n# Review patch and run test suite. Revert if failure.\nhg push\ncd ../release26-maint\nhg pull ../release25-maint\nhg merge\n# Resolve conflicts, if any. Then, review patch and run test suite.\nhg commit -m \"Merged patches from release25-maint.\"\nhg push\ncd ../trunk\nhg pull ../release26-maint\nhg merge\n# Resolve conflicts, if any, then review.\nhg commit -m \"Merged patches from release26-maint.\"\nhg push\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eAlthough this approach makes the history non-linear and slightly\nmore difficult to follow, it encourages fixing bugs across all\nsupported releases. Furthermore, it scales better when there is many\nchanges to backport, because we do not need to seek the specific\nrevision IDs to merge.\u003c/p\u003e\n\u003ca name=\"user-content-id17\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003egit\u003c/h4\u003e\u003ca id=\"user-content-git-4\" class=\"anchor\" aria-label=\"Permalink: git\" href=\"#git-4\"\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 git I would have a workspace which contains all of\nthe relevant master repository branches. git cherry-pick doesn't\nwork across repositories; you need to have the branches in the same\nrepository.\u003c/p\u003e\n\u003cpre\u003e# Assume patch applied to 2.7 in revision release27~3 (4th patch back from tip).\ncd integration\ngit checkout release26\ngit cherry-pick release27~3\n# If there are conflicts, resolve them, and commit those changes.\n# git commit -a -m \"Resolve conflicts.\"\n# Run test suite. If fixes are necessary, record as a separate commit.\n# git commit -a -m \"Fix code causing test failures.\"\ngit checkout master\ngit cherry-pick release27~3\n# Do any conflict resolution and test failure fixups.\n# Revert Misc/NEWS changes.\ngit checkout HEAD^ -- Misc/NEWS\ngit commit -m 'Revert cherry-picked Misc/NEWS changes.' Misc/NEWS\n# Push both ports.\ngit push release26 master\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eIf you are regularly merging (rather than cherry-picking) from a\ngiven branch, then you can block a given commit from being\naccidentally merged in the future by merging, then reverting it.\nThis does not prevent a cherry-pick from pulling in the unwanted\npatch, and this technique requires blocking everything that you don't\nwant merged. I'm not sure if this differs from svn on this point.\u003c/p\u003e\n\u003cpre\u003ecd trunk\n# Merge in the alpha tested code.\ngit merge experimental-branch\n# We don't want the 3rd-to-last commit from the experimental-branch,\n# and we don't want it to ever be merged.\n# The notation \"^N\" means Nth parent of the current commit. Thus HEAD^2^1^1\n# means the first parent of the first parent of the second parent of HEAD.\ngit revert HEAD^2^1^1\n# Propagate the merge and the prohibition to the public repository.\ngit push\n\u003c/pre\u003e\n\u003ca name=\"user-content-coordinated-development-of-a-new-feature\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eCoordinated Development of a New Feature\u003c/h3\u003e\u003ca id=\"user-content-coordinated-development-of-a-new-feature\" class=\"anchor\" aria-label=\"Permalink: Coordinated Development of a New Feature\" href=\"#coordinated-development-of-a-new-feature\"\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\"\u003eSometimes core developers end up working on a major feature with\nseveral developers. As a core developer, I want to be able to\npublish feature branches to a common public location so that I can\ncollaborate with other developers.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThis requires creating a branch on a server that other developers\ncan access. All of the DVCSs support creating new repositories on\nhosts where the developer is already able to commit, with\nappropriate configuration of the repository host. This is\nsimilar in concept to the existing sandbox in svn, although details\nof repository initialization may differ.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eFor non-core developers, there are various more-or-less public-access\nrepository-hosting services.\nBazaar has\n\u003ca href=\"http://www.launchpad.net/\" rel=\"nofollow\"\u003eLaunchpad\u003c/a\u003e,\nMercurial has\n\u003ca href=\"http://www.bitbucket.org/\" rel=\"nofollow\"\u003ebitbucket.org\u003c/a\u003e,\nand git has\n\u003ca href=\"http://www.github.com/\"\u003eGitHub\u003c/a\u003e.\nAll also have easy-to-use\nCGI interfaces for developers who maintain their own servers.\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eBranch trunk.\u003c/li\u003e\n\u003cli\u003ePull from branch on the server.\u003c/li\u003e\n\u003cli\u003ePull from trunk.\u003c/li\u003e\n\u003cli\u003ePush merge to trunk.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ca name=\"user-content-id18\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003esvn\u003c/h4\u003e\u003ca id=\"user-content-svn-5\" class=\"anchor\" aria-label=\"Permalink: svn\" href=\"#svn-5\"\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\u003cpre\u003e# Create branch.\nsvn copy svn+ssh://pythondev@svn.python.org/python/trunk svn+ssh://pythondev@svn.python.org/python/branches/NewHotness\nsvn checkout svn+ssh://pythondev@svn.python.org/python/branches/NewHotness\ncd NewHotness\nsvnmerge init\nsvn commit -m \"Initialize svnmerge.\"\n# Pull in changes from other developers.\nsvn update\n# Pull in trunk and merge to the branch.\nsvnmerge merge\nsvn commit -F svnmerge-commit-message.txt\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eThis scenario is incomplete as the decision for what DVCS to go with\nwas made before the work was complete.\u003c/p\u003e\n\u003ca name=\"user-content-separation-of-issue-dependencies\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eSeparation of Issue Dependencies\u003c/h3\u003e\u003ca id=\"user-content-separation-of-issue-dependencies\" class=\"anchor\" aria-label=\"Permalink: Separation of Issue Dependencies\" href=\"#separation-of-issue-dependencies\"\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\"\u003eSometimes, while working on an issue, it becomes apparent that the\nproblem being worked on is actually a compound issue of various\nsmaller issues. Being able to take the current work and then begin\nworking on a separate issue is very helpful to separate out issues\ninto individual units of work instead of compounding them into a\nsingle, large unit.\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eCreate a branch A (e.g. urllib has a bug).\u003c/li\u003e\n\u003cli\u003eEdit some code.\u003c/li\u003e\n\u003cli\u003eCreate a new branch B that branch A depends on (e.g. the urllib\nbug exposes a socket bug).\u003c/li\u003e\n\u003cli\u003eEdit some code in branch B.\u003c/li\u003e\n\u003cli\u003eCommit branch B.\u003c/li\u003e\n\u003cli\u003eEdit some code in branch A.\u003c/li\u003e\n\u003cli\u003eCommit branch A.\u003c/li\u003e\n\u003cli\u003eClean up.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ca name=\"user-content-id19\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003esvn\u003c/h4\u003e\u003ca id=\"user-content-svn-6\" class=\"anchor\" aria-label=\"Permalink: svn\" href=\"#svn-6\"\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\"\u003eTo make up for svn's lack of cheap branching, it has a changelist\noption to associate a file with a single changelist. This is not as\npowerful as being able to associate at the commit level. There is\nalso no way to express dependencies between changelists.\u003c/p\u003e\n\u003cpre\u003ecp -r trunk issue0000\ncd issue0000\n# Edit some code.\necho \"The cake is a lie!\" \u0026gt; README\nsvn changelist A README\n# Edit some other code.\necho \"I own Python!\" \u0026gt; LICENSE\nsvn changelist B LICENSE\nsvn ci -m \"Tell it how it is.\" --changelist B\n# Edit changelist A some more.\nsvn ci -m \"Speak the truth.\" --changelist A\ncd ..\nrm -rf issue0000\n\u003c/pre\u003e\n\u003ca name=\"user-content-id20\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003ebzr\u003c/h4\u003e\u003ca id=\"user-content-bzr-5\" class=\"anchor\" aria-label=\"Permalink: bzr\" href=\"#bzr-5\"\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\"\u003eHere's an approach that uses bzr shelf (now a standard part of bzr)\nto squirrel away some changes temporarily while you take a detour to\nfix the socket bugs.\u003c/p\u003e\n\u003cpre\u003ebzr branch trunk bug-0000\ncd bug-0000\n# Edit some code. Dang, we need to fix the socket module.\nbzr shelve --all\n# Edit some code.\nbzr commit -m \"Socket module fixes\"\n# Detour over, now resume fixing urllib\nbzr unshelve\n# Edit some code\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eAnother approach uses the loom plugin. Looms can\ngreatly simplify working on dependent branches because they\nautomatically take care of the stacking dependencies for you.\nImagine looms as a stack of dependent branches (called \"threads\" in\nloom parlance), with easy ways to move up and down the stack of\nthreads, merge changes up the stack to descendant threads, create\ndiffs between threads, etc. Occasionally, you may need or want to\nexport your loom threads into separate branches, either for review\nor commit. Higher threads incorporate all the changes in the lower\nthreads, automatically.\u003c/p\u003e\n\u003cpre\u003ebzr branch trunk bug-0000\ncd bug-0000\nbzr loomify --base trunk\nbzr create-thread fix-urllib\n# Edit some code. Dang, we need to fix the socket module first.\nbzr commit -m \"Checkpointing my work so far\"\nbzr down-thread\nbzr create-thread fix-socket\n# Edit some code\nbzr commit -m \"Socket module fixes\"\nbzr up-thread\n# Manually resolve conflicts if necessary\nbzr commit -m 'Merge in socket fixes'\n# Edit me some more code\nbzr commit -m \"Now that socket is fixed, complete the urllib fixes\"\nbzr record done\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eFor bonus points, let's say someone else fixes the socket module in\nexactly the same way you just did. Perhaps this person even grabbed your\nfix-socket thread and applied just that to the trunk. You'd like to\nbe able to merge their changes into your loom and delete your\nnow-redundant fix-socket thread.\u003c/p\u003e\n\u003cpre\u003ebzr down-thread trunk\n# Get all new revisions to the trunk. If you've done things\n# correctly, this will succeed without conflict.\nbzr pull\nbzr up-thread\n# See? The fix-socket thread is now identical to the trunk\nbzr commit -m 'Merge in trunk changes'\nbzr diff -r thread: | wc -l # returns 0\nbzr combine-thread\nbzr up-thread\n# Resolve any conflicts\nbzr commit -m 'Merge trunk'\n# Now our top-thread has an up-to-date trunk and just the urllib fix.\n\u003c/pre\u003e\n\u003ca name=\"user-content-id21\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003ehg\u003c/h4\u003e\u003ca id=\"user-content-hg-5\" class=\"anchor\" aria-label=\"Permalink: hg\" href=\"#hg-5\"\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\"\u003eOne approach is to use the shelve extension; this extension is not included\nwith Mercurial, but it is easy to install. With shelve, you can select changes\nto put temporarily aside.\u003c/p\u003e\n\u003cpre\u003ehg clone trunk issue0000\ncd issue0000\n# Edit some code (e.g. urllib).\nhg shelve\n# Select changes to put aside\n# Edit some other code (e.g. socket).\nhg commit\nhg unshelve\n# Complete initial fix.\nhg commit\ncd ../trunk\nhg pull ../issue0000\nhg merge\nhg commit\nrm -rf ../issue0000\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eSeveral other way to approach this scenario with Mercurial. Alexander Solovyov\npresented a few \u003ca href=\"http://selenic.com/pipermail/mercurial/2009-January/023710.html\" rel=\"nofollow\"\u003ealternative approaches\u003c/a\u003e on Mercurial's mailing list.\u003c/p\u003e\n\u003ca name=\"user-content-id22\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003egit\u003c/h4\u003e\u003ca id=\"user-content-git-5\" class=\"anchor\" aria-label=\"Permalink: git\" href=\"#git-5\"\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\u003cpre\u003ecd trunk\n# Edit some code in urllib.\n# Discover a bug in socket, want to fix that first.\n# So save away our current work.\ngit stash\n# Edit some code, commit some changes.\ngit commit -a -m \"Completed fix of socket.\"\n# Restore the in-progress work on urllib.\ngit stash apply\n# Edit me some more code, commit some more fixes.\ngit commit -a -m \"Complete urllib fixes.\"\n# And push both patches to the public repository.\ngit push\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eBonus points: suppose you took your time, and someone else fixes\nsocket in the same way you just did, and landed that in the trunk. In\nthat case, your push will fail because your branch is not up-to-date.\nIf the fix was a one-liner, there's a very good chance that it's\n\u003cem\u003eexactly\u003c/em\u003e the same, character for character. git would notice that,\nand you are done; git will silently merge them.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eSuppose we're not so lucky:\u003c/p\u003e\n\u003cpre\u003e# Update your branch.\ngit pull git://code.python.org/public/trunk master\n\n# git has fetched all the necessary data, but reports that the\n# merge failed. We discover the nearly-duplicated patch.\n# Neither our version of the master branch nor the workspace has\n# been touched. Revert our socket patch and pull again:\ngit revert HEAD^\ngit pull git://code.python.org/public/trunk master\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eLike Bazaar and Mercurial, git has extensions to manage stacks of\npatches. You can use the original Quilt by Andrew Morton, or there is\nStGit (\"stacked git\") which integrates patch-tracking for large sets\nof patches into the VCS in a way similar to Mercurial Queues or Bazaar\nlooms.\u003c/p\u003e\n\u003ca name=\"user-content-doing-a-python-release\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eDoing a Python Release\u003c/h3\u003e\u003ca id=\"user-content-doing-a-python-release\" class=\"anchor\" aria-label=\"Permalink: Doing a Python Release\" href=\"#doing-a-python-release\"\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\"\u003eHow does \u003ca href=\"http://www.python.org/dev/peps/pep-0101\" rel=\"nofollow\"\u003ePEP 101\u003c/a\u003e change when using a DVCS?\u003c/p\u003e\n\u003ca name=\"user-content-id23\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003ebzr\u003c/h4\u003e\u003ca id=\"user-content-bzr-6\" class=\"anchor\" aria-label=\"Permalink: bzr\" href=\"#bzr-6\"\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\"\u003eIt will change, but not substantially so. When doing the\nmaintenance branch, we'll just push to the new location instead of\ndoing an svn cp. Tags are totally different, since in svn they are\ndirectory copies, but in bzr (and I'm guessing hg), they are just\nsymbolic names for revisions on a particular branch. The release.py\nscript will have to change to use bzr commands instead. It's\npossible that because DVCS (in particular, bzr) does cherry picking\nand merging well enough that we'll be able to create the maint\nbranches sooner. It would be a useful exercise to try to do a\nrelease off the bzr/hg mirrors.\u003c/p\u003e\n\u003ca name=\"user-content-id24\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003ehg\u003c/h4\u003e\u003ca id=\"user-content-hg-6\" class=\"anchor\" aria-label=\"Permalink: hg\" href=\"#hg-6\"\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\"\u003eClearly, details specific to Subversion in \u003ca href=\"http://www.python.org/dev/peps/pep-0101\" rel=\"nofollow\"\u003ePEP 101\u003c/a\u003e and in the\nrelease script will need to be updated. In particular, release\ntagging and maintenance branches creation process will have to be\nmodified to use Mercurial's features; this will simplify and\nstreamline certain aspects of the release process. For example,\ntagging and re-tagging a release will become a trivial operation\nsince a tag, in Mercurial, is simply a symbolic name for a given\nrevision.\u003c/p\u003e\n\u003ca name=\"user-content-id25\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003egit\u003c/h4\u003e\u003ca id=\"user-content-git-6\" class=\"anchor\" aria-label=\"Permalink: git\" href=\"#git-6\"\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\"\u003eIt will change, but not substantially so. When doing the\nmaintenance branch, we'll just git push to the new location instead\nof doing an svn cp. Tags are totally different, since in svn they\nare directory copies, but in git they are just symbolic names for\nrevisions, as are branches. (The difference between a tag and a\nbranch is that tags refer to a particular commit, and will never\nchange unless you use git tag -f to force them to move. The\nchecked-out branch, on the other hand, is automatically updated by\ngit commit.) The release.py script will have to change to use git\ncommands instead. With git I would create a (local) maintenance\nbranch as soon as the release engineer is chosen. Then I'd \"git\npull\" until I didn't like a patch, when it would be \"git pull; git\nrevert ugly-patch\", until it started to look like the sensible thing\nis to fork off, and start doing \"git cherry-pick\" on the good\npatches.\u003c/p\u003e\n\u003ca name=\"user-content-platform-tool-support\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003ePlatform/Tool Support\u003c/h2\u003e\u003ca id=\"user-content-platformtool-support\" class=\"anchor\" aria-label=\"Permalink: Platform/Tool Support\" href=\"#platformtool-support\"\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-operating-systems\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eOperating Systems\u003c/h3\u003e\u003ca id=\"user-content-operating-systems\" class=\"anchor\" aria-label=\"Permalink: Operating Systems\" href=\"#operating-systems\"\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\u003cmarkdown-accessiblity-table\u003e\u003ctable\u003e\n\n\n\n\n\n\n\u003cthead valign=\"bottom\"\u003e\n\u003ctr\u003e\u003cth\u003eDVCS\u003c/th\u003e\n\u003cth\u003eWindows\u003c/th\u003e\n\u003cth\u003eOS X\u003c/th\u003e\n\u003cth\u003eUNIX\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody valign=\"top\"\u003e\n\u003ctr\u003e\u003ctd\u003ebzr\u003c/td\u003e\n\u003ctd\u003eyes (installer) w/ tortoise\u003c/td\u003e\n\u003ctd\u003eyes (installer, fink or MacPorts)\u003c/td\u003e\n\u003ctd\u003eyes (various package formats)\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003ehg\u003c/td\u003e\n\u003ctd\u003eyes (third-party installer) w/ tortoise\u003c/td\u003e\n\u003ctd\u003eyes (third-party installer, fink or MacPorts)\u003c/td\u003e\n\u003ctd\u003eyes (various package formats)\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003egit\u003c/td\u003e\n\u003ctd\u003eyes (third-party installer)\u003c/td\u003e\n\u003ctd\u003eyes (third-party installer, fink or MacPorts)\u003c/td\u003e\n\u003ctd\u003eyes (.deb or .rpm)\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\u003c/markdown-accessiblity-table\u003e\n\u003cp dir=\"auto\"\u003eAs the above table shows, all three DVCSs are available on all three\nmajor OS platforms. But what it also shows is that Bazaar is the\nonly DVCS that directly supports Windows with a binary installer\nwhile Mercurial and git require you to rely on a third-party for\nbinaries. Both bzr and hg have a tortoise version while git does not.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eBazaar and Mercurial also has the benefit of being available in pure\nPython with optional extensions available for performance.\u003c/p\u003e\n\u003ca name=\"user-content-crlf-lf-support\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eCRLF -\u0026gt; LF Support\u003c/h3\u003e\u003ca id=\"user-content-crlf---lf-support\" class=\"anchor\" aria-label=\"Permalink: CRLF -\u0026gt; LF Support\" href=\"#crlf---lf-support\"\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\u003cdl\u003e\n\u003cdt\u003ebzr\u003c/dt\u003e\n\u003cdd\u003eMy understanding is that support for this is being worked on as\nI type, landing in a version RSN. I will try to dig up details.\u003c/dd\u003e\n\u003cdt\u003ehg\u003c/dt\u003e\n\u003cdd\u003eSupported via the win32text extension.\u003c/dd\u003e\n\u003cdt\u003egit\u003c/dt\u003e\n\u003cdd\u003eI can't say from personal experience, but it looks like there's\npretty good support via the core.autocrlf and core.safecrlf\nconfiguration attributes.\u003c/dd\u003e\n\u003c/dl\u003e\n\u003ca name=\"user-content-case-insensitive-filesystem-support\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eCase-insensitive filesystem support\u003c/h3\u003e\u003ca id=\"user-content-case-insensitive-filesystem-support\" class=\"anchor\" aria-label=\"Permalink: Case-insensitive filesystem support\" href=\"#case-insensitive-filesystem-support\"\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\u003cdl\u003e\n\u003cdt\u003ebzr\u003c/dt\u003e\n\u003cdd\u003eShould be OK. I share branches between Linux and OS X all the\ntime. I've done case changes (e.g. \u003ccode\u003ebzr mv Mailman mailman\u003c/code\u003e) and\nas long as I did it on Linux (obviously), when I pulled in the\nchanges on OS X everything was hunky dory.\u003c/dd\u003e\n\u003cdt\u003ehg\u003c/dt\u003e\n\u003cdd\u003eMercurial uses a case safe repository mechanism and detects case\nfolding collisions.\u003c/dd\u003e\n\u003cdt\u003egit\u003c/dt\u003e\n\u003cdd\u003eSince OS X preserves case, you can do case changes there too.\ngit does not have a problem with renames in either direction.\nHowever, case-insensitive filesystem support is usually taken\nto mean complaining about collisions on case-sensitive files\nsystems. git does not do that.\u003c/dd\u003e\n\u003c/dl\u003e\n\u003ca name=\"user-content-tools\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eTools\u003c/h3\u003e\u003ca id=\"user-content-tools\" class=\"anchor\" aria-label=\"Permalink: Tools\" href=\"#tools\"\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 terms of code review tools such as \u003ca href=\"http://www.review-board.org/\" rel=\"nofollow\"\u003eReview Board\u003c/a\u003e and \u003ca href=\"http://code.google.com/p/rietveld/\" rel=\"nofollow\"\u003eRietveld\u003c/a\u003e,\nthe former supports all three while the latter supports hg and git but\nnot bzr. Bazaar does not yet have an online review board, but it\nhas several ways to manage email based reviews and trunk merging.\nThere's \u003ca href=\"http://code.aaronbentley.com/bundlebuggy/\" rel=\"nofollow\"\u003eBundle Buggy\u003c/a\u003e, \u003ca href=\"http://bazaar-vcs.org/PatchQueueManager\" rel=\"nofollow\"\u003ePatch Queue Manager\u003c/a\u003e (PQM), and\n\u003ca href=\"https://launchpad.net/+tour/code-review\" rel=\"nofollow\"\u003eLaunchpad's code reviews\u003c/a\u003e.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eAll three have some web site online that provides basic hosting\nsupport for people who want to put a repository online. Bazaar has\nLaunchpad, Mercurial has bitbucket.org, and git has GitHub. Google\nCode also has instructions on how to use git with the service, both\nto hold a repository and how to act as a read-only mirror.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eAll three also \u003ca href=\"http://buildbot.net/repos/release/docs/buildbot.html#How-Different-VC-Systems-Specify-Sources\" rel=\"nofollow\"\u003eappear to be supported\u003c/a\u003e\nby \u003ca href=\"http://buildbot.net\" rel=\"nofollow\"\u003eBuildbot\u003c/a\u003e.\u003c/p\u003e\n\u003ca name=\"user-content-usage-on-top-of-subversion\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eUsage On Top Of Subversion\u003c/h2\u003e\u003ca id=\"user-content-usage-on-top-of-subversion\" class=\"anchor\" aria-label=\"Permalink: Usage On Top Of Subversion\" href=\"#usage-on-top-of-subversion\"\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\u003cmarkdown-accessiblity-table\u003e\u003ctable\u003e\n\n\n\n\n\u003cthead valign=\"bottom\"\u003e\n\u003ctr\u003e\u003cth\u003eDVCS\u003c/th\u003e\n\u003cth\u003esvn support\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody valign=\"top\"\u003e\n\u003ctr\u003e\u003ctd\u003ebzr\u003c/td\u003e\n\u003ctd\u003e\u003ca href=\"http://bazaar-vcs.org/BzrForeignBranches/Subversion\" rel=\"nofollow\"\u003ebzr-svn\u003c/a\u003e (third-party)\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003ehg\u003c/td\u003e\n\u003ctd\u003e\u003ca href=\"http://www.selenic.com/mercurial/wiki/index.cgi/WorkingWithSubversion\" rel=\"nofollow\"\u003emultiple third-parties\u003c/a\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003egit\u003c/td\u003e\n\u003ctd\u003e\u003ca href=\"http://www.kernel.org/pub/software/scm/git/docs/git-svn.html\" rel=\"nofollow\"\u003egit-svn\u003c/a\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\u003c/markdown-accessiblity-table\u003e\n\u003cp dir=\"auto\"\u003eAll three DVCSs have svn support, although git is the only one to\ncome with that support out-of-the-box.\u003c/p\u003e\n\u003ca name=\"user-content-server-support\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eServer Support\u003c/h2\u003e\u003ca id=\"user-content-server-support\" class=\"anchor\" aria-label=\"Permalink: Server Support\" href=\"#server-support\"\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\u003cmarkdown-accessiblity-table\u003e\u003ctable\u003e\n\n\n\n\n\u003cthead valign=\"bottom\"\u003e\n\u003ctr\u003e\u003cth\u003eDVCS\u003c/th\u003e\n\u003cth\u003eWeb page interface\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody valign=\"top\"\u003e\n\u003ctr\u003e\u003ctd\u003ebzr\u003c/td\u003e\n\u003ctd\u003e\u003ca href=\"https://launchpad.net/loggerhead\" rel=\"nofollow\"\u003eloggerhead\u003c/a\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003ehg\u003c/td\u003e\n\u003ctd\u003e\u003ca href=\"http://www.selenic.com/mercurial/wiki/index.cgi/HgWebDirStepByStep\" rel=\"nofollow\"\u003ehgweb\u003c/a\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003egit\u003c/td\u003e\n\u003ctd\u003e\u003ca href=\"http://git.or.cz/gitwiki/Gitweb\" rel=\"nofollow\"\u003egitweb\u003c/a\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\u003c/markdown-accessiblity-table\u003e\n\u003cp dir=\"auto\"\u003eAll three DVCSs support various hooks on the client and server side\nfor e.g. pre/post-commit verifications.\u003c/p\u003e\n\u003ca name=\"user-content-development\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eDevelopment\u003c/h2\u003e\u003ca id=\"user-content-development\" class=\"anchor\" aria-label=\"Permalink: Development\" href=\"#development\"\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\"\u003eAll three projects are under active development. Git seems to be on a\nmonthly release schedule. Bazaar is on a time-released monthly\nschedule. Mercurial is on a 4-month, timed release schedule.\u003c/p\u003e\n\u003ca name=\"user-content-special-features\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eSpecial Features\u003c/h2\u003e\u003ca id=\"user-content-special-features\" class=\"anchor\" aria-label=\"Permalink: Special Features\" href=\"#special-features\"\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-id26\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003ebzr\u003c/h3\u003e\u003ca id=\"user-content-bzr-7\" class=\"anchor\" aria-label=\"Permalink: bzr\" href=\"#bzr-7\"\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\"\u003eMartin Pool adds: \"bzr has a stable Python scripting interface, with\na distinction between public and private interfaces and a\ndeprecation window for APIs that are changing. Some plugins are\nlisted in \u003ca href=\"https://edge.launchpad.net/bazaar\" rel=\"nofollow\"\u003ehttps://edge.launchpad.net/bazaar\u003c/a\u003e and\n\u003ca href=\"http://bazaar-vcs.org/Documentation\" rel=\"nofollow\"\u003ehttp://bazaar-vcs.org/Documentation\u003c/a\u003e\".\u003c/p\u003e\n\u003ca name=\"user-content-id27\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003ehg\u003c/h3\u003e\u003ca id=\"user-content-hg-7\" class=\"anchor\" aria-label=\"Permalink: hg\" href=\"#hg-7\"\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\"\u003eAlexander Solovyov comments:\u003c/p\u003e\n\u003cblockquote\u003e\nMercurial has easy to use extensive API with hooks for main events\nand ability to extend commands. Also there is the mq (mercurial\nqueues) extension, distributed with Mercurial, which simplifies\nwork with patches.\u003c/blockquote\u003e\n\u003ca name=\"user-content-id28\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003egit\u003c/h3\u003e\u003ca id=\"user-content-git-7\" class=\"anchor\" aria-label=\"Permalink: git\" href=\"#git-7\"\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\"\u003egit has a cvsserver mode, ie, you can check out a tree from git\nusing CVS. You can even commit to the tree, but features like\nmerging are absent, and branches are handled as CVS modules, which\nis likely to shock a veteran CVS user.\u003c/p\u003e\n\u003ca name=\"user-content-tests-impressions\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eTests/Impressions\u003c/h2\u003e\u003ca id=\"user-content-testsimpressions\" class=\"anchor\" aria-label=\"Permalink: Tests/Impressions\" href=\"#testsimpressions\"\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\"\u003eAs I (Brett Cannon) am left with the task of making the final\ndecision of which/any DVCS to go with and not my co-authors, I felt\nit only fair to write down what tests I ran and my impressions as I\nevaluate the various tools so as to be as transparent as possible.\u003c/p\u003e\n\u003ca name=\"user-content-barrier-to-entry\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eBarrier to Entry\u003c/h3\u003e\u003ca id=\"user-content-barrier-to-entry\" class=\"anchor\" aria-label=\"Permalink: Barrier to Entry\" href=\"#barrier-to-entry\"\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 amount of time and effort it takes to get a checkout of Python's\nrepository is critical. If the difficulty or time is too great then a\nperson wishing to contribute to Python may very well give up. That\ncannot be allowed to happen.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eI measured the checking out of the 2.x trunk as if I was a non-core\ndeveloper. Timings were done using the \u003ccode\u003etime\u003c/code\u003e command in zsh and\nspace was calculated with \u003ccode\u003edu -c -h\u003c/code\u003e.\u003c/p\u003e\n\u003cmarkdown-accessiblity-table\u003e\u003ctable\u003e\n\n\n\n\n\n\n\u003cthead valign=\"bottom\"\u003e\n\u003ctr\u003e\u003cth\u003eDVCS\u003c/th\u003e\n\u003cth\u003eSan Francisco\u003c/th\u003e\n\u003cth\u003eVancouver\u003c/th\u003e\n\u003cth\u003eSpace\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody valign=\"top\"\u003e\n\u003ctr\u003e\u003ctd\u003esvn\u003c/td\u003e\n\u003ctd\u003e1:04\u003c/td\u003e\n\u003ctd\u003e2:59\u003c/td\u003e\n\u003ctd\u003e139 M\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003ebzr\u003c/td\u003e\n\u003ctd\u003e10:45\u003c/td\u003e\n\u003ctd\u003e16:04\u003c/td\u003e\n\u003ctd\u003e276 M\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003ehg\u003c/td\u003e\n\u003ctd\u003e2:30\u003c/td\u003e\n\u003ctd\u003e5:24\u003c/td\u003e\n\u003ctd\u003e171 M\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003egit\u003c/td\u003e\n\u003ctd\u003e2:54\u003c/td\u003e\n\u003ctd\u003e5:28\u003c/td\u003e\n\u003ctd\u003e134 M\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\u003c/markdown-accessiblity-table\u003e\n\u003cp dir=\"auto\"\u003eWhen comparing these numbers to svn, it is important to realize that\nit is not a 1:1 comparison. Svn does not pull down the entire revision\nhistory like all of the DVCSs do. That means svn can perform an\ninitial checkout much faster than the DVCS purely based on the fact\nthat it has less information to download for the network.\u003c/p\u003e\n\u003ca name=\"user-content-performance-of-basic-information-functionality\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003ePerformance of basic information functionality\u003c/h3\u003e\u003ca id=\"user-content-performance-of-basic-information-functionality\" class=\"anchor\" aria-label=\"Permalink: Performance of basic information functionality\" href=\"#performance-of-basic-information-functionality\"\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\"\u003eTo see how the tools did for performing a command that required\nquerying the history, the log for the \u003ccode\u003eREADME\u003c/code\u003e file was timed.\u003c/p\u003e\n\u003cmarkdown-accessiblity-table\u003e\u003ctable\u003e\n\n\n\n\n\u003cthead valign=\"bottom\"\u003e\n\u003ctr\u003e\u003cth\u003eDVCS\u003c/th\u003e\n\u003cth\u003eTime\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody valign=\"top\"\u003e\n\u003ctr\u003e\u003ctd\u003ebzr\u003c/td\u003e\n\u003ctd\u003e4.5 s\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003ehg\u003c/td\u003e\n\u003ctd\u003e1.1 s\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003egit\u003c/td\u003e\n\u003ctd\u003e1.5 s\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\u003c/markdown-accessiblity-table\u003e\n\u003cp dir=\"auto\"\u003eOne thing of note during this test was that git took longer than the\nother three tools to figure out how to get the log without it using a\npager. While the pager use is a nice touch in general, not having it\nautomatically turn on took some time (turns out the main \u003ccode\u003egit\u003c/code\u003e\ncommand has a \u003ccode\u003e--no-pager\u003c/code\u003e flag to disable use of the pager).\u003c/p\u003e\n\u003ca name=\"user-content-figuring-out-what-command-to-use-from-built-in-help\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eFiguring out what command to use from built-in help\u003c/h3\u003e\u003ca id=\"user-content-figuring-out-what-command-to-use-from-built-in-help\" class=\"anchor\" aria-label=\"Permalink: Figuring out what command to use from built-in help\" href=\"#figuring-out-what-command-to-use-from-built-in-help\"\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\"\u003eI ended up trying to find out what the command was to see what URL the\nrepository was cloned from. To do this I used nothing more than the\nhelp provided by the tool itself or its man pages.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eBzr was the easiest: \u003ccode\u003ebzr info\u003c/code\u003e. Running \u003ccode\u003ebzr help\u003c/code\u003e didn't show\nwhat I wanted, but mentioned \u003ccode\u003ebzr help commands\u003c/code\u003e. That list had the\ncommand with a description that made sense.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eGit was the second easiest. The command \u003ccode\u003egit help\u003c/code\u003e didn't show much\nand did not have a way of listing all commands. That is when I viewed\nthe man page. Reading through the various commands I discovered \u003ccode\u003egit\nremote\u003c/code\u003e. The command itself spit out nothing more than \u003ccode\u003eorigin\u003c/code\u003e.\nTrying \u003ccode\u003egit remote origin\u003c/code\u003e said it was an error and printed out the\ncommand usage. That is when I noticed \u003ccode\u003egit remote show\u003c/code\u003e. Running\n\u003ccode\u003egit remote show origin\u003c/code\u003e gave me the information I wanted.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eFor hg, I never found the information I wanted on my own. It turns out\nI wanted \u003ccode\u003ehg paths\u003c/code\u003e, but that was not obvious from the description\nof \"show definition of symbolic path names\" as printed by \u003ccode\u003ehg help\u003c/code\u003e\n(it should be noted that reporting this in the PEP did lead to the\nMercurial developers to clarify the wording to make the use of the\n\u003ccode\u003ehg paths\u003c/code\u003e command clearer).\u003c/p\u003e\n\u003ca name=\"user-content-updating-a-checkout\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eUpdating a checkout\u003c/h3\u003e\u003ca id=\"user-content-updating-a-checkout\" class=\"anchor\" aria-label=\"Permalink: Updating a checkout\" href=\"#updating-a-checkout\"\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\"\u003eTo see how long it takes to update an outdated repository I timed both\nupdating a repository 700 commits behind and 50 commits behind (three\nweeks stale and 1 week stale, respectively).\u003c/p\u003e\n\u003cmarkdown-accessiblity-table\u003e\u003ctable\u003e\n\n\n\n\n\n\u003cthead valign=\"bottom\"\u003e\n\u003ctr\u003e\u003cth\u003eDVCS\u003c/th\u003e\n\u003cth\u003e700 commits\u003c/th\u003e\n\u003cth\u003e50 commits\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody valign=\"top\"\u003e\n\u003ctr\u003e\u003ctd\u003ebzr\u003c/td\u003e\n\u003ctd\u003e39 s\u003c/td\u003e\n\u003ctd\u003e7 s\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003ehg\u003c/td\u003e\n\u003ctd\u003e17 s\u003c/td\u003e\n\u003ctd\u003e3 s\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003egit\u003c/td\u003e\n\u003ctd\u003eN/A\u003c/td\u003e\n\u003ctd\u003e4 s\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\u003c/markdown-accessiblity-table\u003e\n\u003cdiv dir=\"auto\"\u003e\n\u003cp dir=\"auto\"\u003eNote\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eGit lacks a value for the \u003cem\u003e700 commits\u003c/em\u003e scenario as it does\nnot seem to allow checking out a repository at a specific\nrevision.\u003c/p\u003e\n\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eGit deserves special mention for its output from \u003ccode\u003egit pull\u003c/code\u003e. It\nnot only lists the delta change information for each file but also\ncolor-codes the information.\u003c/p\u003e\n\u003ca name=\"user-content-decision\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eDecision\u003c/h2\u003e\u003ca id=\"user-content-decision\" class=\"anchor\" aria-label=\"Permalink: Decision\" href=\"#decision\"\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\"\u003eAt PyCon 2009 the decision was made to go with Mercurial.\u003c/p\u003e\n\u003ca name=\"user-content-why-mercurial-over-subversion\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eWhy Mercurial over Subversion\u003c/h3\u003e\u003ca id=\"user-content-why-mercurial-over-subversion\" class=\"anchor\" aria-label=\"Permalink: Why Mercurial over Subversion\" href=\"#why-mercurial-over-subversion\"\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\"\u003eWhile svn has served the development team well, it needs to be\nadmitted that svn does not serve the needs of non-committers as well\nas a DVCS does. Because svn only provides its features such as version\ncontrol, branching, etc. to people with commit privileges on the\nrepository it can be a hindrance for people who lack commit\nprivileges. But DVCSs have no such limitation as anyone can create a\nlocal branch of Python and perform their own local commits without the\nburden that comes with cloning the entire svn repository. Allowing\nanyone to have the same workflow as the core developers was the key\nreason to switch from svn to hg.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eOrthogonal to the benefits of allowing anyone to easily commit locally\nto their own branches is offline, fast operations. Because hg stores\nall data locally there is no need to send requests to a server\nremotely and instead work off of the local disk. This improves\nresponse times tremendously. It also allows for offline usage for when\none lacks an Internet connection. But this benefit is minor and\nconsidered simply a side-effect benefit instead of a driving factor\nfor switching off of Subversion.\u003c/p\u003e\n\u003ca name=\"user-content-why-mercurial-over-other-dvcss\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eWhy Mercurial over other DVCSs\u003c/h3\u003e\u003ca id=\"user-content-why-mercurial-over-other-dvcss\" class=\"anchor\" aria-label=\"Permalink: Why Mercurial over other DVCSs\" href=\"#why-mercurial-over-other-dvcss\"\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\"\u003eGit was not chosen for three key reasons (see the \u003ca href=\"http://pycon.blip.tv/file/1947231/\" rel=\"nofollow\"\u003ePyCon 2009\nlightning talk\u003c/a\u003e where Brett\nCannon lists these exact reasons; talk started at 3:45). First, git's\nWindows support is the weakest out of the three DVCSs being considered\nwhich is unacceptable as Python needs to support development on any\nplatform it runs on. Since Python runs on Windows and some people do\ndevelop on the platform it needs solid support. And while git's\nsupport is improving, as of this moment it is the weakest by a large\nenough margin to warrant considering it a problem.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eSecond, and just as important as the first issue, is that the Python\ncore developers liked git the least out of the three DVCS options by a\nwide margin. If you look at the following table you will see the\nresults of a survey taken of the core developers and how by a large\nmargin git is the least favorite version control system.\u003c/p\u003e\n\u003cmarkdown-accessiblity-table\u003e\u003ctable\u003e\n\n\n\n\n\n\n\n\u003cthead valign=\"bottom\"\u003e\n\u003ctr\u003e\u003cth\u003eDVCS\u003c/th\u003e\n\u003cth\u003e++\u003c/th\u003e\n\u003cth\u003eequal\u003c/th\u003e\n\u003cth\u003e--\u003c/th\u003e\n\u003cth\u003eUninformed\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody valign=\"top\"\u003e\n\u003ctr\u003e\u003ctd\u003egit\u003c/td\u003e\n\u003ctd\u003e5\u003c/td\u003e\n\u003ctd\u003e1\u003c/td\u003e\n\u003ctd\u003e8\u003c/td\u003e\n\u003ctd\u003e13\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003ebzr\u003c/td\u003e\n\u003ctd\u003e10\u003c/td\u003e\n\u003ctd\u003e3\u003c/td\u003e\n\u003ctd\u003e2\u003c/td\u003e\n\u003ctd\u003e12\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003ehg\u003c/td\u003e\n\u003ctd\u003e15\u003c/td\u003e\n\u003ctd\u003e1\u003c/td\u003e\n\u003ctd\u003e1\u003c/td\u003e\n\u003ctd\u003e10\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\u003c/markdown-accessiblity-table\u003e\n\u003cp dir=\"auto\"\u003eLastly, all things being equal (which they are not\nas shown by the previous two issues), it is preferable to\nuse and support a tool written in Python and not one written in C and\nshell. We are pragmatic enough to not choose a tool simply because it\nis written in Python, but we do see the usefulness in promoting tools\nthat do use it when it is reasonable to do so as it is in this case.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eAs for why Mercurial was chosen over Bazaar, it came down to\npopularity. As the core developer survey shows, hg was preferred over\nbzr. But the community also appears to prefer hg as was shown at PyCon\nafter git's removal from consideration was announced. Many people came\nup to Brett and said in various ways that they wanted hg to be chosen.\nWhile no one said they did not want bzr chosen, no one said they did\neither.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eBased on all of this information, Guido and Brett decided Mercurial\nwas to be the next version control system for Python.\u003c/p\u003e\n\u003ca name=\"user-content-transition-plan\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eTransition Plan\u003c/h2\u003e\u003ca id=\"user-content-transition-plan\" class=\"anchor\" aria-label=\"Permalink: Transition Plan\" href=\"#transition-plan\"\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-0385\" rel=\"nofollow\"\u003ePEP 385\u003c/a\u003e outlines the transition from svn to hg.\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 has been placed in the public domain.\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":"_spWxdl_QNmH1DYrxUGHygHHVcorC1bf-l20sBt8VOpt9NstMLMboP4RsOSx0sL6SKMW3VYo6iSYUPwt4225oA"},"/repos/preferences":{"post":"HAzq2HyodbiBGdJjsWyYojKuLJJRxfgZvvk4JL38X5pYXtX2JrMZoO9dcAI0siAHLWhcSAqRzFz0Bn9J90p11Q"}}},"title":"peps/peps/pep-0374.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-0374.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-0374.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-0374.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="53 KB" data-testid="blob-size" class="Truncate__StyledTruncate-sc-23o1d2-0 eAtkQz"><span>1514 lines (1200 loc) · 53 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-0374.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="53 KB" data-testid="blob-size" class="Truncate__StyledTruncate-sc-23o1d2-0 eAtkQz"><span>1514 lines (1200 loc) · 53 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-0374.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: 374 Title: Choosing a distributed VCS for the Python project Author: Brett Cannon <<a href="mailto:brett@python.org">brett@python.org</a>>,</p> <blockquote> Stephen J. Turnbull <<a href="mailto:stephen@xemacs.org">stephen@xemacs.org</a>>, Alexandre Vassalotti <<a href="mailto:alexandre@peadrop.com">alexandre@peadrop.com</a>>, Barry Warsaw <<a href="mailto:barry@python.org">barry@python.org</a>>, Dirkjan Ochtman <<a href="mailto:dirkjan@ochtman.nl">dirkjan@ochtman.nl</a>></blockquote> <p dir="auto">Status: Final Type: Process Created: 07-Nov-2008 Post-History: 07-Nov-2008,</p> <blockquote> 22-Jan-2009</blockquote> <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> <p dir="auto">Python has been using a centralized version control system (VCS; first CVS, now Subversion) for years to great effect. Having a master copy of the official version of Python provides people with a single place to always get the official Python source code. It has also allowed for the storage of the history of the language, mostly for help with development, but also for posterity. And of course the V in VCS is very helpful when developing.</p> <p dir="auto">But a centralized version control system has its drawbacks. First and foremost, in order to have the benefits of version control with Python in a seamless fashion, one must be a "core developer" (i.e. someone with commit privileges on the master copy of Python). People who are not core developers but who wish to work with Python's revision tree, e.g. anyone writing a patch for Python or creating a custom version, do not have direct tool support for revisions. This can be quite a limitation, since these non-core developers cannot easily do basic tasks such as reverting changes to a previously saved state, creating branches, publishing one's changes with full revision history, etc. For non-core developers, the last safe tree state is one the Python developers happen to set, and this prevents safe development. This second-class citizenship is a hindrance to people who wish to contribute to Python with a patch of any complexity and want a way to incrementally save their progress to make their development lives easier.</p> <p dir="auto">There is also the issue of having to be online to be able to commit one's work. Because centralized VCSs keep a central copy that stores all revisions, one must have Internet access in order for their revisions to be stored; no Net, no commit. This can be annoying if you happen to be traveling and lack any Internet. There is also the situation of someone wishing to contribute to Python but having a bad Internet connection where committing is time-consuming and expensive and it might work out better to do it in a single step.</p> <p dir="auto">Another drawback to a centralized VCS is that a common use case is for a developer to revise patches in response to review comments. This is more difficult with a centralized model because there's no place to contain intermediate work. It's either all checked in or none of it is checked in. In the centralized VCS, it's also very difficult to track changes to the trunk as they are committed, while you're working on your feature or bug fix branch. This increases the risk that such branches will grow stale, out-dated, or that merging them into the trunk will generate too may conflicts to be easily resolved.</p> <p dir="auto">Lastly, there is the issue of maintenance of Python. At any one time there is at least one major version of Python under development (at the time of this writing there are two). For each major version of Python under development there is at least the maintenance version of the last minor version and the in-development minor version (e.g. with 2.6 just released, that means that both 2.6 and 2.7 are being worked on). Once a release is done, a branch is created between the code bases where changes in one version do not (but could) belong in the other version. As of right now there is no natural support for this branch in time in central VCSs; you must use tools that simulate the branching. Tracking merges is similarly painful for developers, as revisions often need to be merged between four active branches (e.g. 2.6 maintenance, 3.0 maintenance, 2.7 development, 3.1 development). In this case, VCSs such as Subversion only handle this through arcane third party tools.</p> <p dir="auto">Distributed VCSs (DVCSs) solve all of these problems. While one can keep a master copy of a revision tree, anyone is free to copy that tree for their own use. This gives everyone the power to commit changes to their copy, online or offline. It also more naturally ties into the idea of branching in the history of a revision tree for maintenance and the development of new features bound for Python. DVCSs also provide a great many additional features that centralized VCSs don't or can't provide.</p> <p dir="auto">This PEP explores the possibility of changing Python's use of Subversion to any of the currently popular DVCSs, in order to gain the benefits outlined above. This PEP does not guarantee that a switch to a DVCS will occur at the conclusion of this PEP. It is quite possible that no clear winner will be found and that svn will continue to be used. If this happens, this PEP will be revisited and revised in the future as the state of DVCSs evolves.</p> <a name="user-content-terminology"></a> <div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Terminology</h2><a id="user-content-terminology" class="anchor" aria-label="Permalink: Terminology" href="#terminology"><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">Agreeing on a common terminology is surprisingly difficult, primarily because each VCS uses these terms when describing subtly different tasks, objects, and concepts. Where possible, we try to provide a generic definition of the concepts, but you should consult the individual system's glossaries for details. Here are some basic references for terminology, from some of the standard web-based references on each VCS. You can also refer to glossaries for each DVCS:</p> <ul dir="auto"> <li>Subversion : <a href="http://svnbook.red-bean.com/en/1.5/svn.basic.html" rel="nofollow">http://svnbook.red-bean.com/en/1.5/svn.basic.html</a></li> <li>Bazaar : <a href="http://bazaar-vcs.org/BzrGlossary" rel="nofollow">http://bazaar-vcs.org/BzrGlossary</a></li> <li>Mercurial : <a href="http://www.selenic.com/mercurial/wiki/index.cgi/UnderstandingMercurial" rel="nofollow">http://www.selenic.com/mercurial/wiki/index.cgi/UnderstandingMercurial</a></li> <li>git : <a href="http://book.git-scm.com/1_the_git_object_model.html" rel="nofollow">http://book.git-scm.com/1_the_git_object_model.html</a></li> </ul> <dl> <dt>branch</dt> <dd>A line of development; a collection of revisions, ordered by time.</dd> <dt>checkout/working copy/working tree</dt> <dd>A tree of code the developer can edit, linked to a branch.</dd> <dt>index</dt> <dd>A "staging area" where a revision is built (unique to git).</dd> <dt>repository</dt> <dd>A collection of revisions, organized into branches.</dd> <dt>clone</dt> <dd>A complete copy of a branch or repository.</dd> <dt>commit</dt> <dd>To record a revision in a repository.</dd> <dt>merge</dt> <dd>Applying all the changes and history from one branch/repository to another.</dd> <dt>pull</dt> <dd>To update a checkout/clone from the original branch/repository, which can be remote or local</dd> <dt>push/publish</dt> <dd>To copy a revision, and all revisions it depends on, from a one repository to another.</dd> <dt>cherry-pick</dt> <dd>To merge one or more specific revisions from one branch to another, possibly in a different repository, possibly without its dependent revisions.</dd> <dt>rebase</dt> <dd>To "detach" a branch, and move it to a new branch point; move commits to the beginning of a branch instead of where they happened in time.</dd> </dl> <a name="user-content-typical-workflow"></a> <div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Typical Workflow</h2><a id="user-content-typical-workflow" class="anchor" aria-label="Permalink: Typical Workflow" href="#typical-workflow"><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">At the moment, the typical workflow for a Python core developer is:</p> <ul dir="auto"> <li>Edit code in a checkout until it is stable enough to commit/push.</li> <li>Commit to the master repository.</li> </ul> <p dir="auto">It is a rather simple workflow, but it has drawbacks. For one, because any work that involves the repository takes time thanks to the network, commits/pushes tend to not necessarily be as atomic as possible. There is also the drawback of there not being a necessarily cheap way to create new checkouts beyond a recursive copy of the checkout directory.</p> <p dir="auto">A DVCS would lead to a workflow more like this:</p> <ul dir="auto"> <li>Branch off of a local clone of the master repository.</li> <li>Edit code, committing in atomic pieces.</li> <li>Merge the branch into the mainline, and</li> <li>Push all commits to the master repository.</li> </ul> <p dir="auto">While there are more possible steps, the workflow is much more independent of the master repository than is currently possible. By being able to commit locally at the speed of your disk, a core developer is able to do atomic commits much more frequently, minimizing having commits that do multiple things to the code. Also by using a branch, the changes are isolated (if desired) from other changes being made by other developers. Because branches are cheap, it is easy to create and maintain many smaller branches that address one specific issue, e.g. one bug or one new feature. More sophisticated features of DVCSs allow the developer to more easily track long running development branches as the official mainline progresses.</p> <a name="user-content-contenders"></a> <div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Contenders</h2><a id="user-content-contenders" class="anchor" aria-label="Permalink: Contenders" href="#contenders"><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> <markdown-accessiblity-table><table> <thead valign="bottom"> <tr><th>Name</th> <th>Short Name</th> <th>Version</th> <th>2.x Trunk Mirror</th> <th>3.x Trunk Mirror</th> </tr> </thead> <tbody valign="top"> <tr><td><a href="http://bazaar-vcs.org/" rel="nofollow">Bazaar</a></td> <td>bzr</td> <td>1.12</td> <td><a href="http://code.python.org/python/trunk" rel="nofollow">http://code.python.org/python/trunk</a></td> <td><a href="http://code.python.org/python/3.0" rel="nofollow">http://code.python.org/python/3.0</a></td> </tr> <tr><td><a href="http://www.selenic.com/mercurial/" rel="nofollow">Mercurial</a></td> <td>hg</td> <td>1.2.0</td> <td><a href="http://code.python.org/hg/trunk/" rel="nofollow">http://code.python.org/hg/trunk/</a></td> <td><a href="http://code.python.org/hg/branches/py3k/" rel="nofollow">http://code.python.org/hg/branches/py3k/</a></td> </tr> <tr><td><a href="http://www.git-scm.com/" rel="nofollow">git</a></td> <td>N/A</td> <td>1.6.1</td> <td>git://code.python.org/python/trunk</td> <td>git://code.python.org/python/branches/py3k</td> </tr> </tbody> </table></markdown-accessiblity-table> <p dir="auto">This PEP does not consider darcs, arch, or monotone. The main problem with these DVCSs is that they are simply not popular enough to bother supporting when they do not provide some very compelling features that the other DVCSs provide. Arch and darcs also have significant performance problems which seem unlikely to be addressed in the near future.</p> <a name="user-content-interoperability"></a> <div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Interoperability</h2><a id="user-content-interoperability" class="anchor" aria-label="Permalink: Interoperability" href="#interoperability"><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 those who have already decided which DVCSs they want to use, and are willing to maintain local mirrors themselves, all three DVCSs support interchange via the git "fast-import" changeset format. git does so natively, of course, and native support for Bazaar is under active development, and getting good early reviews as of mid-February 2009. Mercurial has idiosyncratic support for importing via its <em>hg convert</em> command, and <a href="http://repo.or.cz/r/fast-export.git/.git/description" rel="nofollow">third-party fast-import support</a> is available for exporting. Also, the <a href="http://progetti.arstecnica.it/tailor/" rel="nofollow">Tailor</a> tool supports automatic maintenance of mirrors based on an official repository in any of the candidate formats with a local mirror in any format.</p> <a name="user-content-usage-scenarios"></a> <div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Usage Scenarios</h2><a id="user-content-usage-scenarios" class="anchor" aria-label="Permalink: Usage Scenarios" href="#usage-scenarios"><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">Probably the best way to help decide on whether/which DVCS should replace Subversion is to see what it takes to perform some real-world usage scenarios that developers (core and non-core) have to work with. Each usage scenario outlines what it is, a bullet list of what the basic steps are (which can vary slightly per VCS), and how to perform the usage scenario in the various VCSs (including Subversion).</p> <p dir="auto">Each VCS had a single author in charge of writing implementations for each scenario (unless otherwise noted).</p> <markdown-accessiblity-table><table> <thead valign="bottom"> <tr><th>Name</th> <th>VCS</th> </tr> </thead> <tbody valign="top"> <tr><td>Brett</td> <td>svn</td> </tr> <tr><td>Barry</td> <td>bzr</td> </tr> <tr><td>Alexandre</td> <td>hg</td> </tr> <tr><td>Stephen</td> <td>git</td> </tr> </tbody> </table></markdown-accessiblity-table> <a name="user-content-initial-setup"></a> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Initial Setup</h3><a id="user-content-initial-setup" class="anchor" aria-label="Permalink: Initial Setup" href="#initial-setup"><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">Some DVCSs have some perks if you do some initial setup upfront. This section covers what can be done before any of the usage scenarios are run in order to take better advantage of the tools.</p> <p dir="auto">All of the DVCSs support configuring your project identification. Unlike the centralized systems, they use your email address to identify your commits. (Access control is generally done by mechanisms external to the DVCS, such as ssh or console login). This identity may be associated with a full name.</p> <p dir="auto">All of the DVCSs will query the system to get some approximation to this information, but that may not be what you want. They also support setting this information on a per-user basis, and on a per-project basis. Convenience commands to set these attributes vary, but all allow direct editing of configuration files.</p> <p dir="auto">Some VCSs support end-of-line (EOL) conversions on checkout/checkin.</p> <a name="user-content-svn"></a> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">svn</h4><a id="user-content-svn" class="anchor" aria-label="Permalink: svn" href="#svn"><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">None required, but it is recommended you follow the <a href="http://www.python.org/dev/faq/#what-configuration-settings-should-i-use" rel="nofollow">guidelines</a> in the dev FAQ.</p> <a name="user-content-bzr"></a> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">bzr</h4><a id="user-content-bzr" class="anchor" aria-label="Permalink: bzr" href="#bzr"><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">No setup is required, but for much quicker and space-efficient local branching, you should create a shared repository to hold all your Python branches. A shared repository is really just a parent directory containing a .bzr directory. When bzr commits a revision, it searches from the local directory on up the file system for a .bzr directory to hold the revision. By sharing revisions across multiple branches, you cut down on the amount of disk space used. Do this:</p> <pre>cd ~/projects bzr init-repo python cd python </pre> <p dir="auto">Now, all your Python branches should be created inside of <code>~/projects/python</code>.</p> <p dir="auto">There are also some settings you can put in your <code>~/.bzr/bazaar.conf</code> and <code>~/.bzr/locations.conf</code> file to set up defaults for interacting with Python code. None of them are required, although some are recommended. E.g. I would suggest gpg signing all commits, but that might be too high a barrier for developers. Also, you can set up default push locations depending on where you want to push branches by default. If you have write access to the master branches, that push location could be code.python.org. Otherwise, it might be a free Bazaar code hosting service such as Launchpad. If Bazaar is chosen, we should decide what the policies and recommendations are.</p> <p dir="auto">At a minimum, I would set up your email address:</p> <pre>bzr whoami "Firstname Lastname <email.address@example.com>" </pre> <p dir="auto">As with hg and git below, there are ways to set your email address (or really, just about any parameter) on a per-repository basis. You do this with settings in your <code>$HOME/.bazaar/locations.conf</code> file, which has an ini-style format as does the other DVCSs. See the Bazaar documentation for details, which mostly aren't relevant for this discussion.</p> <a name="user-content-hg"></a> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">hg</h4><a id="user-content-hg" class="anchor" aria-label="Permalink: hg" href="#hg"><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">Minimally, you should set your user name. To do so, create the file <code>.hgrc</code> in your home directory and add the following:</p> <pre>[ui] username = Firstname Lastname <email.address@example.com> </pre> <p dir="auto">If you are using Windows and your tools do not support Unix-style newlines, you can enable automatic newline translation by adding to your configuration:</p> <pre>[extensions] win32text = </pre> <p dir="auto">These options can also be set locally to a given repository by customizing <code><repo>/.hg/hgrc</code>, instead of <code>~/.hgrc</code>.</p> <a name="user-content-id1"></a> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">git</h4><a id="user-content-git" class="anchor" aria-label="Permalink: git" href="#git"><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">None needed. However, git supports a number of features that can smooth your work, with a little preparation. git supports setting defaults at the workspace, user, and system levels. The system level is out of scope of this PEP. The user configuration file is <code>$HOME/.gitconfig</code> on Unix-like systems, and the workspace configuration file is <code>$REPOSITORY/.git/config</code>.</p> <p dir="auto">You can use the <code>git-config</code> tool to set preferences for user.name and user.email either globally (for your system login account) or locally (to a given git working copy), or you can edit the configuration files (which have the same format as shown in the Mercurial section above).:</p> <pre># my full name doesn't change # note "--global" flag means per user # (system-wide configuration is set with "--system") git config --global user.name 'Firstname Lastname' # but use my Pythonic email address cd /path/to/python/repository git config user.email email.address@python.example.com </pre> <p dir="auto">If you are using Windows, you probably want to set the core.autocrlf and core.safecrlf preferences to true using <code>git-config</code>.:</p> <pre># check out files with CRLF line endings rather than Unix-style LF only git config --global core.autocrlf true # scream if a transformation would be ambiguous # (eg, a working file contains both naked LF and CRLF) # and check them back in with the reverse transformation git config --global core.safecrlf true </pre> <p dir="auto">Although the repository will usually contain a .gitignore file specifying file names that rarely if ever should be registered in the VCS, you may have personal conventions (e.g., always editing log messages in a temporary file named ".msg") that you may wish to specify.:</p> <pre># tell git where my personal ignores are git config --global core.excludesfile ~/.gitignore # I use .msg for my long commit logs, and Emacs makes backups in # files ending with ~ # these are globs, not regular expressions echo '*~' >> ~/.gitignore echo '.msg' >> ~/.gitignore </pre> <p dir="auto">If you use multiple branches, as with the other VCSes, you can save a lot of space by putting all objects in a common object store. This also can save download time, if the origins of the branches were in different repositories, because objects are shared across branches in your repository even if they were not present in the upstream repositories. git is very space- and time-efficient and applies a number of optimizations automatically, so this configuration is optional. (Examples are omitted.)</p> <a name="user-content-one-off-checkout"></a> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">One-Off Checkout</h3><a id="user-content-one-off-checkout" class="anchor" aria-label="Permalink: One-Off Checkout" href="#one-off-checkout"><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">As a non-core developer, I want to create and publish a one-off patch that fixes a bug, so that a core developer can review it for inclusion in the mainline.</p> <ul dir="auto"> <li>Checkout/branch/clone trunk.</li> <li>Edit some code.</li> <li>Generate a patch (based on what is best supported by the VCS, e.g. branch history).</li> <li>Receive reviewer comments and address the issues.</li> <li>Generate a second patch for the core developer to commit.</li> </ul> <a name="user-content-id2"></a> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">svn</h4><a id="user-content-svn-1" class="anchor" aria-label="Permalink: svn" href="#svn-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> <pre>svn checkout http://svn.python.org/projects/python/trunk cd trunk # Edit some code. echo "The cake is a lie!" > README # Since svn lacks support for local commits, we fake it with patches. svn diff >> commit-1.diff svn diff >> patch-1.diff # Upload the patch-1 to bugs.python.org. # Receive reviewer comments. # Edit some code. echo "The cake is real!" > README # Since svn lacks support for local commits, we fake it with patches. svn diff >> commit-2.diff svn diff >> patch-2.diff # Upload patch-2 to bugs.python.org </pre> <a name="user-content-id3"></a> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">bzr</h4><a id="user-content-bzr-1" class="anchor" aria-label="Permalink: bzr" href="#bzr-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> <pre>bzr branch http://code.python.org/python/trunk cd trunk # Edit some code. bzr commit -m 'Stuff I did' bzr send -o bundle # Upload bundle to bugs.python.org # Receive reviewer comments # Edit some code bzr commit -m 'Respond to reviewer comments' bzr send -o bundle # Upload updated bundle to bugs.python.org </pre> <p dir="auto">The <code>bundle</code> file is like a super-patch. It can be read by <code>patch(1)</code> but it contains additional metadata so that it can be fed to <code>bzr merge</code> to produce a fully usable branch completely with history. See <a href="#patch-review">Patch Review</a> section below.</p> <a name="user-content-id4"></a> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">hg</h4><a id="user-content-hg-1" class="anchor" aria-label="Permalink: hg" href="#hg-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> <pre>hg clone http://code.python.org/hg/trunk cd trunk # Edit some code. hg commit -m "Stuff I did" hg outgoing -p > fixes.patch # Upload patch to bugs.python.org # Receive reviewer comments # Edit some code hg commit -m "Address reviewer comments." hg outgoing -p > additional-fixes.patch # Upload patch to bugs.python.org </pre> <p dir="auto">While <code>hg outgoing</code> does not have the flag for it, most Mercurial commands support git's extended patch format through a <code>--git</code> command. This can be set in one's <code>.hgrc</code> file so that all commands that generate a patch use the extended format.</p> <a name="user-content-id5"></a> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">git</h4><a id="user-content-git-1" class="anchor" aria-label="Permalink: git" href="#git-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">The patches could be created with <code>git diff master > stuff-i-did.patch</code>, too, but <code>git format-patch | git am</code> knows some tricks (empty files, renames, etc) that ordinary patch can't handle. git grabs "Stuff I did" out of the commit message to create the file name 0001-Stuff-I-did.patch. See Patch Review below for a description of the git-format-patch format.</p> <pre># Get the mainline code. git clone git://code.python.org/python/trunk cd trunk # Edit some code. git commit -a -m 'Stuff I did.' # Create patch for my changes (i.e, relative to master). git format-patch master git tag stuff-v1 # Upload 0001-Stuff-I-did.patch to bugs.python.org. # Time passes ... receive reviewer comments. # Edit more code. git commit -a -m 'Address reviewer comments.' # Make an add-on patch to apply on top of the original. git format-patch stuff-v1 # Upload 0001-Address-reviewer-comments.patch to bugs.python.org. </pre> <a name="user-content-backing-out-changes"></a> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Backing Out Changes</h3><a id="user-content-backing-out-changes" class="anchor" aria-label="Permalink: Backing Out Changes" href="#backing-out-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">As a core developer, I want to undo a change that was not ready for inclusion in the mainline.</p> <ul dir="auto"> <li>Back out the unwanted change.</li> <li>Push patch to server.</li> </ul> <a name="user-content-id6"></a> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">svn</h4><a id="user-content-svn-2" class="anchor" aria-label="Permalink: svn" href="#svn-2"><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> <pre># Assume the change to revert is in revision 40 svn merge -c -40 . # Resolve conflicts, if any. svn commit -m "Reverted revision 40" </pre> <a name="user-content-id7"></a> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">bzr</h4><a id="user-content-bzr-2" class="anchor" aria-label="Permalink: bzr" href="#bzr-2"><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> <pre># Assume the change to revert is in revision 40 bzr merge -r 40..39 # Resolve conflicts, if any. bzr commit -m "Reverted revision 40" </pre> <p dir="auto">Note that if the change you want revert is the last one that was made, you can just use <code>bzr uncommit</code>.</p> <a name="user-content-id8"></a> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">hg</h4><a id="user-content-hg-2" class="anchor" aria-label="Permalink: hg" href="#hg-2"><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> <pre># Assume the change to revert is in revision 9150dd9c6d30 hg backout --merge -r 9150dd9c6d30 # Resolve conflicts, if any. hg commit -m "Reverted changeset 9150dd9c6d30" hg push </pre> <p dir="auto">Note, you can use "hg rollback" and "hg strip" to revert changes you committed in your local repository, but did not yet push to other repositories.</p> <a name="user-content-id9"></a> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">git</h4><a id="user-content-git-2" class="anchor" aria-label="Permalink: git" href="#git-2"><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> <pre># Assume the change to revert is the grandfather of a revision tagged "newhotness". git revert newhotness~2 # Resolve conflicts if any. If there are no conflicts, the commit # will be done automatically by "git revert", which prompts for a log. git commit -m "Reverted changeset 9150dd9c6d30." git push </pre> <a name="user-content-patch-review"></a> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Patch Review</h3><a id="user-content-patch-review" class="anchor" aria-label="Permalink: Patch Review" href="#patch-review"><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">As a core developer, I want to review patches submitted by other people, so that I can make sure that only approved changes are added to Python.</p> <p dir="auto">Core developers have to review patches as submitted by other people. This requires applying the patch, testing it, and then tossing away the changes. The assumption can be made that a core developer already has a checkout/branch/clone of the trunk.</p> <ul dir="auto"> <li>Branch off of trunk.</li> <li>Apply patch w/o any comments as generated by the patch submitter.</li> <li>Push patch to server.</li> <li>Delete now-useless branch.</li> </ul> <a name="user-content-id10"></a> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">svn</h4><a id="user-content-svn-3" class="anchor" aria-label="Permalink: svn" href="#svn-3"><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">Subversion does not exactly fit into this development style very well as there are no such thing as a "branch" as has been defined in this PEP. Instead a developer either needs to create another checkout for testing a patch or create a branch on the server. Up to this point, core developers have not taken the "branch on the server" approach to dealing with individual patches. For this scenario the assumption will be the developer creates a local checkout of the trunk to work with.:</p> <pre>cp -r trunk issue0000 cd issue0000 patch -p0 < __patch__ # Review patch. svn commit -m "Some patch." cd .. rm -r issue0000 </pre> <p dir="auto">Another option is to only have a single checkout running at any one time and use <code>svn diff</code> along with <code>svn revert -R</code> to store away independent changes you may have made.</p> <a name="user-content-id11"></a> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">bzr</h4><a id="user-content-bzr-3" class="anchor" aria-label="Permalink: bzr" href="#bzr-3"><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> <pre>bzr branch trunk issueNNNN # Download `patch` bundle from Roundup bzr merge patch # Review patch bzr commit -m'Patch NNN by So N. So' --fixes python:NNNN bzr push bzr+ssh://me@code.python.org/trunk rm -rf ../issueNNNN </pre> <p dir="auto">Alternatively, since you're probably going to commit these changes to the trunk, you could just do a checkout. That would give you a local working tree while the branch (i.e. all revisions) would continue to live on the server. This is similar to the svn model and might allow you to more quickly review the patch. There's no need for the push in this case.:</p> <pre>bzr checkout trunk issueNNNN # Download `patch` bundle from Roundup bzr merge patch # Review patch bzr commit -m'Patch NNNN by So N. So' --fixes python:NNNN rm -rf ../issueNNNN </pre> <a name="user-content-id12"></a> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">hg</h4><a id="user-content-hg-3" class="anchor" aria-label="Permalink: hg" href="#hg-3"><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> <pre>hg clone trunk issue0000 cd issue0000 # If the patch was generated using hg export, the user name of the # submitter is automatically recorded. Otherwise, # use hg import --no-commit submitted.diff and commit with # hg commit -u "Firstname Lastname <email.address@example.com>" hg import submitted.diff # Review patch. hg push ssh://alexandre@code.python.org/hg/trunk/ </pre> <a name="user-content-id13"></a> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">git</h4><a id="user-content-git-3" class="anchor" aria-label="Permalink: git" href="#git-3"><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">We assume a patch created by git-format-patch. This is a Unix mbox file containing one or more patches, each formatted as an <a href="http://tools.ietf.org/html/rfc2822.html" rel="nofollow">RFC 2822</a> message. git-am interprets each message as a commit as follows. The author of the patch is taken from the From: header, the date from the Date header. The commit log is created by concatenating the content of the subject line, a blank line, and the message body up to the start of the patch.:</p> <pre>cd trunk # Create a branch in case we don't like the patch. # This checkout takes zero time, since the workspace is left in # the same state as the master branch. git checkout -b patch-review # Download patch from bugs.python.org to submitted.patch. git am < submitted.patch # Review and approve patch. # Merge into master and push. git checkout master git merge patch-review git push </pre> <a name="user-content-backport"></a> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Backport</h3><a id="user-content-backport" class="anchor" aria-label="Permalink: Backport" href="#backport"><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">As a core developer, I want to apply a patch to 2.6, 2.7, 3.0, and 3.1 so that I can fix a problem in all three versions.</p> <p dir="auto">Thanks to always having the cutting-edge and the latest release version under development, Python currently has four branches being worked on simultaneously. That makes it important for a change to propagate easily through various branches.</p> <a name="user-content-id14"></a> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">svn</h4><a id="user-content-svn-4" class="anchor" aria-label="Permalink: svn" href="#svn-4"><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 of Python's use of svnmerge, changes start with the trunk (2.7) and then get merged to the release version of 2.6. To get the change into the 3.x series, the change is merged into 3.1, fixed up, and then merged into 3.0 (2.7 -> 2.6; 2.7 -> 3.1 -> 3.0).</p> <p dir="auto">This is in contrast to a port-forward strategy where the patch would have been added to 2.6 and then pulled forward into newer versions (2.6 -> 2.7 -> 3.0 -> 3.1).</p> <pre># Assume patch applied to 2.7 in revision 0000. cd release26-maint svnmerge merge -r 0000 # Resolve merge conflicts and make sure patch works. svn commit -F svnmerge-commit-message.txt # revision 0001. cd ../py3k svnmerge merge -r 0000 # Same as for 2.6, except Misc/NEWS changes are reverted. svn revert Misc/NEWS svn commit -F svnmerge-commit-message.txt # revision 0002. cd ../release30-maint svnmerge merge -r 0002 svn commit -F svnmerge-commit-message.txt # revision 0003. </pre> <a name="user-content-id15"></a> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">bzr</h4><a id="user-content-bzr-4" class="anchor" aria-label="Permalink: bzr" href="#bzr-4"><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">Bazaar is pretty straightforward here, since it supports cherry picking revisions manually. In the example below, we could have given a revision id instead of a revision number, but that's usually not necessary. Martin Pool suggests "We'd generally recommend doing the fix first in the oldest supported branch, and then merging it forward to the later releases.":</p> <pre># Assume patch applied to 2.7 in revision 0000 cd release26-maint bzr merge ../trunk -c 0000 # Resolve conflicts and make sure patch works bzr commit -m 'Back port patch NNNN' bzr push bzr+ssh://me@code.python.org/trunk cd ../py3k bzr merge ../trunk -r 0000 # Same as for 2.6 except Misc/NEWS changes are reverted bzr revert Misc/NEWS bzr commit -m 'Forward port patch NNNN' bzr push bzr+ssh://me@code.python.org/py3k </pre> <a name="user-content-id16"></a> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">hg</h4><a id="user-content-hg-4" class="anchor" aria-label="Permalink: hg" href="#hg-4"><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">Mercurial, like other DVCS, does not well support the current workflow used by Python core developers to backport patches. Right now, bug fixes are first applied to the development mainline (i.e., trunk), then back-ported to the maintenance branches and forward-ported, as necessary, to the py3k branch. This workflow requires the ability to cherry-pick individual changes. Mercurial's transplant extension provides this ability. Here is an example of the scenario using this workflow:</p> <pre>cd release26-maint # Assume patch applied to 2.7 in revision 0000 hg transplant -s ../trunk 0000 # Resolve conflicts, if any. cd ../py3k hg pull ../trunk hg merge hg revert Misc/NEWS hg commit -m "Merged trunk" hg push </pre> <p dir="auto">In the above example, transplant acts much like the current svnmerge command. When transplant is invoked without the revision, the command launches an interactive loop useful for transplanting multiple changes. Another useful feature is the --filter option which can be used to modify changesets programmatically (e.g., it could be used for removing changes to Misc/NEWS automatically).</p> <p dir="auto">Alternatively to the traditional workflow, we could avoid transplanting changesets by committing bug fixes to the oldest supported release, then merge these fixes upward to the more recent branches.</p> <pre>cd release25-maint hg import fix_some_bug.diff # Review patch and run test suite. Revert if failure. hg push cd ../release26-maint hg pull ../release25-maint hg merge # Resolve conflicts, if any. Then, review patch and run test suite. hg commit -m "Merged patches from release25-maint." hg push cd ../trunk hg pull ../release26-maint hg merge # Resolve conflicts, if any, then review. hg commit -m "Merged patches from release26-maint." hg push </pre> <p dir="auto">Although this approach makes the history non-linear and slightly more difficult to follow, it encourages fixing bugs across all supported releases. Furthermore, it scales better when there is many changes to backport, because we do not need to seek the specific revision IDs to merge.</p> <a name="user-content-id17"></a> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">git</h4><a id="user-content-git-4" class="anchor" aria-label="Permalink: git" href="#git-4"><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 git I would have a workspace which contains all of the relevant master repository branches. git cherry-pick doesn't work across repositories; you need to have the branches in the same repository.</p> <pre># Assume patch applied to 2.7 in revision release27~3 (4th patch back from tip). cd integration git checkout release26 git cherry-pick release27~3 # If there are conflicts, resolve them, and commit those changes. # git commit -a -m "Resolve conflicts." # Run test suite. If fixes are necessary, record as a separate commit. # git commit -a -m "Fix code causing test failures." git checkout master git cherry-pick release27~3 # Do any conflict resolution and test failure fixups. # Revert Misc/NEWS changes. git checkout HEAD^ -- Misc/NEWS git commit -m 'Revert cherry-picked Misc/NEWS changes.' Misc/NEWS # Push both ports. git push release26 master </pre> <p dir="auto">If you are regularly merging (rather than cherry-picking) from a given branch, then you can block a given commit from being accidentally merged in the future by merging, then reverting it. This does not prevent a cherry-pick from pulling in the unwanted patch, and this technique requires blocking everything that you don't want merged. I'm not sure if this differs from svn on this point.</p> <pre>cd trunk # Merge in the alpha tested code. git merge experimental-branch # We don't want the 3rd-to-last commit from the experimental-branch, # and we don't want it to ever be merged. # The notation "^N" means Nth parent of the current commit. Thus HEAD^2^1^1 # means the first parent of the first parent of the second parent of HEAD. git revert HEAD^2^1^1 # Propagate the merge and the prohibition to the public repository. git push </pre> <a name="user-content-coordinated-development-of-a-new-feature"></a> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Coordinated Development of a New Feature</h3><a id="user-content-coordinated-development-of-a-new-feature" class="anchor" aria-label="Permalink: Coordinated Development of a New Feature" href="#coordinated-development-of-a-new-feature"><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">Sometimes core developers end up working on a major feature with several developers. As a core developer, I want to be able to publish feature branches to a common public location so that I can collaborate with other developers.</p> <p dir="auto">This requires creating a branch on a server that other developers can access. All of the DVCSs support creating new repositories on hosts where the developer is already able to commit, with appropriate configuration of the repository host. This is similar in concept to the existing sandbox in svn, although details of repository initialization may differ.</p> <p dir="auto">For non-core developers, there are various more-or-less public-access repository-hosting services. Bazaar has <a href="http://www.launchpad.net/" rel="nofollow">Launchpad</a>, Mercurial has <a href="http://www.bitbucket.org/" rel="nofollow">bitbucket.org</a>, and git has <a href="http://www.github.com/">GitHub</a>. All also have easy-to-use CGI interfaces for developers who maintain their own servers.</p> <ul dir="auto"> <li>Branch trunk.</li> <li>Pull from branch on the server.</li> <li>Pull from trunk.</li> <li>Push merge to trunk.</li> </ul> <a name="user-content-id18"></a> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">svn</h4><a id="user-content-svn-5" class="anchor" aria-label="Permalink: svn" href="#svn-5"><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> <pre># Create branch. svn copy svn+ssh://pythondev@svn.python.org/python/trunk svn+ssh://pythondev@svn.python.org/python/branches/NewHotness svn checkout svn+ssh://pythondev@svn.python.org/python/branches/NewHotness cd NewHotness svnmerge init svn commit -m "Initialize svnmerge." # Pull in changes from other developers. svn update # Pull in trunk and merge to the branch. svnmerge merge svn commit -F svnmerge-commit-message.txt </pre> <p dir="auto">This scenario is incomplete as the decision for what DVCS to go with was made before the work was complete.</p> <a name="user-content-separation-of-issue-dependencies"></a> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Separation of Issue Dependencies</h3><a id="user-content-separation-of-issue-dependencies" class="anchor" aria-label="Permalink: Separation of Issue Dependencies" href="#separation-of-issue-dependencies"><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">Sometimes, while working on an issue, it becomes apparent that the problem being worked on is actually a compound issue of various smaller issues. Being able to take the current work and then begin working on a separate issue is very helpful to separate out issues into individual units of work instead of compounding them into a single, large unit.</p> <ul dir="auto"> <li>Create a branch A (e.g. urllib has a bug).</li> <li>Edit some code.</li> <li>Create a new branch B that branch A depends on (e.g. the urllib bug exposes a socket bug).</li> <li>Edit some code in branch B.</li> <li>Commit branch B.</li> <li>Edit some code in branch A.</li> <li>Commit branch A.</li> <li>Clean up.</li> </ul> <a name="user-content-id19"></a> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">svn</h4><a id="user-content-svn-6" class="anchor" aria-label="Permalink: svn" href="#svn-6"><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">To make up for svn's lack of cheap branching, it has a changelist option to associate a file with a single changelist. This is not as powerful as being able to associate at the commit level. There is also no way to express dependencies between changelists.</p> <pre>cp -r trunk issue0000 cd issue0000 # Edit some code. echo "The cake is a lie!" > README svn changelist A README # Edit some other code. echo "I own Python!" > LICENSE svn changelist B LICENSE svn ci -m "Tell it how it is." --changelist B # Edit changelist A some more. svn ci -m "Speak the truth." --changelist A cd .. rm -rf issue0000 </pre> <a name="user-content-id20"></a> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">bzr</h4><a id="user-content-bzr-5" class="anchor" aria-label="Permalink: bzr" href="#bzr-5"><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">Here's an approach that uses bzr shelf (now a standard part of bzr) to squirrel away some changes temporarily while you take a detour to fix the socket bugs.</p> <pre>bzr branch trunk bug-0000 cd bug-0000 # Edit some code. Dang, we need to fix the socket module. bzr shelve --all # Edit some code. bzr commit -m "Socket module fixes" # Detour over, now resume fixing urllib bzr unshelve # Edit some code </pre> <p dir="auto">Another approach uses the loom plugin. Looms can greatly simplify working on dependent branches because they automatically take care of the stacking dependencies for you. Imagine looms as a stack of dependent branches (called "threads" in loom parlance), with easy ways to move up and down the stack of threads, merge changes up the stack to descendant threads, create diffs between threads, etc. Occasionally, you may need or want to export your loom threads into separate branches, either for review or commit. Higher threads incorporate all the changes in the lower threads, automatically.</p> <pre>bzr branch trunk bug-0000 cd bug-0000 bzr loomify --base trunk bzr create-thread fix-urllib # Edit some code. Dang, we need to fix the socket module first. bzr commit -m "Checkpointing my work so far" bzr down-thread bzr create-thread fix-socket # Edit some code bzr commit -m "Socket module fixes" bzr up-thread # Manually resolve conflicts if necessary bzr commit -m 'Merge in socket fixes' # Edit me some more code bzr commit -m "Now that socket is fixed, complete the urllib fixes" bzr record done </pre> <p dir="auto">For bonus points, let's say someone else fixes the socket module in exactly the same way you just did. Perhaps this person even grabbed your fix-socket thread and applied just that to the trunk. You'd like to be able to merge their changes into your loom and delete your now-redundant fix-socket thread.</p> <pre>bzr down-thread trunk # Get all new revisions to the trunk. If you've done things # correctly, this will succeed without conflict. bzr pull bzr up-thread # See? The fix-socket thread is now identical to the trunk bzr commit -m 'Merge in trunk changes' bzr diff -r thread: | wc -l # returns 0 bzr combine-thread bzr up-thread # Resolve any conflicts bzr commit -m 'Merge trunk' # Now our top-thread has an up-to-date trunk and just the urllib fix. </pre> <a name="user-content-id21"></a> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">hg</h4><a id="user-content-hg-5" class="anchor" aria-label="Permalink: hg" href="#hg-5"><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">One approach is to use the shelve extension; this extension is not included with Mercurial, but it is easy to install. With shelve, you can select changes to put temporarily aside.</p> <pre>hg clone trunk issue0000 cd issue0000 # Edit some code (e.g. urllib). hg shelve # Select changes to put aside # Edit some other code (e.g. socket). hg commit hg unshelve # Complete initial fix. hg commit cd ../trunk hg pull ../issue0000 hg merge hg commit rm -rf ../issue0000 </pre> <p dir="auto">Several other way to approach this scenario with Mercurial. Alexander Solovyov presented a few <a href="http://selenic.com/pipermail/mercurial/2009-January/023710.html" rel="nofollow">alternative approaches</a> on Mercurial's mailing list.</p> <a name="user-content-id22"></a> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">git</h4><a id="user-content-git-5" class="anchor" aria-label="Permalink: git" href="#git-5"><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> <pre>cd trunk # Edit some code in urllib. # Discover a bug in socket, want to fix that first. # So save away our current work. git stash # Edit some code, commit some changes. git commit -a -m "Completed fix of socket." # Restore the in-progress work on urllib. git stash apply # Edit me some more code, commit some more fixes. git commit -a -m "Complete urllib fixes." # And push both patches to the public repository. git push </pre> <p dir="auto">Bonus points: suppose you took your time, and someone else fixes socket in the same way you just did, and landed that in the trunk. In that case, your push will fail because your branch is not up-to-date. If the fix was a one-liner, there's a very good chance that it's <em>exactly</em> the same, character for character. git would notice that, and you are done; git will silently merge them.</p> <p dir="auto">Suppose we're not so lucky:</p> <pre># Update your branch. git pull git://code.python.org/public/trunk master # git has fetched all the necessary data, but reports that the # merge failed. We discover the nearly-duplicated patch. # Neither our version of the master branch nor the workspace has # been touched. Revert our socket patch and pull again: git revert HEAD^ git pull git://code.python.org/public/trunk master </pre> <p dir="auto">Like Bazaar and Mercurial, git has extensions to manage stacks of patches. You can use the original Quilt by Andrew Morton, or there is StGit ("stacked git") which integrates patch-tracking for large sets of patches into the VCS in a way similar to Mercurial Queues or Bazaar looms.</p> <a name="user-content-doing-a-python-release"></a> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Doing a Python Release</h3><a id="user-content-doing-a-python-release" class="anchor" aria-label="Permalink: Doing a Python Release" href="#doing-a-python-release"><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">How does <a href="http://www.python.org/dev/peps/pep-0101" rel="nofollow">PEP 101</a> change when using a DVCS?</p> <a name="user-content-id23"></a> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">bzr</h4><a id="user-content-bzr-6" class="anchor" aria-label="Permalink: bzr" href="#bzr-6"><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">It will change, but not substantially so. When doing the maintenance branch, we'll just push to the new location instead of doing an svn cp. Tags are totally different, since in svn they are directory copies, but in bzr (and I'm guessing hg), they are just symbolic names for revisions on a particular branch. The release.py script will have to change to use bzr commands instead. It's possible that because DVCS (in particular, bzr) does cherry picking and merging well enough that we'll be able to create the maint branches sooner. It would be a useful exercise to try to do a release off the bzr/hg mirrors.</p> <a name="user-content-id24"></a> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">hg</h4><a id="user-content-hg-6" class="anchor" aria-label="Permalink: hg" href="#hg-6"><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">Clearly, details specific to Subversion in <a href="http://www.python.org/dev/peps/pep-0101" rel="nofollow">PEP 101</a> and in the release script will need to be updated. In particular, release tagging and maintenance branches creation process will have to be modified to use Mercurial's features; this will simplify and streamline certain aspects of the release process. For example, tagging and re-tagging a release will become a trivial operation since a tag, in Mercurial, is simply a symbolic name for a given revision.</p> <a name="user-content-id25"></a> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">git</h4><a id="user-content-git-6" class="anchor" aria-label="Permalink: git" href="#git-6"><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">It will change, but not substantially so. When doing the maintenance branch, we'll just git push to the new location instead of doing an svn cp. Tags are totally different, since in svn they are directory copies, but in git they are just symbolic names for revisions, as are branches. (The difference between a tag and a branch is that tags refer to a particular commit, and will never change unless you use git tag -f to force them to move. The checked-out branch, on the other hand, is automatically updated by git commit.) The release.py script will have to change to use git commands instead. With git I would create a (local) maintenance branch as soon as the release engineer is chosen. Then I'd "git pull" until I didn't like a patch, when it would be "git pull; git revert ugly-patch", until it started to look like the sensible thing is to fork off, and start doing "git cherry-pick" on the good patches.</p> <a name="user-content-platform-tool-support"></a> <div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Platform/Tool Support</h2><a id="user-content-platformtool-support" class="anchor" aria-label="Permalink: Platform/Tool Support" href="#platformtool-support"><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-operating-systems"></a> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Operating Systems</h3><a id="user-content-operating-systems" class="anchor" aria-label="Permalink: Operating Systems" href="#operating-systems"><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> <markdown-accessiblity-table><table> <thead valign="bottom"> <tr><th>DVCS</th> <th>Windows</th> <th>OS X</th> <th>UNIX</th> </tr> </thead> <tbody valign="top"> <tr><td>bzr</td> <td>yes (installer) w/ tortoise</td> <td>yes (installer, fink or MacPorts)</td> <td>yes (various package formats)</td> </tr> <tr><td>hg</td> <td>yes (third-party installer) w/ tortoise</td> <td>yes (third-party installer, fink or MacPorts)</td> <td>yes (various package formats)</td> </tr> <tr><td>git</td> <td>yes (third-party installer)</td> <td>yes (third-party installer, fink or MacPorts)</td> <td>yes (.deb or .rpm)</td> </tr> </tbody> </table></markdown-accessiblity-table> <p dir="auto">As the above table shows, all three DVCSs are available on all three major OS platforms. But what it also shows is that Bazaar is the only DVCS that directly supports Windows with a binary installer while Mercurial and git require you to rely on a third-party for binaries. Both bzr and hg have a tortoise version while git does not.</p> <p dir="auto">Bazaar and Mercurial also has the benefit of being available in pure Python with optional extensions available for performance.</p> <a name="user-content-crlf-lf-support"></a> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">CRLF -> LF Support</h3><a id="user-content-crlf---lf-support" class="anchor" aria-label="Permalink: CRLF -> LF Support" href="#crlf---lf-support"><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> <dl> <dt>bzr</dt> <dd>My understanding is that support for this is being worked on as I type, landing in a version RSN. I will try to dig up details.</dd> <dt>hg</dt> <dd>Supported via the win32text extension.</dd> <dt>git</dt> <dd>I can't say from personal experience, but it looks like there's pretty good support via the core.autocrlf and core.safecrlf configuration attributes.</dd> </dl> <a name="user-content-case-insensitive-filesystem-support"></a> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Case-insensitive filesystem support</h3><a id="user-content-case-insensitive-filesystem-support" class="anchor" aria-label="Permalink: Case-insensitive filesystem support" href="#case-insensitive-filesystem-support"><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> <dl> <dt>bzr</dt> <dd>Should be OK. I share branches between Linux and OS X all the time. I've done case changes (e.g. <code>bzr mv Mailman mailman</code>) and as long as I did it on Linux (obviously), when I pulled in the changes on OS X everything was hunky dory.</dd> <dt>hg</dt> <dd>Mercurial uses a case safe repository mechanism and detects case folding collisions.</dd> <dt>git</dt> <dd>Since OS X preserves case, you can do case changes there too. git does not have a problem with renames in either direction. However, case-insensitive filesystem support is usually taken to mean complaining about collisions on case-sensitive files systems. git does not do that.</dd> </dl> <a name="user-content-tools"></a> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Tools</h3><a id="user-content-tools" class="anchor" aria-label="Permalink: Tools" href="#tools"><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 terms of code review tools such as <a href="http://www.review-board.org/" rel="nofollow">Review Board</a> and <a href="http://code.google.com/p/rietveld/" rel="nofollow">Rietveld</a>, the former supports all three while the latter supports hg and git but not bzr. Bazaar does not yet have an online review board, but it has several ways to manage email based reviews and trunk merging. There's <a href="http://code.aaronbentley.com/bundlebuggy/" rel="nofollow">Bundle Buggy</a>, <a href="http://bazaar-vcs.org/PatchQueueManager" rel="nofollow">Patch Queue Manager</a> (PQM), and <a href="https://launchpad.net/+tour/code-review" rel="nofollow">Launchpad's code reviews</a>.</p> <p dir="auto">All three have some web site online that provides basic hosting support for people who want to put a repository online. Bazaar has Launchpad, Mercurial has bitbucket.org, and git has GitHub. Google Code also has instructions on how to use git with the service, both to hold a repository and how to act as a read-only mirror.</p> <p dir="auto">All three also <a href="http://buildbot.net/repos/release/docs/buildbot.html#How-Different-VC-Systems-Specify-Sources" rel="nofollow">appear to be supported</a> by <a href="http://buildbot.net" rel="nofollow">Buildbot</a>.</p> <a name="user-content-usage-on-top-of-subversion"></a> <div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Usage On Top Of Subversion</h2><a id="user-content-usage-on-top-of-subversion" class="anchor" aria-label="Permalink: Usage On Top Of Subversion" href="#usage-on-top-of-subversion"><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> <markdown-accessiblity-table><table> <thead valign="bottom"> <tr><th>DVCS</th> <th>svn support</th> </tr> </thead> <tbody valign="top"> <tr><td>bzr</td> <td><a href="http://bazaar-vcs.org/BzrForeignBranches/Subversion" rel="nofollow">bzr-svn</a> (third-party)</td> </tr> <tr><td>hg</td> <td><a href="http://www.selenic.com/mercurial/wiki/index.cgi/WorkingWithSubversion" rel="nofollow">multiple third-parties</a></td> </tr> <tr><td>git</td> <td><a href="http://www.kernel.org/pub/software/scm/git/docs/git-svn.html" rel="nofollow">git-svn</a></td> </tr> </tbody> </table></markdown-accessiblity-table> <p dir="auto">All three DVCSs have svn support, although git is the only one to come with that support out-of-the-box.</p> <a name="user-content-server-support"></a> <div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Server Support</h2><a id="user-content-server-support" class="anchor" aria-label="Permalink: Server Support" href="#server-support"><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> <markdown-accessiblity-table><table> <thead valign="bottom"> <tr><th>DVCS</th> <th>Web page interface</th> </tr> </thead> <tbody valign="top"> <tr><td>bzr</td> <td><a href="https://launchpad.net/loggerhead" rel="nofollow">loggerhead</a></td> </tr> <tr><td>hg</td> <td><a href="http://www.selenic.com/mercurial/wiki/index.cgi/HgWebDirStepByStep" rel="nofollow">hgweb</a></td> </tr> <tr><td>git</td> <td><a href="http://git.or.cz/gitwiki/Gitweb" rel="nofollow">gitweb</a></td> </tr> </tbody> </table></markdown-accessiblity-table> <p dir="auto">All three DVCSs support various hooks on the client and server side for e.g. pre/post-commit verifications.</p> <a name="user-content-development"></a> <div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Development</h2><a id="user-content-development" class="anchor" aria-label="Permalink: Development" href="#development"><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">All three projects are under active development. Git seems to be on a monthly release schedule. Bazaar is on a time-released monthly schedule. Mercurial is on a 4-month, timed release schedule.</p> <a name="user-content-special-features"></a> <div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Special Features</h2><a id="user-content-special-features" class="anchor" aria-label="Permalink: Special Features" href="#special-features"><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-id26"></a> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">bzr</h3><a id="user-content-bzr-7" class="anchor" aria-label="Permalink: bzr" href="#bzr-7"><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">Martin Pool adds: "bzr has a stable Python scripting interface, with a distinction between public and private interfaces and a deprecation window for APIs that are changing. Some plugins are listed in <a href="https://edge.launchpad.net/bazaar" rel="nofollow">https://edge.launchpad.net/bazaar</a> and <a href="http://bazaar-vcs.org/Documentation" rel="nofollow">http://bazaar-vcs.org/Documentation</a>".</p> <a name="user-content-id27"></a> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">hg</h3><a id="user-content-hg-7" class="anchor" aria-label="Permalink: hg" href="#hg-7"><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">Alexander Solovyov comments:</p> <blockquote> Mercurial has easy to use extensive API with hooks for main events and ability to extend commands. Also there is the mq (mercurial queues) extension, distributed with Mercurial, which simplifies work with patches.</blockquote> <a name="user-content-id28"></a> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">git</h3><a id="user-content-git-7" class="anchor" aria-label="Permalink: git" href="#git-7"><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">git has a cvsserver mode, ie, you can check out a tree from git using CVS. You can even commit to the tree, but features like merging are absent, and branches are handled as CVS modules, which is likely to shock a veteran CVS user.</p> <a name="user-content-tests-impressions"></a> <div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Tests/Impressions</h2><a id="user-content-testsimpressions" class="anchor" aria-label="Permalink: Tests/Impressions" href="#testsimpressions"><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">As I (Brett Cannon) am left with the task of making the final decision of which/any DVCS to go with and not my co-authors, I felt it only fair to write down what tests I ran and my impressions as I evaluate the various tools so as to be as transparent as possible.</p> <a name="user-content-barrier-to-entry"></a> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Barrier to Entry</h3><a id="user-content-barrier-to-entry" class="anchor" aria-label="Permalink: Barrier to Entry" href="#barrier-to-entry"><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 amount of time and effort it takes to get a checkout of Python's repository is critical. If the difficulty or time is too great then a person wishing to contribute to Python may very well give up. That cannot be allowed to happen.</p> <p dir="auto">I measured the checking out of the 2.x trunk as if I was a non-core developer. Timings were done using the <code>time</code> command in zsh and space was calculated with <code>du -c -h</code>.</p> <markdown-accessiblity-table><table> <thead valign="bottom"> <tr><th>DVCS</th> <th>San Francisco</th> <th>Vancouver</th> <th>Space</th> </tr> </thead> <tbody valign="top"> <tr><td>svn</td> <td>1:04</td> <td>2:59</td> <td>139 M</td> </tr> <tr><td>bzr</td> <td>10:45</td> <td>16:04</td> <td>276 M</td> </tr> <tr><td>hg</td> <td>2:30</td> <td>5:24</td> <td>171 M</td> </tr> <tr><td>git</td> <td>2:54</td> <td>5:28</td> <td>134 M</td> </tr> </tbody> </table></markdown-accessiblity-table> <p dir="auto">When comparing these numbers to svn, it is important to realize that it is not a 1:1 comparison. Svn does not pull down the entire revision history like all of the DVCSs do. That means svn can perform an initial checkout much faster than the DVCS purely based on the fact that it has less information to download for the network.</p> <a name="user-content-performance-of-basic-information-functionality"></a> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Performance of basic information functionality</h3><a id="user-content-performance-of-basic-information-functionality" class="anchor" aria-label="Permalink: Performance of basic information functionality" href="#performance-of-basic-information-functionality"><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">To see how the tools did for performing a command that required querying the history, the log for the <code>README</code> file was timed.</p> <markdown-accessiblity-table><table> <thead valign="bottom"> <tr><th>DVCS</th> <th>Time</th> </tr> </thead> <tbody valign="top"> <tr><td>bzr</td> <td>4.5 s</td> </tr> <tr><td>hg</td> <td>1.1 s</td> </tr> <tr><td>git</td> <td>1.5 s</td> </tr> </tbody> </table></markdown-accessiblity-table> <p dir="auto">One thing of note during this test was that git took longer than the other three tools to figure out how to get the log without it using a pager. While the pager use is a nice touch in general, not having it automatically turn on took some time (turns out the main <code>git</code> command has a <code>--no-pager</code> flag to disable use of the pager).</p> <a name="user-content-figuring-out-what-command-to-use-from-built-in-help"></a> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Figuring out what command to use from built-in help</h3><a id="user-content-figuring-out-what-command-to-use-from-built-in-help" class="anchor" aria-label="Permalink: Figuring out what command to use from built-in help" href="#figuring-out-what-command-to-use-from-built-in-help"><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">I ended up trying to find out what the command was to see what URL the repository was cloned from. To do this I used nothing more than the help provided by the tool itself or its man pages.</p> <p dir="auto">Bzr was the easiest: <code>bzr info</code>. Running <code>bzr help</code> didn't show what I wanted, but mentioned <code>bzr help commands</code>. That list had the command with a description that made sense.</p> <p dir="auto">Git was the second easiest. The command <code>git help</code> didn't show much and did not have a way of listing all commands. That is when I viewed the man page. Reading through the various commands I discovered <code>git remote</code>. The command itself spit out nothing more than <code>origin</code>. Trying <code>git remote origin</code> said it was an error and printed out the command usage. That is when I noticed <code>git remote show</code>. Running <code>git remote show origin</code> gave me the information I wanted.</p> <p dir="auto">For hg, I never found the information I wanted on my own. It turns out I wanted <code>hg paths</code>, but that was not obvious from the description of "show definition of symbolic path names" as printed by <code>hg help</code> (it should be noted that reporting this in the PEP did lead to the Mercurial developers to clarify the wording to make the use of the <code>hg paths</code> command clearer).</p> <a name="user-content-updating-a-checkout"></a> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Updating a checkout</h3><a id="user-content-updating-a-checkout" class="anchor" aria-label="Permalink: Updating a checkout" href="#updating-a-checkout"><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">To see how long it takes to update an outdated repository I timed both updating a repository 700 commits behind and 50 commits behind (three weeks stale and 1 week stale, respectively).</p> <markdown-accessiblity-table><table> <thead valign="bottom"> <tr><th>DVCS</th> <th>700 commits</th> <th>50 commits</th> </tr> </thead> <tbody valign="top"> <tr><td>bzr</td> <td>39 s</td> <td>7 s</td> </tr> <tr><td>hg</td> <td>17 s</td> <td>3 s</td> </tr> <tr><td>git</td> <td>N/A</td> <td>4 s</td> </tr> </tbody> </table></markdown-accessiblity-table> <div dir="auto"> <p dir="auto">Note</p> <p dir="auto">Git lacks a value for the <em>700 commits</em> scenario as it does not seem to allow checking out a repository at a specific revision.</p> </div> <p dir="auto">Git deserves special mention for its output from <code>git pull</code>. It not only lists the delta change information for each file but also color-codes the information.</p> <a name="user-content-decision"></a> <div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Decision</h2><a id="user-content-decision" class="anchor" aria-label="Permalink: Decision" href="#decision"><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">At PyCon 2009 the decision was made to go with Mercurial.</p> <a name="user-content-why-mercurial-over-subversion"></a> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Why Mercurial over Subversion</h3><a id="user-content-why-mercurial-over-subversion" class="anchor" aria-label="Permalink: Why Mercurial over Subversion" href="#why-mercurial-over-subversion"><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">While svn has served the development team well, it needs to be admitted that svn does not serve the needs of non-committers as well as a DVCS does. Because svn only provides its features such as version control, branching, etc. to people with commit privileges on the repository it can be a hindrance for people who lack commit privileges. But DVCSs have no such limitation as anyone can create a local branch of Python and perform their own local commits without the burden that comes with cloning the entire svn repository. Allowing anyone to have the same workflow as the core developers was the key reason to switch from svn to hg.</p> <p dir="auto">Orthogonal to the benefits of allowing anyone to easily commit locally to their own branches is offline, fast operations. Because hg stores all data locally there is no need to send requests to a server remotely and instead work off of the local disk. This improves response times tremendously. It also allows for offline usage for when one lacks an Internet connection. But this benefit is minor and considered simply a side-effect benefit instead of a driving factor for switching off of Subversion.</p> <a name="user-content-why-mercurial-over-other-dvcss"></a> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Why Mercurial over other DVCSs</h3><a id="user-content-why-mercurial-over-other-dvcss" class="anchor" aria-label="Permalink: Why Mercurial over other DVCSs" href="#why-mercurial-over-other-dvcss"><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">Git was not chosen for three key reasons (see the <a href="http://pycon.blip.tv/file/1947231/" rel="nofollow">PyCon 2009 lightning talk</a> where Brett Cannon lists these exact reasons; talk started at 3:45). First, git's Windows support is the weakest out of the three DVCSs being considered which is unacceptable as Python needs to support development on any platform it runs on. Since Python runs on Windows and some people do develop on the platform it needs solid support. And while git's support is improving, as of this moment it is the weakest by a large enough margin to warrant considering it a problem.</p> <p dir="auto">Second, and just as important as the first issue, is that the Python core developers liked git the least out of the three DVCS options by a wide margin. If you look at the following table you will see the results of a survey taken of the core developers and how by a large margin git is the least favorite version control system.</p> <markdown-accessiblity-table><table> <thead valign="bottom"> <tr><th>DVCS</th> <th>++</th> <th>equal</th> <th>--</th> <th>Uninformed</th> </tr> </thead> <tbody valign="top"> <tr><td>git</td> <td>5</td> <td>1</td> <td>8</td> <td>13</td> </tr> <tr><td>bzr</td> <td>10</td> <td>3</td> <td>2</td> <td>12</td> </tr> <tr><td>hg</td> <td>15</td> <td>1</td> <td>1</td> <td>10</td> </tr> </tbody> </table></markdown-accessiblity-table> <p dir="auto">Lastly, all things being equal (which they are not as shown by the previous two issues), it is preferable to use and support a tool written in Python and not one written in C and shell. We are pragmatic enough to not choose a tool simply because it is written in Python, but we do see the usefulness in promoting tools that do use it when it is reasonable to do so as it is in this case.</p> <p dir="auto">As for why Mercurial was chosen over Bazaar, it came down to popularity. As the core developer survey shows, hg was preferred over bzr. But the community also appears to prefer hg as was shown at PyCon after git's removal from consideration was announced. Many people came up to Brett and said in various ways that they wanted hg to be chosen. While no one said they did not want bzr chosen, no one said they did either.</p> <p dir="auto">Based on all of this information, Guido and Brett decided Mercurial was to be the next version control system for Python.</p> <a name="user-content-transition-plan"></a> <div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Transition Plan</h2><a id="user-content-transition-plan" class="anchor" aria-label="Permalink: Transition Plan" href="#transition-plan"><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-0385" rel="nofollow">PEP 385</a> outlines the transition from svn to hg.</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 has been placed in the public domain.</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>