Skip to content

Commit d81ba58

Browse files
committed
Merge branch 'main' into brent/future-annotations-2
2 parents eba43a1 + a357a68 commit d81ba58

755 files changed

Lines changed: 87897 additions & 9339 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/sync_typeshed.yaml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,40 @@ jobs:
3636
run: |
3737
git config --global user.name typeshedbot
3838
git config --global user.email '<>'
39+
- uses: astral-sh/setup-uv@bd01e18f51369d5a26f1651c3cb451d3417e3bba # v6.3.1
3940
- name: Sync typeshed
4041
id: sync
4142
run: |
43+
docstring_adder="git+https://github.com/astral-sh/docstring-adder.git@6de51c5f44aea11fe8c8f2d30f9ee0683682c3d2"
44+
45+
# Run with the full matrix of Python versions supported by typeshed,
46+
# so that we codemod in docstrings that only exist on certain versions.
47+
#
48+
# The codemod will only add docstrings to functions/classes that do not
49+
# already have docstrings. We run with Python 3.14 before running with
50+
# any other Python version so that we get the Python 3.14 version of the
51+
# docstring for a definition that exists on all Python versions: if we
52+
# ran with Python 3.9 first, then the later runs with Python 3.10+ would
53+
# not modify the docstring that had already been added using the old version of Python.
54+
#
55+
# TODO: In order to add docstrings for platform-specific APIs, we would also
56+
# need to run the codemod on Windows. We get the runtime docstrings by inspecting
57+
# the docstrings at runtime, so if an API doesn't exist at runtime (because e.g.
58+
# it's Windows-specific and we're running on Linux), then we won't add a docstring to it.
59+
#
60+
uvx --python=3.14 --force-reinstall --from="${docstring_adder}" add-docstrings --stdlib-path ./typeshed/stdlib
61+
uvx --python=3.13 --force-reinstall --from="${docstring_adder}" add-docstrings --stdlib-path ./typeshed/stdlib
62+
uvx --python=3.12 --force-reinstall --from="${docstring_adder}" add-docstrings --stdlib-path ./typeshed/stdlib
63+
uvx --python=3.11 --force-reinstall --from="${docstring_adder}" add-docstrings --stdlib-path ./typeshed/stdlib
64+
uvx --python=3.10 --force-reinstall --from="${docstring_adder}" add-docstrings --stdlib-path ./typeshed/stdlib
65+
uvx --python=3.9 --force-reinstall --from="${docstring_adder}" add-docstrings --stdlib-path ./typeshed/stdlib
66+
67+
# Here we just reformat the codemodded stubs so that they are
68+
# consistent with the other typeshed stubs around them.
69+
# Typeshed formats code using black in their CI, so we just invoke
70+
# black on the stubs the same way that typeshed does.
71+
uvx --directory=typeshed pre-commit run -a black || true
72+
4273
rm -rf ruff/crates/ty_vendored/vendor/typeshed
4374
mkdir ruff/crates/ty_vendored/vendor/typeshed
4475
cp typeshed/README.md ruff/crates/ty_vendored/vendor/typeshed
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
name: ty ecosystem-report
2+
3+
permissions: {}
4+
5+
on:
6+
workflow_dispatch:
7+
schedule:
8+
# Run every Wednesday at 5:00 UTC:
9+
- cron: 0 5 * * 3
10+
11+
env:
12+
CARGO_INCREMENTAL: 0
13+
CARGO_NET_RETRY: 10
14+
CARGO_TERM_COLOR: always
15+
RUSTUP_MAX_RETRIES: 10
16+
RUST_BACKTRACE: 1
17+
CF_API_TOKEN_EXISTS: ${{ secrets.CF_API_TOKEN != '' }}
18+
19+
jobs:
20+
ty-ecosystem-report:
21+
name: Create ecosystem report
22+
runs-on: depot-ubuntu-22.04-32
23+
timeout-minutes: 20
24+
steps:
25+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
26+
with:
27+
path: ruff
28+
fetch-depth: 0
29+
persist-credentials: false
30+
31+
- name: Install the latest version of uv
32+
uses: astral-sh/setup-uv@bd01e18f51369d5a26f1651c3cb451d3417e3bba # v6.3.1
33+
34+
- uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2.8.0
35+
with:
36+
workspaces: "ruff"
37+
38+
- name: Install Rust toolchain
39+
run: rustup show
40+
41+
- name: Create report
42+
shell: bash
43+
run: |
44+
cd ruff
45+
46+
echo "Enabling configuration overloads (see .github/mypy-primer-ty.toml)"
47+
mkdir -p ~/.config/ty
48+
cp .github/mypy-primer-ty.toml ~/.config/ty/ty.toml
49+
50+
cd ..
51+
52+
uv tool install "git+https://github.com/astral-sh/ecosystem-analyzer@f0eec0e549684d8e1d7b8bc3e351202124b63bda"
53+
54+
ecosystem-analyzer \
55+
--verbose \
56+
--repository ruff \
57+
analyze \
58+
--projects ruff/crates/ty_python_semantic/resources/primer/good.txt \
59+
--output ecosystem-diagnostics.json
60+
61+
mkdir dist
62+
63+
ecosystem-analyzer \
64+
generate-report \
65+
--max-diagnostics-per-project=1200 \
66+
ecosystem-diagnostics.json \
67+
--output dist/index.html
68+
69+
- name: "Deploy to Cloudflare Pages"
70+
if: ${{ env.CF_API_TOKEN_EXISTS == 'true' }}
71+
id: deploy
72+
uses: cloudflare/wrangler-action@da0e0dfe58b7a431659754fdf3f186c529afbe65 # v3.14.1
73+
with:
74+
apiToken: ${{ secrets.CF_API_TOKEN }}
75+
accountId: ${{ secrets.CF_ACCOUNT_ID }}
76+
command: pages deploy dist --project-name=ty-ecosystem --branch main --commit-hash ${GITHUB_SHA}

.github/zizmor.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ rules:
1111
- build-docker.yml
1212
- publish-playground.yml
1313
- ty-ecosystem-analyzer.yaml
14+
- ty-ecosystem-report.yaml
1415
excessive-permissions:
1516
# it's hard to test what the impact of removing these ignores would be
1617
# without actually running the release workflow...

crates/ruff/src/printer.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use ruff_linter::fs::relativize_path;
1616
use ruff_linter::logging::LogLevel;
1717
use ruff_linter::message::{
1818
Emitter, EmitterContext, GithubEmitter, GitlabEmitter, GroupedEmitter, JunitEmitter,
19-
PylintEmitter, RdjsonEmitter, SarifEmitter, TextEmitter,
19+
SarifEmitter, TextEmitter,
2020
};
2121
use ruff_linter::notify_user;
2222
use ruff_linter::settings::flags::{self};
@@ -238,7 +238,11 @@ impl Printer {
238238
write!(writer, "{value}")?;
239239
}
240240
OutputFormat::Rdjson => {
241-
RdjsonEmitter.emit(writer, &diagnostics.inner, &context)?;
241+
let config = DisplayDiagnosticConfig::default()
242+
.format(DiagnosticFormat::Rdjson)
243+
.preview(preview);
244+
let value = DisplayDiagnostics::new(&context, &config, &diagnostics.inner);
245+
write!(writer, "{value}")?;
242246
}
243247
OutputFormat::JsonLines => {
244248
let config = DisplayDiagnosticConfig::default()
@@ -290,7 +294,11 @@ impl Printer {
290294
GitlabEmitter::default().emit(writer, &diagnostics.inner, &context)?;
291295
}
292296
OutputFormat::Pylint => {
293-
PylintEmitter.emit(writer, &diagnostics.inner, &context)?;
297+
let config = DisplayDiagnosticConfig::default()
298+
.format(DiagnosticFormat::Pylint)
299+
.preview(preview);
300+
let value = DisplayDiagnostics::new(&context, &config, &diagnostics.inner);
301+
write!(writer, "{value}")?;
294302
}
295303
OutputFormat::Azure => {
296304
let config = DisplayDiagnosticConfig::default()

crates/ruff/tests/snapshots/lint__output_format_pylint.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@ exit_code: 1
1818
----- stdout -----
1919
input.py:1: [F401] `os` imported but unused
2020
input.py:2: [F821] Undefined name `y`
21-
input.py:3: SyntaxError: Cannot use `match` statement on Python 3.9 (syntax was added in Python 3.10)
21+
input.py:3: [invalid-syntax] SyntaxError: Cannot use `match` statement on Python 3.9 (syntax was added in Python 3.10)
2222

2323
----- stderr -----

crates/ruff/tests/snapshots/lint__output_format_rdjson.snap

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,7 @@ exit_code: 1
7575
},
7676
{
7777
"code": {
78-
"url": null,
79-
"value": null
78+
"value": "invalid-syntax"
8079
},
8180
"location": {
8281
"path": "[TMP]/input.py",
@@ -94,7 +93,7 @@ exit_code: 1
9493
"message": "SyntaxError: Cannot use `match` statement on Python 3.9 (syntax was added in Python 3.10)"
9594
}
9695
],
97-
"severity": "warning",
96+
"severity": "WARNING",
9897
"source": {
9998
"name": "ruff",
10099
"url": "https://docs.astral.sh/ruff"

crates/ruff_db/src/diagnostic/mod.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::{fmt::Formatter, sync::Arc};
1+
use std::{fmt::Formatter, path::Path, sync::Arc};
22

33
use ruff_diagnostics::Fix;
44
use ruff_source_file::{LineColumn, SourceCode, SourceFile};
@@ -308,6 +308,10 @@ impl Diagnostic {
308308

309309
/// Set the fix for this diagnostic.
310310
pub fn set_fix(&mut self, fix: Fix) {
311+
debug_assert!(
312+
self.primary_span().is_some(),
313+
"Expected a source file for a diagnostic with a fix"
314+
);
311315
Arc::make_mut(&mut self.inner).fix = Some(fix);
312316
}
313317

@@ -1008,6 +1012,18 @@ impl UnifiedFile {
10081012
}
10091013
}
10101014

1015+
/// Return the file's path relative to the current working directory.
1016+
pub fn relative_path<'a>(&'a self, resolver: &'a dyn FileResolver) -> &'a Path {
1017+
let cwd = resolver.current_directory();
1018+
let path = Path::new(self.path(resolver));
1019+
1020+
if let Ok(path) = path.strip_prefix(cwd) {
1021+
return path;
1022+
}
1023+
1024+
path
1025+
}
1026+
10111027
fn diagnostic_source(&self, resolver: &dyn FileResolver) -> DiagnosticSource {
10121028
match self {
10131029
UnifiedFile::Ty(file) => DiagnosticSource::Ty(resolver.input(*file)),
@@ -1259,6 +1275,13 @@ pub enum DiagnosticFormat {
12591275
/// format for an array of all diagnostics. See <https://jsonlines.org/> for more details.
12601276
#[cfg(feature = "serde")]
12611277
JsonLines,
1278+
/// Print diagnostics in the JSON format expected by [reviewdog].
1279+
///
1280+
/// [reviewdog]: https://github.com/reviewdog/reviewdog
1281+
#[cfg(feature = "serde")]
1282+
Rdjson,
1283+
/// Print diagnostics in the format emitted by Pylint.
1284+
Pylint,
12621285
}
12631286

12641287
/// A representation of the kinds of messages inside a diagnostic.

crates/ruff_db/src/diagnostic/render.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::collections::BTreeMap;
2+
use std::path::Path;
23

34
use ruff_annotate_snippets::{
45
Annotation as AnnotateAnnotation, Level as AnnotateLevel, Message as AnnotateMessage,
@@ -22,12 +23,16 @@ use super::{
2223
};
2324

2425
use azure::AzureRenderer;
26+
use pylint::PylintRenderer;
2527

2628
mod azure;
2729
#[cfg(feature = "serde")]
2830
mod json;
2931
#[cfg(feature = "serde")]
3032
mod json_lines;
33+
mod pylint;
34+
#[cfg(feature = "serde")]
35+
mod rdjson;
3136

3237
/// A type that implements `std::fmt::Display` for diagnostic rendering.
3338
///
@@ -184,6 +189,13 @@ impl std::fmt::Display for DisplayDiagnostics<'_> {
184189
json_lines::JsonLinesRenderer::new(self.resolver, self.config)
185190
.render(f, self.diagnostics)?;
186191
}
192+
#[cfg(feature = "serde")]
193+
DiagnosticFormat::Rdjson => {
194+
rdjson::RdjsonRenderer::new(self.resolver).render(f, self.diagnostics)?;
195+
}
196+
DiagnosticFormat::Pylint => {
197+
PylintRenderer::new(self.resolver).render(f, self.diagnostics)?;
198+
}
187199
}
188200

189201
Ok(())
@@ -705,6 +717,9 @@ pub trait FileResolver {
705717

706718
/// Returns whether the file given is a Jupyter notebook.
707719
fn is_notebook(&self, file: &UnifiedFile) -> bool;
720+
721+
/// Returns the current working directory.
722+
fn current_directory(&self) -> &Path;
708723
}
709724

710725
impl<T> FileResolver for T
@@ -740,6 +755,10 @@ where
740755
UnifiedFile::Ruff(_) => unimplemented!("Expected an interned ty file"),
741756
}
742757
}
758+
759+
fn current_directory(&self) -> &Path {
760+
self.system().current_directory().as_std_path()
761+
}
743762
}
744763

745764
impl FileResolver for &dyn Db {
@@ -772,6 +791,10 @@ impl FileResolver for &dyn Db {
772791
UnifiedFile::Ruff(_) => unimplemented!("Expected an interned ty file"),
773792
}
774793
}
794+
795+
fn current_directory(&self) -> &Path {
796+
self.system().current_directory().as_std_path()
797+
}
775798
}
776799

777800
/// An abstraction over a unit of user input.

crates/ruff_db/src/diagnostic/render/json.rs

Lines changed: 4 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -262,9 +262,6 @@ struct JsonEdit<'a> {
262262

263263
#[cfg(test)]
264264
mod tests {
265-
use ruff_diagnostics::{Edit, Fix};
266-
use ruff_text_size::TextSize;
267-
268265
use crate::diagnostic::{
269266
DiagnosticFormat,
270267
render::tests::{
@@ -297,13 +294,7 @@ mod tests {
297294
env.format(DiagnosticFormat::Json);
298295
env.preview(false);
299296

300-
let diag = env
301-
.err()
302-
.fix(Fix::safe_edit(Edit::insertion(
303-
"edit".to_string(),
304-
TextSize::from(0),
305-
)))
306-
.build();
297+
let diag = env.err().build();
307298

308299
insta::assert_snapshot!(
309300
env.render(&diag),
@@ -317,23 +308,7 @@ mod tests {
317308
"row": 1
318309
},
319310
"filename": "",
320-
"fix": {
321-
"applicability": "safe",
322-
"edits": [
323-
{
324-
"content": "edit",
325-
"end_location": {
326-
"column": 1,
327-
"row": 1
328-
},
329-
"location": {
330-
"column": 1,
331-
"row": 1
332-
}
333-
}
334-
],
335-
"message": null
336-
},
311+
"fix": null,
337312
"location": {
338313
"column": 1,
339314
"row": 1
@@ -353,13 +328,7 @@ mod tests {
353328
env.format(DiagnosticFormat::Json);
354329
env.preview(true);
355330

356-
let diag = env
357-
.err()
358-
.fix(Fix::safe_edit(Edit::insertion(
359-
"edit".to_string(),
360-
TextSize::from(0),
361-
)))
362-
.build();
331+
let diag = env.err().build();
363332

364333
insta::assert_snapshot!(
365334
env.render(&diag),
@@ -370,17 +339,7 @@ mod tests {
370339
"code": null,
371340
"end_location": null,
372341
"filename": null,
373-
"fix": {
374-
"applicability": "safe",
375-
"edits": [
376-
{
377-
"content": "edit",
378-
"end_location": null,
379-
"location": null
380-
}
381-
],
382-
"message": null
383-
},
342+
"fix": null,
384343
"location": null,
385344
"message": "main diagnostic message",
386345
"noqa_row": null,

0 commit comments

Comments
 (0)