Danny Yang
yangdanny@meta.com
90d · built 2026-05-28
90-day totals
- Commits
- 149
- Grow
- 4.5
- Maintenance
- 4.4
- Fixes
- 6.8
- Total ETV
- 15.7
Where this dev ranks
Percentile against the global top-100 leaderboard (all-time totals).
- By commits
- Top 19 %
- By Growth share
- Top 62 %
30-day trajectory
Last 30 days vs. the 30 days before. Up arrows on Growth and ETV mean improvement; up arrow on Fixes share means more time on fixes (worse).
Daily performance
Daily ETV, stacked by Growth, Maintenance and Fixes.
Work-mix over time
Share of Growth / Maintenance / Fixes over a rolling 7-day window. Reads as 'where is effort flowing right now'.
Bug flow over time
Monthly bug flow attributed to this developer. The left bar (red) is bug impact this dev authored that was addressed in the given month — combining bugs others fixed for them and bugs they fixed themselves. The right bar is fixes they personally shipped that month, split between self-fixes (overlap with the red bar) and fixes done for someone else. X-axis is fix-time, not introduction-time — the Navigara API attributes bugs backward to the author at the moment the fix lands.
- Self-fix share
- 20%
- Bugs you introduced
- 21.6
- Bugs you fixed
- 25.2
Repository spread
Where this developer's commits land. Concentrated work (top1 > 80%) vs polymath spread (top1 < 30%).
Most impactful commits
Top 20 by ETV in the 90-day window.
- 1.6ETVFix suppression matching for f/t-strings Summary: `# pyrefly: ignore` comments placed above or on the closing line of a multi-line f/t-string now suppress errors inside the string. Extracts f-string ranges from the AST at the `Errors` level and plumbs them into `ErrorCollector::collect_into` to check suppression at the f-string's start and end lines in addition to the error's own line. Now, if the error suppression comment applies to either the first or last line of the f-string, all errors in the f-string are suppressed. Reviewed By: stroxler Differential Revision: D95964858 fbshipit-source-id: 29c693b3010db66e1f90a17dec2e674590ab4579github.com-facebook-pyrefly · 4db55230 · 2026-03-12
- 1.4ETVport the benchmarks from type_coverage_py repo Summary: This is ported directly from https://github.com/lolpack/type_coverage_py, with a few minor modifications. These are intended to be PUBLIC benchmarks that anyone can run. Changes made: 1. add --runs flag to type checker benchmark 2. fix macos memory measurements to use /usr/bin/time. previously it was completely wrong and only recorded the memory if a type checker used more memory than all type checkers that ran before it, which means in practice only pyright and ty had results 3. integrate the lsp daily_runner.py file (which handles cloning and orchestration) into the lsp_benchmark script directly For now, it should be run using python directly, not via buck Further improvements to come in later diffs Reviewed By: grievejia Differential Revision: D96997879 fbshipit-source-id: 8f78a15e57d5fb19e5539b57e446547b1ad721afgithub.com-facebook-pyrefly · c39a6837 · 2026-03-18
- 0.8ETVPreserve literal member type in enums Summary: Instead of promoting away the enum member's literal type, we preserve the unpromoted literal & change VisitMut to skip it. Then, in alt/class/enums.rs we modify some logic to decide when to promote away the literal & when to keep it. The special enum attr resolution is weirdly complex because it deals with a bunch of different conditions like django and mixins. I'm not a big fan of how complex it is but it seems necessary. closes https://github.com/facebook/pyrefly/issues/2741 Reviewed By: grievejia Differential Revision: D96157102 fbshipit-source-id: 69ae410dc1afcec9e3a4c290f7724a6560bdb38fgithub.com-facebook-pyrefly · 350bac26 · 2026-04-03
- 0.5ETVFix __slots__ error on cross-module class imports Summary: When a class with `__slots__` was imported from another module, and the importing module also defined a class with `__slots__`, pyrefly could report a spurious "not declared in `__slots__`" error on valid attribute accesses. This happened because `ClassDefIndex` is a per-file counter, so looking up an imported class's `__slots__` binding in the current module's binding table could match a completely different class that happened to share the same index. Move the `__slots__` name extraction from `attr.rs` to class metadata computation, which always runs in the class's own module where `self.bindings()` correctly resolves the `ClassDefIndex`. The extracted slot names are stored in a new `SlotsInfo` field on `ClassMetadata`, and`extract_local_slot_names` now reads from metadata instead of bindings. fixes https://github.com/facebook/pyrefly/issues/2950 Reviewed By: rchen152, stroxler Differential Revision: D99442589 fbshipit-source-id: af82359e439011cdfd6bd7d2e5fbc1d33db1f04bgithub.com-facebook-pyrefly · a1f6301a · 2026-04-03
- 0.5ETVattempt to fix panic in LSP Summary: for https://github.com/facebook/pyrefly/issues/2784 There is no codebase to repro this so it's only an attempted fix, I'll ask the users to try it after next release Reviewed By: rchen152 Differential Revision: D96791064 fbshipit-source-id: 1fd2df6ab401d0fcd34336b80a8e4446288171ecgithub.com-facebook-pyrefly · 076a458e · 2026-03-16
- 0.5ETVstubgen: add overloads, type constructors, old-style aliases, and PEP 695 generics (#2721) Summary: Port several features from the AST-only stubgen (PR #2721) into the inference-based implementation: - **Overload handling**: Skip non-overloaded implementations when `overload` variants exist, keeping only the typed overload signatures in stubs. - **TypeVar/NamedTuple/TypedDict preservation**: Recognize assignments like `T = TypeVar('T')`, `ParamSpec`, `TypeVarTuple`, `NewType`, `NamedTuple`, and `TypedDict` calls and emit them verbatim instead of trying to infer types. - **Old-style type alias detection**: Preserve assignments with subscript RHS (`Vector = List[float]`) or union pipe RHS (`X = int | str`) verbatim as type aliases. - **PEP 695 generics**: Extract and emit `type_params` for both classes (`class Stack[T]:`) and functions (`def first[T](...)`). Also adds snapshot tests for each new feature (overloads, typevar, type_alias_old_style, generics). Pull request resolved: #2721 Reviewed By: lolpack Differential Revision: D95793377 fbshipit-source-id: a48aa2d57278dd3b839c9d9c6ce9bbcda93d0d64github.com-facebook-pyrefly · f8b1152b · 2026-03-16
- 0.5ETVstubgen: emit synthesized `__init__` for dataclasses (#3586) Summary: Pull Request resolved: https://github.com/facebook/pyrefly/pull/3586 closes https://github.com/facebook/pyrefly/issues/3221 Dataclasses (and similar patterns like NamedTuples) generate their `__init__` at type-check time rather than declaring it in source. Previously, stubgen would omit the `__init__` entirely for these classes, producing stubs that lost the constructor signature. Look up `KeyClassSynthesizedFields` in the answers to find the synthesized `__init__` type (a `Type::Function` with the full `Callable` signature), then convert its `Param` list into stub parameters. Only emitted when no explicit `__init__` exists in the source. Reviewed By: rchen152 Differential Revision: D106327984 fbshipit-source-id: f7476513b3234393945e6737dfca32cea56f8297github.com-facebook-pyrefly · fc794752 · 2026-05-26
- 0.5ETVNarrow individual variables in tuple match subjects Summary: When the match subject is a tuple expression (e.g., `match x, y:`), individual variables were not being narrowed by corresponding sub-patterns because `expr_to_subjects` returns empty for tuple expressions, leaving no narrowing subject for the MatchSequence handler. Fix: extract per-element narrowing subjects from the tuple elements and pass them to the MatchSequence handler, which uses them directly instead of faceting a single parent subject. fixes #2863 Reviewed By: rchen152 Differential Revision: D98297415 fbshipit-source-id: 838e52b1e716d618193fe2b9f297bcd4d649d6c9github.com-facebook-pyrefly · 1e6ac255 · 2026-04-01
- 0.4ETVmigrate pyrefly report test suite to snapshot testing Summary: The unit tests were too unwieldy Reviewed By: grievejia Differential Revision: D95792654 fbshipit-source-id: 6b2480fa869704ca026bff943ca613e2171fb425github.com-facebook-pyrefly · 14774163 · 2026-03-10
- 0.4ETVimprove typed dict error messages Summary: fixes https://github.com/facebook/pyrefly/issues/3210 1. make invalid assignments report bad-assignment rather than bad-typed-dict-key, the key exists but the value is wrong 2. print out anonymous typed dict errors differently 3. for anonymous typed dict index errors, emit bad-index rather than bad-typed-dict-key, since anonymous typed dict is an implementation detail Reviewed By: grievejia Differential Revision: D105733104 fbshipit-source-id: 796a15ea7c98133c2ddf54d96bdba03bbbdab589github.com-facebook-pyrefly · 7c7916b1 · 2026-05-19
- 0.4ETVAdd stubgen extraction logic Summary: Add the core extraction that walks a type-checked module's AST and builds stub declarations. Uses pyrefly's binding/answer system to resolve inferred types for functions, classes, and variables. Reviewed By: rchen152 Differential Revision: D95791732 fbshipit-source-id: da16334d228306af479bc2b0291e7149a07929d0github.com-facebook-pyrefly · e6e6dfaa · 2026-03-16
- 0.4ETVAdd integration tests for stubgen with checked-in fixtures (#2808) Summary: Pull Request resolved: https://github.com/facebook/pyrefly/pull/2808 Add snapshot-based integration tests for the stubgen command. Each test case has a checked-in input.py and expected.pyi pair under pyrefly/lib/test/stubgen/. Test categories: - functions: params, defaults, async, pos-only, kw-only, varargs - classes: empty class, inheritance, methods, attributes - variables: annotated module-level variables with values - imports: preserved import statements - mixed: type aliases, classes, and functions together The test harness supports an update mode via STUBGEN_TEST_WRITE_PATH env var for regenerating expected output after intentional changes. Reviewed By: rchen152 Differential Revision: D95791749 fbshipit-source-id: 0ec29cfe5371533979b0a90c350ba7e7d0accb33github.com-facebook-pyrefly · dead632c · 2026-03-16
- 0.3ETVFix provide-type for operator results and type alias qualification Summary: The provide-type endpoint had two bugs where it returned incorrect types: 1. For operator expressions like `+pos`, the endpoint returned the dunder method signature (`(self: Pos) -> Literal[False]`) instead of the expression's result type (`Literal[False]`). The fix is to use `get_result_type_at` instead of `type_from_expression_at` for the provide_type API 2. Type alias names in function signatures were not module-qualified (showed `TA` instead of `bar.TA`). The solution is to store the module in the union display_name field, which shows the original type alias name for unions. fixes https://github.com/facebook/pyrefly/issues/2975 Reviewed By: rchen152 Differential Revision: D99215882 fbshipit-source-id: 802bb97ec815efe49167459dd9b144f024655a86github.com-facebook-pyrefly · 88da6cc2 · 2026-04-02
- 0.3ETVAdd --comment-location flag for configurable suppression comment placement Summary: Add a flag that puts trailing suppression comments rather than putting them on the line before. This flag only applies to `pyrefly suppress`, not `pyrefly check --suppress-errors` which defaults to the old behavior. Default behavior does not change. Google said they would help maintain it. fixes #2648 Reviewed By: rchen152 Differential Revision: D98297121 fbshipit-source-id: e5dbd0d96c53e9a5111baf235a9cf0d67b6eb481github.com-facebook-pyrefly · b2fd8a63 · 2026-03-26
- 0.2ETVAdd backslash continuation support for suppression comments Summary: We can't put a suppression comment after the `\` in a backslash continuation, nor can we put a suppression comment in between lines. We should apply the same pattern here as we do for multi-line strings, where the suppression above the first line applies to the whole expression. The logic handles backslashes appearing in multiline strings, in comments, etc. fixes https://github.com/facebook/pyrefly/issues/2935 Reviewed By: maggiemoss Differential Revision: D98363019 fbshipit-source-id: 7d05d84a46afd9428f19d04fff3e72c55633bd9egithub.com-facebook-pyrefly · 08a6ae58 · 2026-03-31
- 0.2ETVExclude private module symbols & attributes Summary: Typestats does not report private class methods or attributes (those with a single-underscore prefix like _method or _attr). Pyrefly was reporting all class members regardless of visibility, causing ~2,100 extra symbols in the pandas comparison (87% of the 3,131 pyrefly_only diffs). Filter out class methods and instance attrs whose name starts with _ but not __ (dunders like __init__ are kept). Module-level private names are unaffected since they go through the exports filter. Update inherited_attrs test to cover both public methods (kept) and private methods (filtered). Reviewed By: rchen152 Differential Revision: D99628474 fbshipit-source-id: 8376e18f8d3759737d2b2a62811d064f9b48c1afgithub.com-facebook-pyrefly · db31b9ba · 2026-04-06
- 0.2ETVAdd stubgen data model and emitter Summary: Add the stub data model (ModuleStub, StubItem, StubFunction, StubClass, StubVariable, etc.) and the emitter that generates .pyi text from it. The data types represent the intermediate representation of a stub file, and the emitter handles formatting concerns like spacing, indentation, parameter rendering, and the Incomplete import. Reviewed By: rchen152 Differential Revision: D95791729 fbshipit-source-id: c6d9debc04fc630426bfd3e7093b5f51d9aac9efgithub.com-facebook-pyrefly · d08832e3 · 2026-03-16
- 0.2ETVdeduplicate identical TypeVars when merging control flow branches Summary: When try/except (or other branching) defines the same TypeVar in multiple branches with different qualified names but identical name, constraint, etc, we create a union of type vars, which cannot be used as a type form. This fix checks that the type vars are structurally identical & have the same name, and merges them. fixes https://github.com/facebook/pyrefly/issues/3402 Reviewed By: rchen152 Differential Revision: D106520566 fbshipit-source-id: af3996d3859da6e3a606040b92c1eec81b68d819github.com-facebook-pyrefly · f65b3233 · 2026-05-27
- 0.2ETVImplement PEP 800 disjoint bases for subclasses (#1592) (#2726) Summary: Pull Request resolved: https://github.com/facebook/pyrefly/pull/2726 The `disjoint_base()` function previously only checked if a class itself was decorated with `disjoint_base`. It did not walk the MRO to find disjoint base ancestors. This meant that subclasses of disjoint bases (e.g. `class A(str)` and `class B(int)`) were not recognized as disjoint — their intersection produced `A & B` instead of `Never`. Fix: Walk the MRO in `disjoint_base()` to find the most specific ancestor marked `disjoint_base`. Changed return type from `&Class` to owned `Class` (cheap — wraps `Arc`) to avoid lifetime issues with the local MRO. fixes https://github.com/facebook/pyrefly/issues/1592 Reviewed By: rchen152 Differential Revision: D95800401 fbshipit-source-id: 9f8907d37ef444d9d6c55f18ef24fb4ab203f1c2github.com-facebook-pyrefly · 31524c53 · 2026-03-09
- 0.2ETVfix false positive w/ multiple match subjects #2168 Summary: Previously, we were only doing some narrow ops if the subject was a single variable. This diff makes it unconditional fixes https://github.com/facebook/pyrefly/issues/2168 Reviewed By: grievejia Differential Revision: D97624241 fbshipit-source-id: 60bbbe57a5faad8c50bea0ef136e7ac0052bec4cgithub.com-facebook-pyrefly · cc8da164 · 2026-03-24