Fix for Use of exit() or quit()#20
Open
odaysec wants to merge 295 commits into
Open
Conversation
added 30 commits
August 17, 2021 18:28
Increments version for a rotriever release
push gh-pages only on master add benchmarks to docs site benchmarks and docs deploy in single workflow
Calculate benchmarks data for each push on PRs. Compares benchmark results to master (instead of previous commit), and avoids retriggering lifecycles while still allowing checks to run and pass.
Update benchmark data.json to comply with the newest benchmarks
* Fix new true positive analysis warning. Submitted a similar PR upstream. * Eliminate unused dependencies to get rid of some 0% coverage in rotriever proxy files.
* Pass key to createChild, updateSlot, add test * Add fix for nested children arrays * Add benchmarks results for b018a4374ff037832d8817c5eecd9a866f937469 skip-push-benchmarks: true * Add benchmarks results for cf67e67847416a3efaf7ad1c48a198e9b322c149 skip-push-benchmarks: true * Add key to single element when changing from array * Add benchmarks results for 7b035d84334cbad245a57eb84dbc880f8fb5e9bb skip-push-benchmarks: true * Add deviation comments to tests * Add benchmarks results for 323aa7586104f0cb31715e4aa488c9e7d9b55c96 skip-push-benchmarks: true * Update Deviations.md * Add benchmarks results for 84a2b81f277f500076c83ad63d365e098a3d9c4d skip-push-benchmarks: true * Don't use expensive isArray, instead directly check if element before passing it newIdx * Add benchmarks results for d77ddcae5064aad786dd7a16a745cf16d8b3a481 skip-push-benchmarks: true
* LUAFDN-540 Limit pcalls in recursivelyCommitLayoutEffects * Add benchmarks results for cfaf6a261dbfcdf1302576111759edfdca95e9d2 skip-push-benchmarks: true * Lowered threshold to 180, added test to break things * Update dev mode and max run depth * Add benchmarks results for 9b17402a805c9c90daa6561a8529599ac138d139 skip-push-benchmarks: true * Fix whitespace issues in test * Add benchmarks results for 55488503ce63674a1a9158484b5a4b3073f7e15d skip-push-benchmarks: true
* Store should re-assign its event-handling methods in its constructor so that they can be called in isolation without reference to self * More minor fixes, mainly removing Map.new * Fix another round of require paths. Workspace is the local package's src directory. Packages is the local package's explicit dependencies as specified in the rotriver.toml. * Fix some warnings relating to keys not being found on the reconciler import. Reconciler is special, in that it returns a function that needs to be called with a HostConfig object. This is our runtime emulation of a bundle/compile-time injection that happens upstream. Talking with Paul, we need to make it so we can import data-only exports like ReactTypeOfMode, without the need for a host config. We'll figure it out next week, but we should be able to run store-test and some of the other self-contained unit tests in the meantime. * Expose ReactFiberFlags in ReactFiberReconciler * Renderer calls aren't instance calls * Introduce Agent type * Properly return exports for cache, even thought the module isn't used. Manually fix another stylua misformat bug. * First pass at a public interface for devtools-shared. Like the shared/ directory upstream, there's no explicit interface (yet).
…sages (#192) * Make ReactFiberComponentStack exception handling durable against all kinds of error shapes that could be thrown * export unstable_batchedUpdates to be consistent with other renderers. * export createTextInstance and throw an unimplemented error for clearer feedback when porting upstream tests. * Fix some of the string formatting issues lying in wait mentioned in the JIRA ticket. This functionality is already covered upstream by a test file we haven't ported yet, so port the relevant portions of that file. * Enable many newly ported upstream tests. * Review all console.error messages for bugs and issues. Found a number of issues and fixed them. Most of the bugs would have been found with the upstream createReactClassIntegration-test file, which we haven't ported yet. Saving that step for another ticket. * Review all the invariant messages, and fix a few issues found. Port an upstream test file over that would have covered things. Add some deviation and TODO comments. * Add missing upstream comments, remove some out-of-date deciation/FIXME comments. * Fix https links * Fix a very interesting bug that would have bit us deeply. This was partially due to the deviated logic around when we can check for 'ref.current', and that we weren't consistent about using hard errors around use of string refs.
* I could not figure out how to do the console spying, so I created a completely deviant `toLogDev` matcher. We should do a proper `spyOnDevAndProd` implementation in jest, which will likely need some intimacy with the `console` in LuauPolyfill. * The Suspense tests for DebugTracing aren't passing because we never get the `resolve` message. Files LUAFDN-564 to track that future work.
* change scheduler's work window
* Switch back to setTimeout skip-push-benchmarks: true
* Fix numerous wrong-code bugs in the initial react-devtools-shared and react-debug-tools translation
* Align upstream types and comments in react-devtools-shared and react-debug-tools. Fix all nonstrict and most strict analysis issues. Add nonstrict to robloxrc for both packages.
* Fix slightly misaligned types and some missing types (`any`) in react-reconciler and shared
* Move the `Dispatcher` type to Shared so it can be used without running into circular dependencies
* We actually get 'code is too complex to typecheck' warnings when adding `Dispatcher` type annotation in a key place. Add a FIXME comments and make it `Object` for now.
* Today I learned that a function returning void ('()') will not match a function type returning 'any'. It *will* match '...any', though.
* Format react-devtools-shared and react-debug-tools using StyLua. Update StyLua to run on these entire directories.
There are two steps we need to take: Switch to using task.delay Separate yield tracking from frame boundary tracking; decide dynamically when to delay vs. simply yielding This PR will track only step 1. I've created LUAFDN-603 for the second part.
* Set run depth checks to use MAX_RUN_DEPTH * update associated test * update deviation text * Add benchmarks results for d5070ccd96a0422a5c60708c36df78c9e94fb6a9 skip-push-benchmarks: true * Add benchmarks results for 7f52b3f9e49cecbbd101ce43a31c3cd3c5157e60 skip-push-benchmarks: true
This addresses the issue that folks hit with jest-roblox, where robloxdev-cli convert has different type analysis behavior than roblox-cli analyze
Moves a warning that was happening in non-dev to only happen in dev mode.
* Update to rc.3
Fix bug where reconcileChildrenArray does not pass a value for tableKey causing instance names to be incorrect
… (#207) * Align types that would have allowed Luau type analysis to surface this bug. * Found several more hard runtime error bugs in string formatting by looking closely at strict mode. Another example of upstream using a field that doesn't exist on the type and is never initialized. Marked with a TODO. * Avoid dereferecing a function with a field. We don't currently use the value anyway, so comment out offending code. Comment out now-unused code. Filed a ticket to pick up this color-coding work. * Move UpdateQueue<> types to ReactInternalTypes to avoid future initialization order issues.
* Made types compatible with Luau RFC recursive-type-restriction
… bugs (#206) * Fix hard runtime errors caused by multiple mistranslation of string concatenation. Last bug was some JS WAT behavior upstream relied on. Two previously skipped tests now pass.
…rror (#205) * Fix a mistranslation bug, and fortify the types that *should* find it once Luau issues are fixed. Luau issue filed as CLI-46597 * Put react-cache under StyLua enforcement
* Type the hooks exports. Align more types with upstream, which fixes quite a few strict mode analysis errors where it couldn't infer types. Fix other places where strict analysis couldn't deduce types. skip-push-benchmarks: true
* Switch promise dependency to internal one skip-push-benchmarks: true
Improves the error output when assigning a bad prop. Crucially, this also replaces the hard error with a console.error instead. Before these changes, the UI would fail to render and have no meaningful way to recover unless an error boundary has been established. With these changes, we print an accordingly but swallow the actual hard error. This means that we're a lot more likely to get mostly-working behavior, which may be preferable for production environments. We've kept the hard error for now to avoid losing signal from production / canary testing, but we can remove it once we introduce that logic.
…(#213) * Add strict pragma to easy files * Remove Luau workarounds that are no longer needed * Fix a subtle type bug that led Luau to give an ambiguous error message. Squash the problem entirely and douse the files with strict pramga. * Eradicate local inspect, use the polyfill. * Fix generic type arguments so they don't force an argument when it wouldn't be needed with proper function generics. This fixes an issue found in apollo-client-lua.
…(#214) Closes LUAFDN-622. Exports act from both ReactRoblox and RoactCompat
* More strict mode cleanups, a few of hard are hard bugs -- calling .length, etc. * Clean up store. Add instance fields and methods to the Store type. * Use Array.reverse polyfill * go through strict mode errors with a fine-tooth comb. found many subtle misalignments with upstream, and a few bugs. * Fix another .size mistranslation. I could not get Luau to detect this, even in strict mode and with stronger type annotations than upstream. Filed an issue for Luau. There is no upstream test that fails even when I break it's implementation :( * Fix another bug in react-devtools-shared, found with manual review. It looks like the upstream test 'should handle a stress test with different tree operations (Concurrent Mode)' would have caught this. * Catch up a few missing bits. Add the skipped test that could have caught one of the bugs.
Closes [UIBLOX-2787](https://roblox.atlassian.net/browse/UIBLOX-2787). Implements a small example app to make testing DevTools and other React features easier. The example app itself is taken from the HMR repo.
### Why are the changes being made? Closes [UIBLOX-2778](https://roblox.atlassian.net/browse/UIBLOX-2778). Fixes a few bugs with native element highlights in Devtools: - We now make sure that an instance is a GuiBase2d before trying to read UI properties - OverlayTip now accounts for a global ZIndex - Focusing the viewport no longer ends selection (e.g. clicking from devtools into studio) - Overlapping highlight rects no longer stack their transparency
… (#461) ### Why are the changes being made? Closes [UIBLOX-2757](https://roblox.atlassian.net/browse/UIBLOX-2757). Adds check for touch events when doing element selection in devtools. This adds minimal support for the mobile emulator, but the UX still isn't ideal since you have to hold your pointer down to preview the selection. Unfortunately, I don't think there's a way around this since input events only fire in the emulator when the pointer is down. This shouldn't merge until after #460 because I need to apply the new check to the other input event that PR introduces. ### What changes are being made? - Adds `isInputValid` utility to React DevTools Highlighter to support touch input for Roblox Studio's mobile emulator and updates input handling accordingly. --- - [x] AI-assisted summary reviewed and verified by author
### Why are the changes being made? Closes [UIBLOX-2770](https://roblox.atlassian.net/browse/UIBLOX-2770). ### What changes are being made? - Fixes root name display in React DevTools by initializing flags before importing `ReactDevtoolsCore`, replacing `mountedRoots` table operations with `Set` methods, and using fiber key for root name resolution. --- - [x] AI-assisted summary reviewed and verified by author ---------
### Why are the changes being made? Release version 17.3.2 ### What changes are being made? - Updates version in `rotriever.toml` from `17.3.1` to `17.3.2` for new release preparation --- - [x] AI-assisted summary reviewed and verified by author
### Why are the changes being made? Closes [UIBLOX-1997](https://roblox.atlassian.net/browse/UIBLOX-1997). *Put your pull request body here!* Checklist before submitting: * [ ] Added/updated relevant tests * [ ] Added/updated documentation ### What changes are being made? - Introduces `ReactGlobals` package to replace `_G` for React's global variables, ensuring scoped and type-safe global state per React instance. - Refactors all modules and tests to use `ReactGlobals`, updates dependencies to include the new package, and maintains backward compatibility. - Adds documentation for `ReactGlobals` and resolves cross-plugin state leakage issue described in UIBLOX-1997. --- - [ ] AI-assisted summary reviewed and verified by author
Closes [UIBLOX-2900](https://roblox.atlassian.net/browse/UIBLOX-2900). Adds a `profileOnStart` option when connecting to DevTools. This makes the agent start profiling as soon as the DevTools hook is setup and initialized, before any tree is even mounted. This is a deviation from upstream, which doesn't expose a public API for starting the profiler immediately.
### Why are the changes being made? Add context about changes here. ### What changes are being made? - Updates `roact-alignment` to version `17.3.3` by modifying `ReactVersion.lua` and `rotriever.toml`. --- - [ ] AI-assisted summary reviewed and verified by author
### Why are the changes being made? Closes [UIBLOX-2937](https://roblox.atlassian.net/browse/UIBLOX-2937). Implements a new React Telemetry package for internal-only telemetry collection. This is currently only used for DevTools, but is designed to be easy to use in other applications later. ### What changes are being made? - Adds new `react-telemetry` module for internal telemetry reporting in React apps, including event logging for DevTools connections via `TelemetryService`. - Introduces feature flag `ReactTelemetryEnabled` to gate telemetry functionality and supports custom fields for event data. - Adds configuration and utility files (`.luaurc`, `.robloxrc`, `rotriever.toml`, README, `reportCounter`, `getCustomFields`) to structure and document the module. --- - [x] AI-assisted summary reviewed and verified by author
### Why are the changes being made? Closes [UIBLOX-3019](https://roblox.atlassian.net/browse/UIBLOX-3019). Ports the minimal amount of code from `react-devtools-timeline` required by the latest version of `react-devtools-shared`. This is just Luau types and a couple of constants, but could expand in the future. I considered just inlining these in devtools shared, but wanted to stay aligned with upstream. edit: I also apprantely updated styling for some example files. probably wanna keep that? ### What changes are being made? - Ports minimal subset of `react-devtools-timeline` to support latest `react-devtools-shared` by adding `constants.lua` and `types.lua` with upstream constants and types - Adds new module configuration files `.luaurc`, `.robloxrc`, `default.project.json`, and `rotriever.toml` for `react-devtools-timeline` - Updates example files for compatibility and formatting consistent with Roblox Luau environment --- - [ ] AI-assisted summary reviewed and verified by author
I got an error using hooks incorrectly, but all I saw was ``` invalid argument Roblox#4 to 'format' (string expected, got table) ------ Error caught by React ------ ReplicatedStorage.Packages._Index.ReactRoblox.ReactRoblox.client.roblox.RobloxComponentProps:242 function setInitialProperties ReplicatedStorage.Packages._Index.ReactRoblox.ReactRoblox.client.ReactRobloxHostConfig:407 ``` It's because hooks error is an Error object from Polyfill and tostring is not called by format (no idea why) Now the errors look like ``` Error applying initial props to Roblox Instance 'SizeConstraint' (UISizeConstraint): Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: 1. You might have mismatching versions of React and the renderer (such as React DOM) 2. You might be breaking the Rules of Hooks 3. You might have more than one copy of React in the same app See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem. ``` Checklist before submitting: * [ ] Added/updated relevant tests * [ ] Added/updated documentation ---------
### Why are the changes being made? When re-rendering a component using derived state idiom for functional components, if the component had any useCallbacks inside it, React would error with `Rendered more hooks than during the previous render.` when in DEV mode. It looks like this was caused by a mistranslation where instead of calling updateCallback, we would call mountCallback in DEV mode. Note that in non-DEV mode, we already call the correct api (updateCallback) and this seems to be a mistranslation since this was implemented correctly in upstream: https://github.com/facebook/react/blob/43363e2795393a00fd77312a16d6b80e626c29de/packages/react-reconciler/src/ReactFiberHooks.new.js#L2289 Unflagged because it's under DEV mode.
### Why are the changes being made? Closes [UIBLOX-3203](https://roblox.atlassian.net/browse/UIBLOX-3203). Repository facelift! - Clears out the root readme because everything there was outdated and/or not useful for anyone - Rewrites the readme with better branding and no internal jargon - Adds a gitattributes file for luau - Removes the deviations.md file as it was just a to-do file for roact and all were resolved - Removes standalone/ directory because it was unused - Removes the examples/ directory because all the examples were outdated and most showed code style we don't want to encourage - We'll be showing better code examples in the upcoming docs refresh Currently the readme is pretty empty. Once the docs are refreshed the readme can be added to with useful information.
### Why are the changes being made? Closes [UIBLOX-3261](https://roblox.atlassian.net/browse/UIBLOX-3261). Adds a new flag for React to catch any fiber that yields when in DEV mode. Nothing in React supports yielding today, and when you do yield it often results in undefined behaviour. This flag enables an explicit error telling the user that their code is yielding. ### What changes are being made? - Adds `catchYieldingInDEV` feature flag and integrates it into React scheduler to error on yielding within components/hooks during DEV mode - Implements `NoYield` utility to enforce no-yield behavior in callbacks - Updates `ReactFeatureFlags` and adds comprehensive tests for the new yield-catching mechanism --- - [x] AI-assisted summary reviewed and verified by author
### Why are the changes being made? Just cleaning up flags that are completely unused in React today. They have no reference anywhere else in the code. ### What changes are being made? - Removes 13 unused feature flags from the `ReactFeatureFlags` module. - Cleans up related test files to eliminate obsolete feature flag references. - Improves maintainability by reducing dead code and configurations. --- - [x] AI-assisted summary reviewed and verified by author
### Why are the changes being made? Adds documentation to the bulk of React's public API for a better editor experience. ### What changes are being made? - Adds detailed documentation comments to most React public APIs in `react-roblox`, covering functions, hooks, and components. - Enhances code readability and editor support with parameter descriptions, return values, and official React API reference links. --- - [x] AI-assisted summary reviewed and verified by author
### Why are the changes being made? Closes [UIBLOX-3280](https://roblox.atlassian.net/browse/UIBLOX-3280). React stacktraces kinda suck right now. They can be huge and the vast majority of the frames in the stacktrace are from React internal modules. This gets worse the larger the tree is due to React's recursion. This PR: - Introduces a new feature flag for filtering stack frames - Implements a best-effort algorithm for determining if a stack frame is from inside React - Works out the path of known React packages in the datamodel and then checks if the frame is under one of those paths - Does not filter any stack frame if the first stack frame is from inside React (i.e the error originated internally) Before: ``` CorePackages._Workspace.Scheduler.Scheduler.forks.SchedulerHostConfig.default:316: CorePackages._Workspace.Scheduler.Scheduler.forks.SchedulerHostConfig.default:293: ------ Error caught by React ------ Something went very wrong! ------ Error caught by React ------ CorePackages._Workspace.ExampleApp.ExampleApp.someLibraryModule:4 function intentionallyFailingMethod CorePackages._Workspace.ExampleApp.ExampleApp.NameTag:25 function Name CorePackages._Workspace.ReactReconciler.ReactReconciler.ReactFiberHooks.new:3196 function renderWithHooks CorePackages._Workspace.ReactReconciler.ReactReconciler.ReactFiberBeginWork.new:209 function renderWithHooks CorePackages._Workspace.ReactReconciler.ReactReconciler.ReactFiberBeginWork.new:867 function updateFunctionComponent CorePackages._Workspace.ReactReconciler.ReactReconciler.ReactFiberBeginWork.new:3509 function beginWork CorePackages._Workspace.ReactReconciler.ReactReconciler.ReactFiberWorkLoop.new:253 CorePackages._Workspace.Shared.Shared.invokeGuardedCallbackImpl:30 function invokeGuardedCallbackProd CorePackages._Workspace.Shared.Shared.ReactErrorUtils:49 CorePackages._Workspace.ReactReconciler.ReactReconciler.ReactFiberWorkLoop.new:3474 CorePackages._Workspace.ReactReconciler.ReactReconciler.ReactFiberWorkLoop.new:1972 CorePackages._Workspace.ReactReconciler.ReactReconciler.ReactFiberWorkLoop.new:1860 CorePackages._Workspace.ReactReconciler.ReactReconciler.ReactFiberWorkLoop.new:1809 CorePackages._Workspace.ReactReconciler.ReactReconciler.ReactFiberWorkLoop.new:942 CorePackages._Workspace.ReactReconciler.ReactReconciler.ReactFiberWorkLoop.new:858 CorePackages._Workspace.Scheduler.Scheduler.Scheduler:320 CorePackages._Workspace.Scheduler.Scheduler.Scheduler:268 CorePackages._Workspace.Scheduler.Scheduler.forks.SchedulerHostConfig.default:241 function doWork CorePackages._Workspace.Scheduler.Scheduler.forks.SchedulerHostConfig.default:277 function performWorkUntilDeadline ``` After: ``` CorePackages._Workspace.Scheduler.Scheduler.forks.SchedulerHostConfig.default:316: CorePackages._Workspace.Scheduler.Scheduler.forks.SchedulerHostConfig.default:293: ------ Error caught by React ------ Something went very wrong! ------ Error caught by React ------ CorePackages._Workspace.ExampleApp.ExampleApp.someLibraryModule:4 function intentionallyFailingMethod CorePackages._Workspace.ExampleApp.ExampleApp.NameTag:25 function Name ``` ### What changes are being made? - Adds `filterInternalStackFrames` feature flag to exclude React internal stack frames from error traces for improved readability. - Implements `buildStackString` function to construct filtered stack traces by identifying and omitting known React internal modules. - Updates `describeError` to apply stack frame filtering based on the new feature flag while preserving unfiltered errors from React internals. --- - [x] AI-assisted summary reviewed and verified by author
### Why are the changes being made? Closes [UIBLOX-3163](https://roblox.atlassian.net/browse/UIBLOX-3163). Updates DevTools to use the new user-space WebSocket API that's developer-accessible in Studio. This unblocks a couple of internal teams adopting DevTools, and will allow the wider community to use it as well. This change is flagged behind `ReactDevtoolsUseHttpWebStream` because I'd like to get it out sooner rather than later, but releasing it without waiting a few weeks will probably break some internal workflows (e.g. people on an outdated version of studio). Once the new API has been live for a month or so I'll come back and clean up the flag. ### What changes are being made? - Updates DevTools to use `HttpService:CreateWebStreamClient` and renders GUI in `Players.LocalPlayer.PlayerGui` with adjusted `App.lua` GUI properties for user-space compatibility. --- - [x] AI-assisted summary reviewed and verified by author
As mentioned in #488 we noticed that the rotriever version used in the repo is so old that one of the bugs in it was causing non-publish packages to become published. This PR bumps the rotriever version to pull in any more modern bugfixes and features :)
While working on publishing this repo to the Creator Store, I noticed that some `publish = true` packages depend on the following `publish = false` packages: - `modules/react-noop-renderer` - `modules/scheduler` - `modules/shared` This breaks our Creator Store publishing workflow as we assume `publish = false` packages should not be included in the final build, but depending on them from a `publish = true` package conflicts with this. Furthermore, it turns out the rotriever version used in this repo is old enough that this setting isn't respected anyway, so all of the nonpublish packages are, in fact, published: https://rotriever.simulprod.com/package/Shared So this PR removes the `publish = false` declarations from the rotriever TOMLs since they aren't doing anything (except breaking our automation!) and don't seem to make sense anyway given they're publicly depended upon. It is better to have these TOMLs reflect their actual behaviour so that rotriever can be safely updated in the future without stopping updates from being pushed to the registry.
### Why are the changes being made? Updates the documentation site to use the new `react-luau.dev` URL. ### What changes are being made? - Updates `mkdocs.yml` site metadata (site name, URL, repo) and fixes `nav` indentation for nested pages. --- - [x] AI-assisted summary reviewed and verified by author
### Why are the changes being made? Updates the error message when a component yields in DEV mode to more clearly explain the error and point the user towards the doc on yielding. ### What changes are being made? - Updates DEV no-yield error in `NoYield.lua` to multi-line; explains yields stall scheduler and links `go/react-yield-error` --- - [ ] AI-assisted summary reviewed and verified by author
Implements react/react#21039 on our codebase. Creates a new deleted tree clean up level with three distinct levels. Facebook did an experiment and found level 3 to be the best, we should do the same and see whether the existing path, 1, 2, or 3 is the best.
Rotriever requires readmes for publishing now. Added stubs.
lute versions was too old, foreman couldn't even see it https://github.com/Roblox/roact-alignment/actions/runs/23354471638/job/67941642914 Checklist before submitting: * [ ] Added/updated relevant tests * [ ] Added/updated documentation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The
exitandquit"functions" are actuallysite.Quitterobjects and are loaded, at interpreter start up, from site. However, if the interpreter is started with the -S flag, or a custom site is used then exit and quit may not be present. In thisexit()is used and will fail if the interpreter is passed the -S option.Use
sys.exit(1)instead ofexit(1)in this script.sys.exitis always available after importingsys(already imported at line 17), and is the correct non-interactive termination API. Best fix in this snippet: update the three shown occurrences in argument parsing error branches (lines 63, 72, and 81) fromexit(1)tosys.exit(1).Checklist before submitting: