Compare commits
31 Commits
0.12.5
...
cjm/recrel
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
89228c344c | ||
|
|
ef3a195f28 | ||
|
|
008bbfdf5a | ||
|
|
df5eba7583 | ||
|
|
469c50b0b7 | ||
|
|
738246627f | ||
|
|
e867830848 | ||
|
|
72fdb7d439 | ||
|
|
fbf1dfc782 | ||
|
|
a0d8ff51dd | ||
|
|
165091a31c | ||
|
|
4a4dc38b5b | ||
|
|
3e366fdf13 | ||
|
|
53e9e4421c | ||
|
|
859262bd49 | ||
|
|
c0768dfd96 | ||
|
|
d4eb4277ad | ||
|
|
b033fb6bfd | ||
|
|
f722bfa9e6 | ||
|
|
b124e182ca | ||
|
|
57373a7e4d | ||
|
|
ae9d450b5f | ||
|
|
c8c80e054e | ||
|
|
4bc34b82ef | ||
|
|
d9cab4d242 | ||
|
|
d77b7312b0 | ||
|
|
f9091ea8bb | ||
|
|
1d2181623c | ||
|
|
dc6be457b5 | ||
|
|
1079975b35 | ||
|
|
39eb0f6c6c |
97
.github/workflows/typing_conformance_comment.yaml
vendored
Normal file
97
.github/workflows/typing_conformance_comment.yaml
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
name: PR comment (typing_conformance)
|
||||
|
||||
on: # zizmor: ignore[dangerous-triggers]
|
||||
workflow_run:
|
||||
workflows: [Run typing conformance]
|
||||
types: [completed]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
workflow_run_id:
|
||||
description: The typing_conformance workflow that triggers the workflow run
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
comment:
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: dawidd6/action-download-artifact@20319c5641d495c8a52e688b7dc5fada6c3a9fbc # v8
|
||||
name: Download PR number
|
||||
with:
|
||||
name: pr-number
|
||||
run_id: ${{ github.event.workflow_run.id || github.event.inputs.workflow_run_id }}
|
||||
if_no_artifact_found: ignore
|
||||
allow_forks: true
|
||||
|
||||
- name: Parse pull request number
|
||||
id: pr-number
|
||||
run: |
|
||||
if [[ -f pr-number ]]
|
||||
then
|
||||
echo "pr-number=$(<pr-number)" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
- uses: dawidd6/action-download-artifact@20319c5641d495c8a52e688b7dc5fada6c3a9fbc # v8
|
||||
name: "Download typing_conformance results"
|
||||
id: download-typing_conformance_diff
|
||||
if: steps.pr-number.outputs.pr-number
|
||||
with:
|
||||
name: typing_conformance_diagnostics_diff
|
||||
workflow: typing_conformance.yaml
|
||||
pr: ${{ steps.pr-number.outputs.pr-number }}
|
||||
path: pr/typing_conformance_diagnostics_diff
|
||||
workflow_conclusion: completed
|
||||
if_no_artifact_found: ignore
|
||||
allow_forks: true
|
||||
|
||||
- name: Generate comment content
|
||||
id: generate-comment
|
||||
if: ${{ steps.download-typing_conformance_diff.outputs.found_artifact == 'true' }}
|
||||
run: |
|
||||
# Guard against malicious typing_conformance results that symlink to a secret
|
||||
# file on this runner
|
||||
if [[ -L pr/typing_conformance_diagnostics_diff/typing_conformance_diagnostics.diff ]]
|
||||
then
|
||||
echo "Error: typing_conformance_diagnostics.diff cannot be a symlink"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Note this identifier is used to find the comment to update on
|
||||
# subsequent runs
|
||||
echo '<!-- generated-comment typing_conformance_diagnostics_diff -->' >> comment.txt
|
||||
|
||||
echo '## Diagnostic diff on typing conformance tests' >> comment.txt
|
||||
if [ -s "pr/typing_conformance_diagnostics_diff/typing_conformance_diagnostics.diff" ]; then
|
||||
echo '<details>' >> comment.txt
|
||||
echo '<summary>Changes were detected when running ty on typing conformance tests</summary>' >> comment.txt
|
||||
echo '' >> comment.txt
|
||||
echo '```diff' >> comment.txt
|
||||
cat pr/typing_conformance_diagnostics_diff/typing_conformance_diagnostics.diff >> comment.txt
|
||||
echo '```' >> comment.txt
|
||||
echo '</details>' >> comment.txt
|
||||
else
|
||||
echo 'No changes detected when running ty on typing conformance tests ✅' >> comment.txt
|
||||
fi
|
||||
|
||||
echo 'comment<<EOF' >> "$GITHUB_OUTPUT"
|
||||
cat comment.txt >> "$GITHUB_OUTPUT"
|
||||
echo 'EOF' >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Find existing comment
|
||||
uses: peter-evans/find-comment@3eae4d37986fb5a8592848f6a574fdf654e61f9e # v3.1.0
|
||||
if: steps.generate-comment.outcome == 'success'
|
||||
id: find-comment
|
||||
with:
|
||||
issue-number: ${{ steps.pr-number.outputs.pr-number }}
|
||||
comment-author: "github-actions[bot]"
|
||||
body-includes: "<!-- generated-comment typing_conformance_diagnostics_diff -->"
|
||||
|
||||
- name: Create or update comment
|
||||
if: steps.find-comment.outcome == 'success'
|
||||
uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4
|
||||
with:
|
||||
comment-id: ${{ steps.find-comment.outputs.comment-id }}
|
||||
issue-number: ${{ steps.pr-number.outputs.pr-number }}
|
||||
body-path: comment.txt
|
||||
edit-mode: replace
|
||||
@@ -84,7 +84,7 @@ repos:
|
||||
rev: v0.12.4
|
||||
hooks:
|
||||
- id: ruff-format
|
||||
- id: ruff
|
||||
- id: ruff-check
|
||||
args: [--fix, --exit-non-zero-on-fix]
|
||||
types_or: [python, pyi]
|
||||
require_serial: true
|
||||
|
||||
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -2960,6 +2960,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
"memchr",
|
||||
"ruff_cache",
|
||||
"ruff_db",
|
||||
"ruff_linter",
|
||||
@@ -4304,7 +4305,6 @@ dependencies = [
|
||||
"strum_macros",
|
||||
"tempfile",
|
||||
"test-case",
|
||||
"thin-vec",
|
||||
"thiserror 2.0.12",
|
||||
"tracing",
|
||||
"ty_python_semantic",
|
||||
|
||||
@@ -166,7 +166,6 @@ strum_macros = { version = "0.27.0" }
|
||||
syn = { version = "2.0.55" }
|
||||
tempfile = { version = "3.9.0" }
|
||||
test-case = { version = "3.3.1" }
|
||||
thin-vec = { version = "0.2.14" }
|
||||
thiserror = { version = "2.0.0" }
|
||||
tikv-jemallocator = { version = "0.6.0" }
|
||||
toml = { version = "0.9.0" }
|
||||
|
||||
@@ -169,6 +169,9 @@ pub struct AnalyzeGraphCommand {
|
||||
/// Attempt to detect imports from string literals.
|
||||
#[clap(long)]
|
||||
detect_string_imports: bool,
|
||||
/// The minimum number of dots in a string import to consider it a valid import.
|
||||
#[clap(long)]
|
||||
min_dots: Option<usize>,
|
||||
/// Enable preview mode. Use `--no-preview` to disable.
|
||||
#[arg(long, overrides_with("no_preview"))]
|
||||
preview: bool,
|
||||
@@ -808,6 +811,7 @@ impl AnalyzeGraphCommand {
|
||||
} else {
|
||||
None
|
||||
},
|
||||
string_imports_min_dots: self.min_dots,
|
||||
preview: resolve_bool_arg(self.preview, self.no_preview).map(PreviewMode::from),
|
||||
target_version: self.target_version.map(ast::PythonVersion::from),
|
||||
..ExplicitConfigOverrides::default()
|
||||
@@ -1305,6 +1309,7 @@ struct ExplicitConfigOverrides {
|
||||
show_fixes: Option<bool>,
|
||||
extension: Option<Vec<ExtensionPair>>,
|
||||
detect_string_imports: Option<bool>,
|
||||
string_imports_min_dots: Option<usize>,
|
||||
}
|
||||
|
||||
impl ConfigurationTransformer for ExplicitConfigOverrides {
|
||||
@@ -1392,6 +1397,9 @@ impl ConfigurationTransformer for ExplicitConfigOverrides {
|
||||
if let Some(detect_string_imports) = &self.detect_string_imports {
|
||||
config.analyze.detect_string_imports = Some(*detect_string_imports);
|
||||
}
|
||||
if let Some(string_imports_min_dots) = &self.string_imports_min_dots {
|
||||
config.analyze.string_imports_min_dots = Some(*string_imports_min_dots);
|
||||
}
|
||||
|
||||
config
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ pub(crate) fn analyze_graph(
|
||||
|
||||
// Resolve the per-file settings.
|
||||
let settings = resolver.resolve(path);
|
||||
let string_imports = settings.analyze.detect_string_imports;
|
||||
let string_imports = settings.analyze.string_imports;
|
||||
let include_dependencies = settings.analyze.include_dependencies.get(path).cloned();
|
||||
|
||||
// Skip excluded files.
|
||||
|
||||
@@ -279,6 +279,7 @@ mod test {
|
||||
|
||||
TextEmitter::default()
|
||||
.with_show_fix_status(true)
|
||||
.with_color(false)
|
||||
.emit(
|
||||
&mut output,
|
||||
&diagnostics.inner,
|
||||
|
||||
@@ -197,23 +197,43 @@ fn string_detection() -> Result<()> {
|
||||
insta::with_settings!({
|
||||
filters => INSTA_FILTERS.to_vec(),
|
||||
}, {
|
||||
assert_cmd_snapshot!(command().arg("--detect-string-imports").current_dir(&root), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
{
|
||||
"ruff/__init__.py": [],
|
||||
"ruff/a.py": [
|
||||
"ruff/b.py"
|
||||
],
|
||||
"ruff/b.py": [
|
||||
"ruff/c.py"
|
||||
],
|
||||
"ruff/c.py": []
|
||||
}
|
||||
assert_cmd_snapshot!(command().arg("--detect-string-imports").current_dir(&root), @r#"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
{
|
||||
"ruff/__init__.py": [],
|
||||
"ruff/a.py": [
|
||||
"ruff/b.py"
|
||||
],
|
||||
"ruff/b.py": [],
|
||||
"ruff/c.py": []
|
||||
}
|
||||
|
||||
----- stderr -----
|
||||
"###);
|
||||
----- stderr -----
|
||||
"#);
|
||||
});
|
||||
|
||||
insta::with_settings!({
|
||||
filters => INSTA_FILTERS.to_vec(),
|
||||
}, {
|
||||
assert_cmd_snapshot!(command().arg("--detect-string-imports").arg("--min-dots").arg("1").current_dir(&root), @r#"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
{
|
||||
"ruff/__init__.py": [],
|
||||
"ruff/a.py": [
|
||||
"ruff/b.py"
|
||||
],
|
||||
"ruff/b.py": [
|
||||
"ruff/c.py"
|
||||
],
|
||||
"ruff/c.py": []
|
||||
}
|
||||
|
||||
----- stderr -----
|
||||
"#);
|
||||
});
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -2422,7 +2422,7 @@ requires-python = ">= 3.11"
|
||||
analyze.exclude = []
|
||||
analyze.preview = disabled
|
||||
analyze.target_version = 3.11
|
||||
analyze.detect_string_imports = false
|
||||
analyze.string_imports = disabled
|
||||
analyze.extension = ExtensionMapping({})
|
||||
analyze.include_dependencies = {}
|
||||
|
||||
@@ -2734,7 +2734,7 @@ requires-python = ">= 3.11"
|
||||
analyze.exclude = []
|
||||
analyze.preview = disabled
|
||||
analyze.target_version = 3.10
|
||||
analyze.detect_string_imports = false
|
||||
analyze.string_imports = disabled
|
||||
analyze.extension = ExtensionMapping({})
|
||||
analyze.include_dependencies = {}
|
||||
|
||||
@@ -3098,7 +3098,7 @@ from typing import Union;foo: Union[int, str] = 1
|
||||
analyze.exclude = []
|
||||
analyze.preview = disabled
|
||||
analyze.target_version = 3.11
|
||||
analyze.detect_string_imports = false
|
||||
analyze.string_imports = disabled
|
||||
analyze.extension = ExtensionMapping({})
|
||||
analyze.include_dependencies = {}
|
||||
|
||||
@@ -3478,7 +3478,7 @@ from typing import Union;foo: Union[int, str] = 1
|
||||
analyze.exclude = []
|
||||
analyze.preview = disabled
|
||||
analyze.target_version = 3.11
|
||||
analyze.detect_string_imports = false
|
||||
analyze.string_imports = disabled
|
||||
analyze.extension = ExtensionMapping({})
|
||||
analyze.include_dependencies = {}
|
||||
|
||||
@@ -3806,7 +3806,7 @@ from typing import Union;foo: Union[int, str] = 1
|
||||
analyze.exclude = []
|
||||
analyze.preview = disabled
|
||||
analyze.target_version = 3.10
|
||||
analyze.detect_string_imports = false
|
||||
analyze.string_imports = disabled
|
||||
analyze.extension = ExtensionMapping({})
|
||||
analyze.include_dependencies = {}
|
||||
|
||||
@@ -4134,7 +4134,7 @@ from typing import Union;foo: Union[int, str] = 1
|
||||
analyze.exclude = []
|
||||
analyze.preview = disabled
|
||||
analyze.target_version = 3.9
|
||||
analyze.detect_string_imports = false
|
||||
analyze.string_imports = disabled
|
||||
analyze.extension = ExtensionMapping({})
|
||||
analyze.include_dependencies = {}
|
||||
|
||||
@@ -4419,7 +4419,7 @@ from typing import Union;foo: Union[int, str] = 1
|
||||
analyze.exclude = []
|
||||
analyze.preview = disabled
|
||||
analyze.target_version = 3.9
|
||||
analyze.detect_string_imports = false
|
||||
analyze.string_imports = disabled
|
||||
analyze.extension = ExtensionMapping({})
|
||||
analyze.include_dependencies = {}
|
||||
|
||||
@@ -4757,7 +4757,7 @@ from typing import Union;foo: Union[int, str] = 1
|
||||
analyze.exclude = []
|
||||
analyze.preview = disabled
|
||||
analyze.target_version = 3.10
|
||||
analyze.detect_string_imports = false
|
||||
analyze.string_imports = disabled
|
||||
analyze.extension = ExtensionMapping({})
|
||||
analyze.include_dependencies = {}
|
||||
|
||||
|
||||
@@ -392,7 +392,7 @@ formatter.docstring_code_line_width = dynamic
|
||||
analyze.exclude = []
|
||||
analyze.preview = disabled
|
||||
analyze.target_version = 3.7
|
||||
analyze.detect_string_imports = false
|
||||
analyze.string_imports = disabled
|
||||
analyze.extension = ExtensionMapping({})
|
||||
analyze.include_dependencies = {}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ ty_python_semantic = { workspace = true }
|
||||
|
||||
anyhow = { workspace = true }
|
||||
clap = { workspace = true, optional = true }
|
||||
memchr = { workspace = true }
|
||||
salsa = { workspace = true }
|
||||
schemars = { workspace = true, optional = true }
|
||||
serde = { workspace = true, optional = true }
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::StringImports;
|
||||
use ruff_python_ast::visitor::source_order::{
|
||||
SourceOrderVisitor, walk_expr, walk_module, walk_stmt,
|
||||
};
|
||||
@@ -10,13 +11,13 @@ pub(crate) struct Collector<'a> {
|
||||
/// The path to the current module.
|
||||
module_path: Option<&'a [String]>,
|
||||
/// Whether to detect imports from string literals.
|
||||
string_imports: bool,
|
||||
string_imports: StringImports,
|
||||
/// The collected imports from the Python AST.
|
||||
imports: Vec<CollectedImport>,
|
||||
}
|
||||
|
||||
impl<'a> Collector<'a> {
|
||||
pub(crate) fn new(module_path: Option<&'a [String]>, string_imports: bool) -> Self {
|
||||
pub(crate) fn new(module_path: Option<&'a [String]>, string_imports: StringImports) -> Self {
|
||||
Self {
|
||||
module_path,
|
||||
string_imports,
|
||||
@@ -118,7 +119,7 @@ impl<'ast> SourceOrderVisitor<'ast> for Collector<'_> {
|
||||
| Stmt::Continue(_)
|
||||
| Stmt::IpyEscapeCommand(_) => {
|
||||
// Only traverse simple statements when string imports is enabled.
|
||||
if self.string_imports {
|
||||
if self.string_imports.enabled {
|
||||
walk_stmt(self, stmt);
|
||||
}
|
||||
}
|
||||
@@ -126,20 +127,26 @@ impl<'ast> SourceOrderVisitor<'ast> for Collector<'_> {
|
||||
}
|
||||
|
||||
fn visit_expr(&mut self, expr: &'ast Expr) {
|
||||
if self.string_imports {
|
||||
if self.string_imports.enabled {
|
||||
if let Expr::StringLiteral(ast::ExprStringLiteral {
|
||||
value,
|
||||
range: _,
|
||||
node_index: _,
|
||||
}) = expr
|
||||
{
|
||||
// Determine whether the string literal "looks like" an import statement: contains
|
||||
// a dot, and consists solely of valid Python identifiers.
|
||||
let value = value.to_str();
|
||||
if let Some(module_name) = ModuleName::new(value) {
|
||||
self.imports.push(CollectedImport::Import(module_name));
|
||||
// Determine whether the string literal "looks like" an import statement: contains
|
||||
// the requisite number of dots, and consists solely of valid Python identifiers.
|
||||
if self.string_imports.min_dots == 0
|
||||
|| memchr::memchr_iter(b'.', value.as_bytes()).count()
|
||||
>= self.string_imports.min_dots
|
||||
{
|
||||
if let Some(module_name) = ModuleName::new(value) {
|
||||
self.imports.push(CollectedImport::Import(module_name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
walk_expr(self, expr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ use ruff_python_parser::{Mode, ParseOptions, parse};
|
||||
use crate::collector::Collector;
|
||||
pub use crate::db::ModuleDb;
|
||||
use crate::resolver::Resolver;
|
||||
pub use crate::settings::{AnalyzeSettings, Direction};
|
||||
pub use crate::settings::{AnalyzeSettings, Direction, StringImports};
|
||||
|
||||
mod collector;
|
||||
mod db;
|
||||
@@ -26,7 +26,7 @@ impl ModuleImports {
|
||||
db: &ModuleDb,
|
||||
path: &SystemPath,
|
||||
package: Option<&SystemPath>,
|
||||
string_imports: bool,
|
||||
string_imports: StringImports,
|
||||
) -> Result<Self> {
|
||||
// Read and parse the source code.
|
||||
let source = std::fs::read_to_string(path)?;
|
||||
|
||||
@@ -11,7 +11,7 @@ pub struct AnalyzeSettings {
|
||||
pub exclude: FilePatternSet,
|
||||
pub preview: PreviewMode,
|
||||
pub target_version: PythonVersion,
|
||||
pub detect_string_imports: bool,
|
||||
pub string_imports: StringImports,
|
||||
pub include_dependencies: BTreeMap<PathBuf, (PathBuf, Vec<String>)>,
|
||||
pub extension: ExtensionMapping,
|
||||
}
|
||||
@@ -26,7 +26,7 @@ impl fmt::Display for AnalyzeSettings {
|
||||
self.exclude,
|
||||
self.preview,
|
||||
self.target_version,
|
||||
self.detect_string_imports,
|
||||
self.string_imports,
|
||||
self.extension | debug,
|
||||
self.include_dependencies | debug,
|
||||
]
|
||||
@@ -35,6 +35,31 @@ impl fmt::Display for AnalyzeSettings {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, CacheKey)]
|
||||
pub struct StringImports {
|
||||
pub enabled: bool,
|
||||
pub min_dots: usize,
|
||||
}
|
||||
|
||||
impl Default for StringImports {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
enabled: false,
|
||||
min_dots: 2,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for StringImports {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
if self.enabled {
|
||||
write!(f, "enabled (min_dots: {})", self.min_dots)
|
||||
} else {
|
||||
write!(f, "disabled")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, CacheKey)]
|
||||
#[cfg_attr(
|
||||
feature = "serde",
|
||||
|
||||
@@ -25,5 +25,5 @@ def my_func():
|
||||
|
||||
# t-strings - all ok
|
||||
t"0.0.0.0"
|
||||
"0.0.0.0" t"0.0.0.0{expr}0.0.0.0"
|
||||
"0.0.0.0" f"0.0.0.0{expr}0.0.0.0" t"0.0.0.0{expr}0.0.0.0"
|
||||
t"0.0.0.0" t"0.0.0.0{expr}0.0.0.0"
|
||||
t"0.0.0.0" t"0.0.0.0{expr}0.0.0.0" t"0.0.0.0{expr}0.0.0.0"
|
||||
|
||||
@@ -94,7 +94,7 @@ except Exception:
|
||||
logging.error("...", exc_info=True)
|
||||
|
||||
|
||||
from logging import error, exception
|
||||
from logging import critical, error, exception
|
||||
|
||||
try:
|
||||
pass
|
||||
@@ -114,6 +114,23 @@ except Exception:
|
||||
error("...", exc_info=None)
|
||||
|
||||
|
||||
try:
|
||||
pass
|
||||
except Exception:
|
||||
critical("...")
|
||||
|
||||
|
||||
try:
|
||||
pass
|
||||
except Exception:
|
||||
critical("...", exc_info=False)
|
||||
|
||||
|
||||
try:
|
||||
pass
|
||||
except Exception:
|
||||
critical("...", exc_info=None)
|
||||
|
||||
try:
|
||||
pass
|
||||
except Exception:
|
||||
@@ -125,6 +142,13 @@ try:
|
||||
except Exception:
|
||||
error("...", exc_info=True)
|
||||
|
||||
|
||||
try:
|
||||
pass
|
||||
except Exception:
|
||||
critical("...", exc_info=True)
|
||||
|
||||
|
||||
try:
|
||||
...
|
||||
except Exception as e:
|
||||
|
||||
@@ -143,3 +143,23 @@ class NotAMethodButHardToDetect:
|
||||
# without risking false positives elsewhere or introducing complex heuristics
|
||||
# that users would find surprising and confusing
|
||||
FOO = sorted([x for x in BAR], key=lambda x: x.baz)
|
||||
|
||||
# https://github.com/astral-sh/ruff/issues/19305
|
||||
import pytest
|
||||
|
||||
@pytest.fixture
|
||||
def my_fixture_with_param(request):
|
||||
return request.param
|
||||
|
||||
@pytest.fixture()
|
||||
def my_fixture_with_param2(request):
|
||||
return request.param
|
||||
|
||||
|
||||
# Decorated function (should be ignored)
|
||||
def custom_decorator(func):
|
||||
return func
|
||||
|
||||
@custom_decorator
|
||||
def add(x, y):
|
||||
return x + y
|
||||
|
||||
@@ -65,3 +65,62 @@ class Foo:
|
||||
bar = "should've used attrs"
|
||||
|
||||
def __post_init__(self, bar: str = "ahhh", baz: str = "hmm") -> None: ...
|
||||
|
||||
|
||||
# https://github.com/astral-sh/ruff/issues/18950
|
||||
@dataclass
|
||||
class Foo:
|
||||
def __post_init__(self, bar: int = (x := 1)) -> None:
|
||||
pass
|
||||
|
||||
|
||||
@dataclass
|
||||
class Foo:
|
||||
def __post_init__(
|
||||
self,
|
||||
bar: int = (x := 1) # comment
|
||||
,
|
||||
baz: int = (y := 2), # comment
|
||||
foo = (a := 1) # comment
|
||||
,
|
||||
faz = (b := 2), # comment
|
||||
) -> None:
|
||||
pass
|
||||
|
||||
|
||||
@dataclass
|
||||
class Foo:
|
||||
def __post_init__(
|
||||
self,
|
||||
bar: int = 1, # comment
|
||||
baz: int = 2, # comment
|
||||
) -> None:
|
||||
pass
|
||||
|
||||
|
||||
@dataclass
|
||||
class Foo:
|
||||
def __post_init__(
|
||||
self,
|
||||
arg1: int = (1) # comment
|
||||
,
|
||||
arg2: int = ((1)) # comment
|
||||
,
|
||||
arg2: int = (i for i in range(10)) # comment
|
||||
,
|
||||
) -> None:
|
||||
pass
|
||||
|
||||
|
||||
# makes little sense, but is valid syntax
|
||||
def fun_with_python_syntax():
|
||||
@dataclass
|
||||
class Foo:
|
||||
def __post_init__(
|
||||
self,
|
||||
bar: (int) = (yield from range(5)) # comment
|
||||
,
|
||||
) -> None:
|
||||
...
|
||||
|
||||
return Foo
|
||||
|
||||
@@ -53,3 +53,16 @@ regex.subn(br"""eak your machine with rm -""", rf"""/""")
|
||||
regex.splititer(both, non_literal)
|
||||
regex.subf(f, lambda _: r'means', '"format"')
|
||||
regex.subfn(fn, f'''a$1n't''', lambda: "'function'")
|
||||
|
||||
|
||||
# https://github.com/astral-sh/ruff/issues/16713
|
||||
re.compile("\a\f\n\r\t\u27F2\U0001F0A1\v\x41") # with unsafe fix
|
||||
re.compile("\b") # without fix
|
||||
re.compile("\"") # without fix
|
||||
re.compile("\'") # without fix
|
||||
re.compile('\"') # without fix
|
||||
re.compile('\'') # without fix
|
||||
re.compile("\\") # without fix
|
||||
re.compile("\101") # without fix
|
||||
re.compile("a\
|
||||
b") # without fix
|
||||
|
||||
@@ -91,3 +91,20 @@ regex.subf(
|
||||
br''br""br''
|
||||
)
|
||||
regex.subfn(br'I\s\nee*d\s[O0o]me\x20\Qoffe\E, ' br'b')
|
||||
|
||||
|
||||
# https://github.com/astral-sh/ruff/issues/16713
|
||||
re.compile(
|
||||
"["
|
||||
"\U0001F600-\U0001F64F" # emoticons
|
||||
"\U0001F300-\U0001F5FF" # symbols & pictographs
|
||||
"\U0001F680-\U0001F6FF" # transport & map symbols
|
||||
"\U0001F1E0-\U0001F1FF" # flags (iOS)
|
||||
"\U00002702-\U000027B0"
|
||||
"\U000024C2-\U0001F251"
|
||||
"\u200d" # zero width joiner
|
||||
"\u200c" # zero width non-joiner
|
||||
"\\u200c" # must not be escaped in a raw string
|
||||
"]+",
|
||||
flags=re.UNICODE,
|
||||
)
|
||||
|
||||
3
crates/ruff_linter/resources/test/fixtures/ruff/RUF039_py_version_sensitive.py
vendored
Normal file
3
crates/ruff_linter/resources/test/fixtures/ruff/RUF039_py_version_sensitive.py
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
import re
|
||||
|
||||
re.compile("\N{Partial Differential}") # with unsafe fix if python target is 3.8 or higher, else without fix
|
||||
@@ -473,7 +473,7 @@ pub fn lint_only(
|
||||
&& !is_py314_support_enabled(settings)
|
||||
{
|
||||
warn_user_once!(
|
||||
"Support for Python 3.14 is under development and may be unstable. Enable `preview` to remove this warning."
|
||||
"Support for Python 3.14 is in preview and may undergo breaking changes. Enable `preview` to remove this warning."
|
||||
);
|
||||
}
|
||||
|
||||
@@ -584,7 +584,7 @@ pub fn lint_fix<'a>(
|
||||
&& !is_py314_support_enabled(settings)
|
||||
{
|
||||
warn_user_once!(
|
||||
"Support for Python 3.14 is under development and may be unstable. Enable `preview` to remove this warning."
|
||||
"Support for Python 3.14 is in preview and may undergo breaking changes. Enable `preview` to remove this warning."
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -76,6 +76,12 @@ impl TextEmitter {
|
||||
self.config = self.config.preview(preview);
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_color(mut self, color: bool) -> Self {
|
||||
self.config = self.config.color(color);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Emitter for TextEmitter {
|
||||
|
||||
@@ -47,9 +47,10 @@ use crate::checkers::ast::Checker;
|
||||
/// raise
|
||||
/// ```
|
||||
///
|
||||
/// Exceptions that are logged via `logging.exception()` or `logging.error()`
|
||||
/// with `exc_info` enabled will _not_ be flagged, as this is a common pattern
|
||||
/// for propagating exception traces:
|
||||
/// Exceptions that are logged via `logging.exception()` or are logged via
|
||||
/// `logging.error()` or `logging.critical()` with `exc_info` enabled will
|
||||
/// _not_ be flagged, as this is a common pattern for propagating exception
|
||||
/// traces:
|
||||
/// ```python
|
||||
/// try:
|
||||
/// foo()
|
||||
@@ -201,7 +202,7 @@ impl<'a> StatementVisitor<'a> for LogExceptionVisitor<'a> {
|
||||
) {
|
||||
if match attr.as_str() {
|
||||
"exception" => true,
|
||||
"error" => arguments
|
||||
"error" | "critical" => arguments
|
||||
.find_keyword("exc_info")
|
||||
.is_some_and(|keyword| is_const_true(&keyword.value)),
|
||||
_ => false,
|
||||
@@ -214,7 +215,7 @@ impl<'a> StatementVisitor<'a> for LogExceptionVisitor<'a> {
|
||||
if self.semantic.resolve_qualified_name(func).is_some_and(
|
||||
|qualified_name| match qualified_name.segments() {
|
||||
["logging", "exception"] => true,
|
||||
["logging", "error"] => arguments
|
||||
["logging", "error" | "critical"] => arguments
|
||||
.find_keyword("exc_info")
|
||||
.is_some_and(|keyword| is_const_true(&keyword.value)),
|
||||
_ => false,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_blind_except/mod.rs
|
||||
snapshot_kind: text
|
||||
---
|
||||
BLE.py:25:8: BLE001 Do not catch blind exception: `BaseException`
|
||||
|
|
||||
@@ -121,3 +120,30 @@ BLE.py:113:8: BLE001 Do not catch blind exception: `Exception`
|
||||
| ^^^^^^^^^ BLE001
|
||||
114 | error("...", exc_info=None)
|
||||
|
|
||||
|
||||
BLE.py:119:8: BLE001 Do not catch blind exception: `Exception`
|
||||
|
|
||||
117 | try:
|
||||
118 | pass
|
||||
119 | except Exception:
|
||||
| ^^^^^^^^^ BLE001
|
||||
120 | critical("...")
|
||||
|
|
||||
|
||||
BLE.py:125:8: BLE001 Do not catch blind exception: `Exception`
|
||||
|
|
||||
123 | try:
|
||||
124 | pass
|
||||
125 | except Exception:
|
||||
| ^^^^^^^^^ BLE001
|
||||
126 | critical("...", exc_info=False)
|
||||
|
|
||||
|
||||
BLE.py:131:8: BLE001 Do not catch blind exception: `Exception`
|
||||
|
|
||||
129 | try:
|
||||
130 | pass
|
||||
131 | except Exception:
|
||||
| ^^^^^^^^^ BLE001
|
||||
132 | critical("...", exc_info=None)
|
||||
|
|
||||
|
||||
@@ -104,6 +104,13 @@ pub(crate) fn reimplemented_operator(checker: &Checker, target: &FunctionLike) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip decorated functions
|
||||
if let FunctionLike::Function(func) = target {
|
||||
if !func.decorator_list.is_empty() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let Some(params) = target.parameters() else {
|
||||
return;
|
||||
};
|
||||
|
||||
@@ -555,6 +555,44 @@ mod tests {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test_case(Rule::UnrawRePattern, Path::new("RUF039_py_version_sensitive.py"))]
|
||||
fn preview_rules_py37(rule_code: Rule, path: &Path) -> Result<()> {
|
||||
let snapshot = format!(
|
||||
"preview__py37__{}_{}",
|
||||
rule_code.noqa_code(),
|
||||
path.to_string_lossy()
|
||||
);
|
||||
let diagnostics = test_path(
|
||||
Path::new("ruff").join(path).as_path(),
|
||||
&settings::LinterSettings {
|
||||
preview: PreviewMode::Enabled,
|
||||
unresolved_target_version: PythonVersion::PY37.into(),
|
||||
..settings::LinterSettings::for_rule(rule_code)
|
||||
},
|
||||
)?;
|
||||
assert_diagnostics!(snapshot, diagnostics);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test_case(Rule::UnrawRePattern, Path::new("RUF039_py_version_sensitive.py"))]
|
||||
fn preview_rules_py38(rule_code: Rule, path: &Path) -> Result<()> {
|
||||
let snapshot = format!(
|
||||
"preview__py38__{}_{}",
|
||||
rule_code.noqa_code(),
|
||||
path.to_string_lossy()
|
||||
);
|
||||
let diagnostics = test_path(
|
||||
Path::new("ruff").join(path).as_path(),
|
||||
&settings::LinterSettings {
|
||||
preview: PreviewMode::Enabled,
|
||||
unresolved_target_version: PythonVersion::PY38.into(),
|
||||
..settings::LinterSettings::for_rule(rule_code)
|
||||
},
|
||||
)?;
|
||||
assert_diagnostics!(snapshot, diagnostics);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test_case(Rule::UsedDummyVariable, Path::new("RUF052.py"), r"^_+", 1)]
|
||||
#[test_case(Rule::UsedDummyVariable, Path::new("RUF052.py"), r"", 2)]
|
||||
fn custom_regexp_preset(
|
||||
|
||||
@@ -2,6 +2,7 @@ use anyhow::Context;
|
||||
|
||||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
use ruff_python_ast as ast;
|
||||
use ruff_python_ast::parenthesize::parenthesized_range;
|
||||
use ruff_python_semantic::{Scope, ScopeKind};
|
||||
use ruff_python_trivia::{indentation_at_offset, textwrap};
|
||||
use ruff_source_file::LineRanges;
|
||||
@@ -117,13 +118,7 @@ pub(crate) fn post_init_default(checker: &Checker, function_def: &ast::StmtFunct
|
||||
|
||||
if !stopped_fixes {
|
||||
diagnostic.try_set_fix(|| {
|
||||
use_initvar(
|
||||
current_scope,
|
||||
function_def,
|
||||
¶meter.parameter,
|
||||
default,
|
||||
checker,
|
||||
)
|
||||
use_initvar(current_scope, function_def, parameter, default, checker)
|
||||
});
|
||||
// Need to stop fixes as soon as there is a parameter we cannot fix.
|
||||
// Otherwise, we risk a syntax error (a parameter without a default
|
||||
@@ -138,10 +133,11 @@ pub(crate) fn post_init_default(checker: &Checker, function_def: &ast::StmtFunct
|
||||
fn use_initvar(
|
||||
current_scope: &Scope,
|
||||
post_init_def: &ast::StmtFunctionDef,
|
||||
parameter: &ast::Parameter,
|
||||
parameter_with_default: &ast::ParameterWithDefault,
|
||||
default: &ast::Expr,
|
||||
checker: &Checker,
|
||||
) -> anyhow::Result<Fix> {
|
||||
let parameter = ¶meter_with_default.parameter;
|
||||
if current_scope.has(¶meter.name) {
|
||||
return Err(anyhow::anyhow!(
|
||||
"Cannot add a `{}: InitVar` field to the class body, as a field by that name already exists",
|
||||
@@ -157,17 +153,25 @@ fn use_initvar(
|
||||
checker.semantic(),
|
||||
)?;
|
||||
|
||||
let locator = checker.locator();
|
||||
|
||||
let default_loc = parenthesized_range(
|
||||
default.into(),
|
||||
parameter_with_default.into(),
|
||||
checker.comment_ranges(),
|
||||
checker.source(),
|
||||
)
|
||||
.unwrap_or(default.range());
|
||||
|
||||
// Delete the default value. For example,
|
||||
// - def __post_init__(self, foo: int = 0) -> None: ...
|
||||
// + def __post_init__(self, foo: int) -> None: ...
|
||||
let default_edit = Edit::deletion(parameter.end(), default.end());
|
||||
let default_edit = Edit::deletion(parameter.end(), default_loc.end());
|
||||
|
||||
// Add `dataclasses.InitVar` field to class body.
|
||||
let locator = checker.locator();
|
||||
|
||||
let content = {
|
||||
let default = locator.slice(default_loc);
|
||||
let parameter_name = locator.slice(¶meter.name);
|
||||
let default = locator.slice(default);
|
||||
let line_ending = checker.stylist().line_ending().as_str();
|
||||
|
||||
if let Some(annotation) = ¶meter
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::str::FromStr;
|
||||
|
||||
use ruff_diagnostics::Applicability;
|
||||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
use ruff_python_ast::{
|
||||
BytesLiteral, Expr, ExprBytesLiteral, ExprCall, ExprStringLiteral, StringLiteral,
|
||||
BytesLiteral, Expr, ExprBytesLiteral, ExprCall, ExprStringLiteral, PythonVersion, StringLiteral,
|
||||
};
|
||||
use ruff_python_semantic::{Modules, SemanticModel};
|
||||
|
||||
use ruff_text_size::Ranged;
|
||||
use ruff_text_size::{Ranged, TextRange};
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::{Edit, Fix, FixAvailability, Violation};
|
||||
@@ -24,6 +24,29 @@ use crate::{Edit, Fix, FixAvailability, Violation};
|
||||
/// Regular expressions should be written
|
||||
/// using raw strings to avoid double escaping.
|
||||
///
|
||||
/// ## Fix safety
|
||||
/// The fix is unsafe if the string/bytes literal contains an escape sequence because the fix alters
|
||||
/// the runtime value of the literal while retaining the regex semantics.
|
||||
///
|
||||
/// For example
|
||||
/// ```python
|
||||
/// # Literal is `1\n2`.
|
||||
/// re.compile("1\n2")
|
||||
///
|
||||
/// # Literal is `1\\n2`, but the regex library will interpret `\\n` and will still match a newline
|
||||
/// # character as before.
|
||||
/// re.compile(r"1\n2")
|
||||
/// ```
|
||||
///
|
||||
/// ## Fix availability
|
||||
/// A fix is not available if either
|
||||
/// * the argument is a string with a (no-op) `u` prefix (e.g., `u"foo"`) as the prefix is
|
||||
/// incompatible with the raw prefix `r`
|
||||
/// * the argument is a string or bytes literal with an escape sequence that has a different
|
||||
/// meaning in the context of a regular expression such as `\b`, which is word boundary or
|
||||
/// backspace in a regex, depending on the context, but always a backspace in string and bytes
|
||||
/// literals.
|
||||
///
|
||||
/// ## Example
|
||||
///
|
||||
/// ```python
|
||||
@@ -163,20 +186,44 @@ fn check_string(checker: &Checker, literal: &StringLiteral, module: RegexModule,
|
||||
let range = literal.range;
|
||||
let mut diagnostic = checker.report_diagnostic(UnrawRePattern { module, func, kind }, range);
|
||||
|
||||
if
|
||||
// The (no-op) `u` prefix is a syntax error when combined with `r`
|
||||
!literal.flags.prefix().is_unicode()
|
||||
// We are looking for backslash characters
|
||||
// in the raw source code here, because `\n`
|
||||
// gets converted to a single character already
|
||||
// at the lexing stage.
|
||||
&&!checker.locator().slice(literal.range()).contains('\\')
|
||||
{
|
||||
diagnostic.set_fix(Fix::safe_edit(Edit::insertion(
|
||||
"r".to_string(),
|
||||
literal.range().start(),
|
||||
)));
|
||||
let Some(applicability) = raw_string_applicability(checker, literal) else {
|
||||
return;
|
||||
};
|
||||
|
||||
diagnostic.set_fix(Fix::applicable_edit(
|
||||
Edit::insertion("r".to_string(), literal.range().start()),
|
||||
applicability,
|
||||
));
|
||||
}
|
||||
|
||||
/// Check how safe it is to prepend the `r` prefix to the string.
|
||||
///
|
||||
/// ## Returns
|
||||
/// * `None` if the prefix cannot be added,
|
||||
/// * `Some(a)` if it can be added with applicability `a`.
|
||||
fn raw_string_applicability(checker: &Checker, literal: &StringLiteral) -> Option<Applicability> {
|
||||
if literal.flags.prefix().is_unicode() {
|
||||
// The (no-op) `u` prefix is a syntax error when combined with `r`
|
||||
return None;
|
||||
}
|
||||
|
||||
if checker.target_version() >= PythonVersion::PY38 {
|
||||
raw_applicability(checker, literal.range(), |escaped| {
|
||||
matches!(
|
||||
escaped,
|
||||
Some('a' | 'f' | 'n' | 'r' | 't' | 'u' | 'U' | 'v' | 'x' | 'N')
|
||||
)
|
||||
})
|
||||
} else {
|
||||
raw_applicability(checker, literal.range(), |escaped| {
|
||||
matches!(
|
||||
escaped,
|
||||
Some('a' | 'f' | 'n' | 'r' | 't' | 'u' | 'U' | 'v' | 'x')
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
// re.compile("\a\f\n\N{Partial Differential}\r\t\u27F2\U0001F0A1\v\x41") # with unsafe fix
|
||||
}
|
||||
|
||||
fn check_bytes(checker: &Checker, literal: &BytesLiteral, module: RegexModule, func: &str) {
|
||||
@@ -187,5 +234,53 @@ fn check_bytes(checker: &Checker, literal: &BytesLiteral, module: RegexModule, f
|
||||
let kind = PatternKind::Bytes;
|
||||
let func = func.to_string();
|
||||
let range = literal.range;
|
||||
checker.report_diagnostic(UnrawRePattern { module, func, kind }, range);
|
||||
let mut diagnostic = checker.report_diagnostic(UnrawRePattern { module, func, kind }, range);
|
||||
|
||||
let Some(applicability) = raw_byte_applicability(checker, literal) else {
|
||||
return;
|
||||
};
|
||||
|
||||
diagnostic.set_fix(Fix::applicable_edit(
|
||||
Edit::insertion("r".to_string(), literal.range().start()),
|
||||
applicability,
|
||||
));
|
||||
}
|
||||
|
||||
/// Check how same it is to prepend the `r` prefix to the byte sting.
|
||||
///
|
||||
/// ## Returns
|
||||
/// * `None` if the prefix cannot be added,
|
||||
/// * `Some(a)` if it can be added with applicability `a`.
|
||||
fn raw_byte_applicability(checker: &Checker, literal: &BytesLiteral) -> Option<Applicability> {
|
||||
raw_applicability(checker, literal.range(), |escaped| {
|
||||
matches!(escaped, Some('a' | 'f' | 'n' | 'r' | 't' | 'v' | 'x'))
|
||||
})
|
||||
}
|
||||
|
||||
fn raw_applicability(
|
||||
checker: &Checker,
|
||||
literal_range: TextRange,
|
||||
match_allowed_escape_sequence: impl Fn(Option<char>) -> bool,
|
||||
) -> Option<Applicability> {
|
||||
let mut found_slash = false;
|
||||
let mut chars = checker.locator().slice(literal_range).chars().peekable();
|
||||
while let Some(char) = chars.next() {
|
||||
if char == '\\' {
|
||||
found_slash = true;
|
||||
// Turning `"\uXXXX"` into `r"\uXXXX"` is behaviorally equivalent when passed
|
||||
// to `re`, however, it's not exactly the same runtime value.
|
||||
// Similarly, for the other escape sequences.
|
||||
if !match_allowed_escape_sequence(chars.peek().copied()) {
|
||||
// If the next character is not one of the whitelisted ones, we likely cannot safely turn
|
||||
// this into a raw string.
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some(if found_slash {
|
||||
Applicability::Unsafe
|
||||
} else {
|
||||
Applicability::Safe
|
||||
})
|
||||
}
|
||||
|
||||
@@ -156,3 +156,281 @@ RUF033.py:67:59: RUF033 `__post_init__` method with argument defaults
|
||||
| ^^^^^ RUF033
|
||||
|
|
||||
= help: Use `dataclasses.InitVar` instead
|
||||
|
||||
RUF033.py:73:41: RUF033 [*] `__post_init__` method with argument defaults
|
||||
|
|
||||
71 | @dataclass
|
||||
72 | class Foo:
|
||||
73 | def __post_init__(self, bar: int = (x := 1)) -> None:
|
||||
| ^^^^^^ RUF033
|
||||
74 | pass
|
||||
|
|
||||
= help: Use `dataclasses.InitVar` instead
|
||||
|
||||
ℹ Unsafe fix
|
||||
70 70 | # https://github.com/astral-sh/ruff/issues/18950
|
||||
71 71 | @dataclass
|
||||
72 72 | class Foo:
|
||||
73 |- def __post_init__(self, bar: int = (x := 1)) -> None:
|
||||
73 |+ bar: InitVar[int] = (x := 1)
|
||||
74 |+ def __post_init__(self, bar: int) -> None:
|
||||
74 75 | pass
|
||||
75 76 |
|
||||
76 77 |
|
||||
|
||||
RUF033.py:81:21: RUF033 [*] `__post_init__` method with argument defaults
|
||||
|
|
||||
79 | def __post_init__(
|
||||
80 | self,
|
||||
81 | bar: int = (x := 1) # comment
|
||||
| ^^^^^^ RUF033
|
||||
82 | ,
|
||||
83 | baz: int = (y := 2), # comment
|
||||
|
|
||||
= help: Use `dataclasses.InitVar` instead
|
||||
|
||||
ℹ Unsafe fix
|
||||
76 76 |
|
||||
77 77 | @dataclass
|
||||
78 78 | class Foo:
|
||||
79 |+ bar: InitVar[int] = (x := 1)
|
||||
79 80 | def __post_init__(
|
||||
80 81 | self,
|
||||
81 |- bar: int = (x := 1) # comment
|
||||
82 |+ bar: int # comment
|
||||
82 83 | ,
|
||||
83 84 | baz: int = (y := 2), # comment
|
||||
84 85 | foo = (a := 1) # comment
|
||||
|
||||
RUF033.py:83:21: RUF033 [*] `__post_init__` method with argument defaults
|
||||
|
|
||||
81 | bar: int = (x := 1) # comment
|
||||
82 | ,
|
||||
83 | baz: int = (y := 2), # comment
|
||||
| ^^^^^^ RUF033
|
||||
84 | foo = (a := 1) # comment
|
||||
85 | ,
|
||||
|
|
||||
= help: Use `dataclasses.InitVar` instead
|
||||
|
||||
ℹ Unsafe fix
|
||||
76 76 |
|
||||
77 77 | @dataclass
|
||||
78 78 | class Foo:
|
||||
79 |+ baz: InitVar[int] = (y := 2)
|
||||
79 80 | def __post_init__(
|
||||
80 81 | self,
|
||||
81 82 | bar: int = (x := 1) # comment
|
||||
82 83 | ,
|
||||
83 |- baz: int = (y := 2), # comment
|
||||
84 |+ baz: int, # comment
|
||||
84 85 | foo = (a := 1) # comment
|
||||
85 86 | ,
|
||||
86 87 | faz = (b := 2), # comment
|
||||
|
||||
RUF033.py:84:16: RUF033 [*] `__post_init__` method with argument defaults
|
||||
|
|
||||
82 | ,
|
||||
83 | baz: int = (y := 2), # comment
|
||||
84 | foo = (a := 1) # comment
|
||||
| ^^^^^^ RUF033
|
||||
85 | ,
|
||||
86 | faz = (b := 2), # comment
|
||||
|
|
||||
= help: Use `dataclasses.InitVar` instead
|
||||
|
||||
ℹ Unsafe fix
|
||||
76 76 |
|
||||
77 77 | @dataclass
|
||||
78 78 | class Foo:
|
||||
79 |+ foo: InitVar = (a := 1)
|
||||
79 80 | def __post_init__(
|
||||
80 81 | self,
|
||||
81 82 | bar: int = (x := 1) # comment
|
||||
82 83 | ,
|
||||
83 84 | baz: int = (y := 2), # comment
|
||||
84 |- foo = (a := 1) # comment
|
||||
85 |+ foo # comment
|
||||
85 86 | ,
|
||||
86 87 | faz = (b := 2), # comment
|
||||
87 88 | ) -> None:
|
||||
|
||||
RUF033.py:86:16: RUF033 [*] `__post_init__` method with argument defaults
|
||||
|
|
||||
84 | foo = (a := 1) # comment
|
||||
85 | ,
|
||||
86 | faz = (b := 2), # comment
|
||||
| ^^^^^^ RUF033
|
||||
87 | ) -> None:
|
||||
88 | pass
|
||||
|
|
||||
= help: Use `dataclasses.InitVar` instead
|
||||
|
||||
ℹ Unsafe fix
|
||||
76 76 |
|
||||
77 77 | @dataclass
|
||||
78 78 | class Foo:
|
||||
79 |+ faz: InitVar = (b := 2)
|
||||
79 80 | def __post_init__(
|
||||
80 81 | self,
|
||||
81 82 | bar: int = (x := 1) # comment
|
||||
--------------------------------------------------------------------------------
|
||||
83 84 | baz: int = (y := 2), # comment
|
||||
84 85 | foo = (a := 1) # comment
|
||||
85 86 | ,
|
||||
86 |- faz = (b := 2), # comment
|
||||
87 |+ faz, # comment
|
||||
87 88 | ) -> None:
|
||||
88 89 | pass
|
||||
89 90 |
|
||||
|
||||
RUF033.py:95:20: RUF033 [*] `__post_init__` method with argument defaults
|
||||
|
|
||||
93 | def __post_init__(
|
||||
94 | self,
|
||||
95 | bar: int = 1, # comment
|
||||
| ^ RUF033
|
||||
96 | baz: int = 2, # comment
|
||||
97 | ) -> None:
|
||||
|
|
||||
= help: Use `dataclasses.InitVar` instead
|
||||
|
||||
ℹ Unsafe fix
|
||||
90 90 |
|
||||
91 91 | @dataclass
|
||||
92 92 | class Foo:
|
||||
93 |+ bar: InitVar[int] = 1
|
||||
93 94 | def __post_init__(
|
||||
94 95 | self,
|
||||
95 |- bar: int = 1, # comment
|
||||
96 |+ bar: int, # comment
|
||||
96 97 | baz: int = 2, # comment
|
||||
97 98 | ) -> None:
|
||||
98 99 | pass
|
||||
|
||||
RUF033.py:96:20: RUF033 [*] `__post_init__` method with argument defaults
|
||||
|
|
||||
94 | self,
|
||||
95 | bar: int = 1, # comment
|
||||
96 | baz: int = 2, # comment
|
||||
| ^ RUF033
|
||||
97 | ) -> None:
|
||||
98 | pass
|
||||
|
|
||||
= help: Use `dataclasses.InitVar` instead
|
||||
|
||||
ℹ Unsafe fix
|
||||
90 90 |
|
||||
91 91 | @dataclass
|
||||
92 92 | class Foo:
|
||||
93 |+ baz: InitVar[int] = 2
|
||||
93 94 | def __post_init__(
|
||||
94 95 | self,
|
||||
95 96 | bar: int = 1, # comment
|
||||
96 |- baz: int = 2, # comment
|
||||
97 |+ baz: int, # comment
|
||||
97 98 | ) -> None:
|
||||
98 99 | pass
|
||||
99 100 |
|
||||
|
||||
RUF033.py:105:22: RUF033 [*] `__post_init__` method with argument defaults
|
||||
|
|
||||
103 | def __post_init__(
|
||||
104 | self,
|
||||
105 | arg1: int = (1) # comment
|
||||
| ^ RUF033
|
||||
106 | ,
|
||||
107 | arg2: int = ((1)) # comment
|
||||
|
|
||||
= help: Use `dataclasses.InitVar` instead
|
||||
|
||||
ℹ Unsafe fix
|
||||
100 100 |
|
||||
101 101 | @dataclass
|
||||
102 102 | class Foo:
|
||||
103 |+ arg1: InitVar[int] = (1)
|
||||
103 104 | def __post_init__(
|
||||
104 105 | self,
|
||||
105 |- arg1: int = (1) # comment
|
||||
106 |+ arg1: int # comment
|
||||
106 107 | ,
|
||||
107 108 | arg2: int = ((1)) # comment
|
||||
108 109 | ,
|
||||
|
||||
RUF033.py:107:23: RUF033 [*] `__post_init__` method with argument defaults
|
||||
|
|
||||
105 | arg1: int = (1) # comment
|
||||
106 | ,
|
||||
107 | arg2: int = ((1)) # comment
|
||||
| ^ RUF033
|
||||
108 | ,
|
||||
109 | arg2: int = (i for i in range(10)) # comment
|
||||
|
|
||||
= help: Use `dataclasses.InitVar` instead
|
||||
|
||||
ℹ Unsafe fix
|
||||
100 100 |
|
||||
101 101 | @dataclass
|
||||
102 102 | class Foo:
|
||||
103 |+ arg2: InitVar[int] = ((1))
|
||||
103 104 | def __post_init__(
|
||||
104 105 | self,
|
||||
105 106 | arg1: int = (1) # comment
|
||||
106 107 | ,
|
||||
107 |- arg2: int = ((1)) # comment
|
||||
108 |+ arg2: int # comment
|
||||
108 109 | ,
|
||||
109 110 | arg2: int = (i for i in range(10)) # comment
|
||||
110 111 | ,
|
||||
|
||||
RUF033.py:109:21: RUF033 [*] `__post_init__` method with argument defaults
|
||||
|
|
||||
107 | arg2: int = ((1)) # comment
|
||||
108 | ,
|
||||
109 | arg2: int = (i for i in range(10)) # comment
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ RUF033
|
||||
110 | ,
|
||||
111 | ) -> None:
|
||||
|
|
||||
= help: Use `dataclasses.InitVar` instead
|
||||
|
||||
ℹ Unsafe fix
|
||||
100 100 |
|
||||
101 101 | @dataclass
|
||||
102 102 | class Foo:
|
||||
103 |+ arg2: InitVar[int] = (i for i in range(10))
|
||||
103 104 | def __post_init__(
|
||||
104 105 | self,
|
||||
105 106 | arg1: int = (1) # comment
|
||||
106 107 | ,
|
||||
107 108 | arg2: int = ((1)) # comment
|
||||
108 109 | ,
|
||||
109 |- arg2: int = (i for i in range(10)) # comment
|
||||
110 |+ arg2: int # comment
|
||||
110 111 | ,
|
||||
111 112 | ) -> None:
|
||||
112 113 | pass
|
||||
|
||||
RUF033.py:121:27: RUF033 [*] `__post_init__` method with argument defaults
|
||||
|
|
||||
119 | def __post_init__(
|
||||
120 | self,
|
||||
121 | bar: (int) = (yield from range(5)) # comment
|
||||
| ^^^^^^^^^^^^^^^^^^^ RUF033
|
||||
122 | ,
|
||||
123 | ) -> None:
|
||||
|
|
||||
= help: Use `dataclasses.InitVar` instead
|
||||
|
||||
ℹ Unsafe fix
|
||||
116 116 | def fun_with_python_syntax():
|
||||
117 117 | @dataclass
|
||||
118 118 | class Foo:
|
||||
119 |+ bar: InitVar[int] = (yield from range(5))
|
||||
119 120 | def __post_init__(
|
||||
120 121 | self,
|
||||
121 |- bar: (int) = (yield from range(5)) # comment
|
||||
122 |+ bar: (int) # comment
|
||||
122 123 | ,
|
||||
123 124 | ) -> None:
|
||||
124 125 | ...
|
||||
|
||||
@@ -21,7 +21,7 @@ RUF039.py:5:12: RUF039 [*] First argument to `re.compile()` is not raw string
|
||||
7 7 | re.finditer("dou\ble")
|
||||
8 8 | re.fullmatch('''t\riple single''')
|
||||
|
||||
RUF039.py:6:12: RUF039 First argument to `re.findall()` is not raw string
|
||||
RUF039.py:6:12: RUF039 [*] First argument to `re.findall()` is not raw string
|
||||
|
|
||||
4 | # Errors
|
||||
5 | re.compile('single free-spacing', flags=re.X)
|
||||
@@ -32,6 +32,16 @@ RUF039.py:6:12: RUF039 First argument to `re.findall()` is not raw string
|
||||
|
|
||||
= help: Replace with raw string
|
||||
|
||||
ℹ Unsafe fix
|
||||
3 3 |
|
||||
4 4 | # Errors
|
||||
5 5 | re.compile('single free-spacing', flags=re.X)
|
||||
6 |-re.findall('si\ngle')
|
||||
6 |+re.findall(r'si\ngle')
|
||||
7 7 | re.finditer("dou\ble")
|
||||
8 8 | re.fullmatch('''t\riple single''')
|
||||
9 9 | re.match("""\triple double""")
|
||||
|
||||
RUF039.py:7:13: RUF039 First argument to `re.finditer()` is not raw string
|
||||
|
|
||||
5 | re.compile('single free-spacing', flags=re.X)
|
||||
@@ -43,7 +53,7 @@ RUF039.py:7:13: RUF039 First argument to `re.finditer()` is not raw string
|
||||
|
|
||||
= help: Replace with raw string
|
||||
|
||||
RUF039.py:8:14: RUF039 First argument to `re.fullmatch()` is not raw string
|
||||
RUF039.py:8:14: RUF039 [*] First argument to `re.fullmatch()` is not raw string
|
||||
|
|
||||
6 | re.findall('si\ngle')
|
||||
7 | re.finditer("dou\ble")
|
||||
@@ -54,7 +64,17 @@ RUF039.py:8:14: RUF039 First argument to `re.fullmatch()` is not raw string
|
||||
|
|
||||
= help: Replace with raw string
|
||||
|
||||
RUF039.py:9:10: RUF039 First argument to `re.match()` is not raw string
|
||||
ℹ Unsafe fix
|
||||
5 5 | re.compile('single free-spacing', flags=re.X)
|
||||
6 6 | re.findall('si\ngle')
|
||||
7 7 | re.finditer("dou\ble")
|
||||
8 |-re.fullmatch('''t\riple single''')
|
||||
8 |+re.fullmatch(r'''t\riple single''')
|
||||
9 9 | re.match("""\triple double""")
|
||||
10 10 | re.search('two', 'args')
|
||||
11 11 | re.split("raw", r'second')
|
||||
|
||||
RUF039.py:9:10: RUF039 [*] First argument to `re.match()` is not raw string
|
||||
|
|
||||
7 | re.finditer("dou\ble")
|
||||
8 | re.fullmatch('''t\riple single''')
|
||||
@@ -65,6 +85,16 @@ RUF039.py:9:10: RUF039 First argument to `re.match()` is not raw string
|
||||
|
|
||||
= help: Replace with raw string
|
||||
|
||||
ℹ Unsafe fix
|
||||
6 6 | re.findall('si\ngle')
|
||||
7 7 | re.finditer("dou\ble")
|
||||
8 8 | re.fullmatch('''t\riple single''')
|
||||
9 |-re.match("""\triple double""")
|
||||
9 |+re.match(r"""\triple double""")
|
||||
10 10 | re.search('two', 'args')
|
||||
11 11 | re.split("raw", r'second')
|
||||
12 12 | re.sub(u'''nicode''', u"f(?i)rst")
|
||||
|
||||
RUF039.py:10:11: RUF039 [*] First argument to `re.search()` is not raw string
|
||||
|
|
||||
8 | re.fullmatch('''t\riple single''')
|
||||
@@ -117,7 +147,7 @@ RUF039.py:12:8: RUF039 First argument to `re.sub()` is not raw string
|
||||
|
|
||||
= help: Replace with raw string
|
||||
|
||||
RUF039.py:13:9: RUF039 First argument to `re.subn()` is not raw bytes literal
|
||||
RUF039.py:13:9: RUF039 [*] First argument to `re.subn()` is not raw bytes literal
|
||||
|
|
||||
11 | re.split("raw", r'second')
|
||||
12 | re.sub(u'''nicode''', u"f(?i)rst")
|
||||
@@ -128,6 +158,16 @@ RUF039.py:13:9: RUF039 First argument to `re.subn()` is not raw bytes literal
|
||||
|
|
||||
= help: Replace with raw bytes literal
|
||||
|
||||
ℹ Safe fix
|
||||
10 10 | re.search('two', 'args')
|
||||
11 11 | re.split("raw", r'second')
|
||||
12 12 | re.sub(u'''nicode''', u"f(?i)rst")
|
||||
13 |-re.subn(b"""ytes are""", f"\u006e")
|
||||
13 |+re.subn(rb"""ytes are""", f"\u006e")
|
||||
14 14 |
|
||||
15 15 | regex.compile('single free-spacing', flags=regex.X)
|
||||
16 16 | regex.findall('si\ngle')
|
||||
|
||||
RUF039.py:15:15: RUF039 [*] First argument to `regex.compile()` is not raw string
|
||||
|
|
||||
13 | re.subn(b"""ytes are""", f"\u006e")
|
||||
@@ -149,7 +189,7 @@ RUF039.py:15:15: RUF039 [*] First argument to `regex.compile()` is not raw strin
|
||||
17 17 | regex.finditer("dou\ble")
|
||||
18 18 | regex.fullmatch('''t\riple single''')
|
||||
|
||||
RUF039.py:16:15: RUF039 First argument to `regex.findall()` is not raw string
|
||||
RUF039.py:16:15: RUF039 [*] First argument to `regex.findall()` is not raw string
|
||||
|
|
||||
15 | regex.compile('single free-spacing', flags=regex.X)
|
||||
16 | regex.findall('si\ngle')
|
||||
@@ -159,6 +199,16 @@ RUF039.py:16:15: RUF039 First argument to `regex.findall()` is not raw string
|
||||
|
|
||||
= help: Replace with raw string
|
||||
|
||||
ℹ Unsafe fix
|
||||
13 13 | re.subn(b"""ytes are""", f"\u006e")
|
||||
14 14 |
|
||||
15 15 | regex.compile('single free-spacing', flags=regex.X)
|
||||
16 |-regex.findall('si\ngle')
|
||||
16 |+regex.findall(r'si\ngle')
|
||||
17 17 | regex.finditer("dou\ble")
|
||||
18 18 | regex.fullmatch('''t\riple single''')
|
||||
19 19 | regex.match("""\triple double""")
|
||||
|
||||
RUF039.py:17:16: RUF039 First argument to `regex.finditer()` is not raw string
|
||||
|
|
||||
15 | regex.compile('single free-spacing', flags=regex.X)
|
||||
@@ -170,7 +220,7 @@ RUF039.py:17:16: RUF039 First argument to `regex.finditer()` is not raw string
|
||||
|
|
||||
= help: Replace with raw string
|
||||
|
||||
RUF039.py:18:17: RUF039 First argument to `regex.fullmatch()` is not raw string
|
||||
RUF039.py:18:17: RUF039 [*] First argument to `regex.fullmatch()` is not raw string
|
||||
|
|
||||
16 | regex.findall('si\ngle')
|
||||
17 | regex.finditer("dou\ble")
|
||||
@@ -181,7 +231,17 @@ RUF039.py:18:17: RUF039 First argument to `regex.fullmatch()` is not raw string
|
||||
|
|
||||
= help: Replace with raw string
|
||||
|
||||
RUF039.py:19:13: RUF039 First argument to `regex.match()` is not raw string
|
||||
ℹ Unsafe fix
|
||||
15 15 | regex.compile('single free-spacing', flags=regex.X)
|
||||
16 16 | regex.findall('si\ngle')
|
||||
17 17 | regex.finditer("dou\ble")
|
||||
18 |-regex.fullmatch('''t\riple single''')
|
||||
18 |+regex.fullmatch(r'''t\riple single''')
|
||||
19 19 | regex.match("""\triple double""")
|
||||
20 20 | regex.search('two', 'args')
|
||||
21 21 | regex.split("raw", r'second')
|
||||
|
||||
RUF039.py:19:13: RUF039 [*] First argument to `regex.match()` is not raw string
|
||||
|
|
||||
17 | regex.finditer("dou\ble")
|
||||
18 | regex.fullmatch('''t\riple single''')
|
||||
@@ -192,6 +252,16 @@ RUF039.py:19:13: RUF039 First argument to `regex.match()` is not raw string
|
||||
|
|
||||
= help: Replace with raw string
|
||||
|
||||
ℹ Unsafe fix
|
||||
16 16 | regex.findall('si\ngle')
|
||||
17 17 | regex.finditer("dou\ble")
|
||||
18 18 | regex.fullmatch('''t\riple single''')
|
||||
19 |-regex.match("""\triple double""")
|
||||
19 |+regex.match(r"""\triple double""")
|
||||
20 20 | regex.search('two', 'args')
|
||||
21 21 | regex.split("raw", r'second')
|
||||
22 22 | regex.sub(u'''nicode''', u"f(?i)rst")
|
||||
|
||||
RUF039.py:20:14: RUF039 [*] First argument to `regex.search()` is not raw string
|
||||
|
|
||||
18 | regex.fullmatch('''t\riple single''')
|
||||
@@ -244,7 +314,7 @@ RUF039.py:22:11: RUF039 First argument to `regex.sub()` is not raw string
|
||||
|
|
||||
= help: Replace with raw string
|
||||
|
||||
RUF039.py:23:12: RUF039 First argument to `regex.subn()` is not raw bytes literal
|
||||
RUF039.py:23:12: RUF039 [*] First argument to `regex.subn()` is not raw bytes literal
|
||||
|
|
||||
21 | regex.split("raw", r'second')
|
||||
22 | regex.sub(u'''nicode''', u"f(?i)rst")
|
||||
@@ -255,6 +325,16 @@ RUF039.py:23:12: RUF039 First argument to `regex.subn()` is not raw bytes litera
|
||||
|
|
||||
= help: Replace with raw bytes literal
|
||||
|
||||
ℹ Safe fix
|
||||
20 20 | regex.search('two', 'args')
|
||||
21 21 | regex.split("raw", r'second')
|
||||
22 22 | regex.sub(u'''nicode''', u"f(?i)rst")
|
||||
23 |-regex.subn(b"""ytes are""", f"\u006e")
|
||||
23 |+regex.subn(rb"""ytes are""", f"\u006e")
|
||||
24 24 |
|
||||
25 25 | regex.template("""(?m)
|
||||
26 26 | (?:ulti)?
|
||||
|
||||
RUF039.py:25:16: RUF039 [*] First argument to `regex.template()` is not raw string
|
||||
|
|
||||
23 | regex.subn(b"""ytes are""", f"\u006e")
|
||||
@@ -278,3 +358,111 @@ RUF039.py:25:16: RUF039 [*] First argument to `regex.template()` is not raw stri
|
||||
26 26 | (?:ulti)?
|
||||
27 27 | (?=(?<!(?<=(?!l)))
|
||||
28 28 | l(?i:ne)
|
||||
|
||||
RUF039.py:59:12: RUF039 [*] First argument to `re.compile()` is not raw string
|
||||
|
|
||||
58 | # https://github.com/astral-sh/ruff/issues/16713
|
||||
59 | re.compile("\a\f\n\r\t\u27F2\U0001F0A1\v\x41") # with unsafe fix
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF039
|
||||
60 | re.compile("\b") # without fix
|
||||
61 | re.compile("\"") # without fix
|
||||
|
|
||||
= help: Replace with raw string
|
||||
|
||||
ℹ Unsafe fix
|
||||
56 56 |
|
||||
57 57 |
|
||||
58 58 | # https://github.com/astral-sh/ruff/issues/16713
|
||||
59 |-re.compile("\a\f\n\r\t\u27F2\U0001F0A1\v\x41") # with unsafe fix
|
||||
59 |+re.compile(r"\a\f\n\r\t\u27F2\U0001F0A1\v\x41") # with unsafe fix
|
||||
60 60 | re.compile("\b") # without fix
|
||||
61 61 | re.compile("\"") # without fix
|
||||
62 62 | re.compile("\'") # without fix
|
||||
|
||||
RUF039.py:60:12: RUF039 First argument to `re.compile()` is not raw string
|
||||
|
|
||||
58 | # https://github.com/astral-sh/ruff/issues/16713
|
||||
59 | re.compile("\a\f\n\r\t\u27F2\U0001F0A1\v\x41") # with unsafe fix
|
||||
60 | re.compile("\b") # without fix
|
||||
| ^^^^ RUF039
|
||||
61 | re.compile("\"") # without fix
|
||||
62 | re.compile("\'") # without fix
|
||||
|
|
||||
= help: Replace with raw string
|
||||
|
||||
RUF039.py:61:12: RUF039 First argument to `re.compile()` is not raw string
|
||||
|
|
||||
59 | re.compile("\a\f\n\r\t\u27F2\U0001F0A1\v\x41") # with unsafe fix
|
||||
60 | re.compile("\b") # without fix
|
||||
61 | re.compile("\"") # without fix
|
||||
| ^^^^ RUF039
|
||||
62 | re.compile("\'") # without fix
|
||||
63 | re.compile('\"') # without fix
|
||||
|
|
||||
= help: Replace with raw string
|
||||
|
||||
RUF039.py:62:12: RUF039 First argument to `re.compile()` is not raw string
|
||||
|
|
||||
60 | re.compile("\b") # without fix
|
||||
61 | re.compile("\"") # without fix
|
||||
62 | re.compile("\'") # without fix
|
||||
| ^^^^ RUF039
|
||||
63 | re.compile('\"') # without fix
|
||||
64 | re.compile('\'') # without fix
|
||||
|
|
||||
= help: Replace with raw string
|
||||
|
||||
RUF039.py:63:12: RUF039 First argument to `re.compile()` is not raw string
|
||||
|
|
||||
61 | re.compile("\"") # without fix
|
||||
62 | re.compile("\'") # without fix
|
||||
63 | re.compile('\"') # without fix
|
||||
| ^^^^ RUF039
|
||||
64 | re.compile('\'') # without fix
|
||||
65 | re.compile("\\") # without fix
|
||||
|
|
||||
= help: Replace with raw string
|
||||
|
||||
RUF039.py:64:12: RUF039 First argument to `re.compile()` is not raw string
|
||||
|
|
||||
62 | re.compile("\'") # without fix
|
||||
63 | re.compile('\"') # without fix
|
||||
64 | re.compile('\'') # without fix
|
||||
| ^^^^ RUF039
|
||||
65 | re.compile("\\") # without fix
|
||||
66 | re.compile("\101") # without fix
|
||||
|
|
||||
= help: Replace with raw string
|
||||
|
||||
RUF039.py:65:12: RUF039 First argument to `re.compile()` is not raw string
|
||||
|
|
||||
63 | re.compile('\"') # without fix
|
||||
64 | re.compile('\'') # without fix
|
||||
65 | re.compile("\\") # without fix
|
||||
| ^^^^ RUF039
|
||||
66 | re.compile("\101") # without fix
|
||||
67 | re.compile("a\
|
||||
|
|
||||
= help: Replace with raw string
|
||||
|
||||
RUF039.py:66:12: RUF039 First argument to `re.compile()` is not raw string
|
||||
|
|
||||
64 | re.compile('\'') # without fix
|
||||
65 | re.compile("\\") # without fix
|
||||
66 | re.compile("\101") # without fix
|
||||
| ^^^^^^ RUF039
|
||||
67 | re.compile("a\
|
||||
68 | b") # without fix
|
||||
|
|
||||
= help: Replace with raw string
|
||||
|
||||
RUF039.py:67:12: RUF039 First argument to `re.compile()` is not raw string
|
||||
|
|
||||
65 | re.compile("\\") # without fix
|
||||
66 | re.compile("\101") # without fix
|
||||
67 | re.compile("a\
|
||||
| ____________^
|
||||
68 | | b") # without fix
|
||||
| |__^ RUF039
|
||||
|
|
||||
= help: Replace with raw string
|
||||
|
||||
@@ -65,7 +65,7 @@ RUF039_concat.py:12:5: RUF039 [*] First argument to `re.findall()` is not raw st
|
||||
14 14 | """
|
||||
15 15 | )
|
||||
|
||||
RUF039_concat.py:26:5: RUF039 First argument to `re.match()` is not raw bytes literal
|
||||
RUF039_concat.py:26:5: RUF039 [*] First argument to `re.match()` is not raw bytes literal
|
||||
|
|
||||
24 | )
|
||||
25 | re.match(
|
||||
@@ -76,6 +76,16 @@ RUF039_concat.py:26:5: RUF039 First argument to `re.match()` is not raw bytes li
|
||||
|
|
||||
= help: Replace with raw bytes literal
|
||||
|
||||
ℹ Safe fix
|
||||
23 23 | f'much?'
|
||||
24 24 | )
|
||||
25 25 | re.match(
|
||||
26 |- b'reak'
|
||||
26 |+ rb'reak'
|
||||
27 27 | br'eak'
|
||||
28 28 | )
|
||||
29 29 | re.search(
|
||||
|
||||
RUF039_concat.py:30:8: RUF039 First argument to `re.search()` is not raw string
|
||||
|
|
||||
28 | )
|
||||
@@ -295,7 +305,7 @@ RUF039_concat.py:52:5: RUF039 [*] First argument to `regex.findall()` is not raw
|
||||
54 54 | """
|
||||
55 55 | )
|
||||
|
||||
RUF039_concat.py:66:5: RUF039 First argument to `regex.match()` is not raw bytes literal
|
||||
RUF039_concat.py:66:5: RUF039 [*] First argument to `regex.match()` is not raw bytes literal
|
||||
|
|
||||
64 | )
|
||||
65 | regex.match(
|
||||
@@ -306,6 +316,16 @@ RUF039_concat.py:66:5: RUF039 First argument to `regex.match()` is not raw bytes
|
||||
|
|
||||
= help: Replace with raw bytes literal
|
||||
|
||||
ℹ Safe fix
|
||||
63 63 | f'much?'
|
||||
64 64 | )
|
||||
65 65 | regex.match(
|
||||
66 |- b'reak'
|
||||
66 |+ rb'reak'
|
||||
67 67 | br'eak'
|
||||
68 68 | )
|
||||
69 69 | regex.search(
|
||||
|
||||
RUF039_concat.py:70:8: RUF039 First argument to `regex.search()` is not raw string
|
||||
|
|
||||
68 | )
|
||||
@@ -460,3 +480,223 @@ RUF039_concat.py:78:24: RUF039 [*] First argument to `regex.subn()` is not raw s
|
||||
79 79 |
|
||||
80 80 |
|
||||
81 81 | regex.template(
|
||||
|
||||
RUF039_concat.py:98:5: RUF039 [*] First argument to `re.compile()` is not raw string
|
||||
|
|
||||
96 | # https://github.com/astral-sh/ruff/issues/16713
|
||||
97 | re.compile(
|
||||
98 | "["
|
||||
| ^^^ RUF039
|
||||
99 | "\U0001F600-\U0001F64F" # emoticons
|
||||
100 | "\U0001F300-\U0001F5FF" # symbols & pictographs
|
||||
|
|
||||
= help: Replace with raw string
|
||||
|
||||
ℹ Safe fix
|
||||
95 95 |
|
||||
96 96 | # https://github.com/astral-sh/ruff/issues/16713
|
||||
97 97 | re.compile(
|
||||
98 |- "["
|
||||
98 |+ r"["
|
||||
99 99 | "\U0001F600-\U0001F64F" # emoticons
|
||||
100 100 | "\U0001F300-\U0001F5FF" # symbols & pictographs
|
||||
101 101 | "\U0001F680-\U0001F6FF" # transport & map symbols
|
||||
|
||||
RUF039_concat.py:99:5: RUF039 [*] First argument to `re.compile()` is not raw string
|
||||
|
|
||||
97 | re.compile(
|
||||
98 | "["
|
||||
99 | "\U0001F600-\U0001F64F" # emoticons
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ RUF039
|
||||
100 | "\U0001F300-\U0001F5FF" # symbols & pictographs
|
||||
101 | "\U0001F680-\U0001F6FF" # transport & map symbols
|
||||
|
|
||||
= help: Replace with raw string
|
||||
|
||||
ℹ Unsafe fix
|
||||
96 96 | # https://github.com/astral-sh/ruff/issues/16713
|
||||
97 97 | re.compile(
|
||||
98 98 | "["
|
||||
99 |- "\U0001F600-\U0001F64F" # emoticons
|
||||
99 |+ r"\U0001F600-\U0001F64F" # emoticons
|
||||
100 100 | "\U0001F300-\U0001F5FF" # symbols & pictographs
|
||||
101 101 | "\U0001F680-\U0001F6FF" # transport & map symbols
|
||||
102 102 | "\U0001F1E0-\U0001F1FF" # flags (iOS)
|
||||
|
||||
RUF039_concat.py:100:5: RUF039 [*] First argument to `re.compile()` is not raw string
|
||||
|
|
||||
98 | "["
|
||||
99 | "\U0001F600-\U0001F64F" # emoticons
|
||||
100 | "\U0001F300-\U0001F5FF" # symbols & pictographs
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ RUF039
|
||||
101 | "\U0001F680-\U0001F6FF" # transport & map symbols
|
||||
102 | "\U0001F1E0-\U0001F1FF" # flags (iOS)
|
||||
|
|
||||
= help: Replace with raw string
|
||||
|
||||
ℹ Unsafe fix
|
||||
97 97 | re.compile(
|
||||
98 98 | "["
|
||||
99 99 | "\U0001F600-\U0001F64F" # emoticons
|
||||
100 |- "\U0001F300-\U0001F5FF" # symbols & pictographs
|
||||
100 |+ r"\U0001F300-\U0001F5FF" # symbols & pictographs
|
||||
101 101 | "\U0001F680-\U0001F6FF" # transport & map symbols
|
||||
102 102 | "\U0001F1E0-\U0001F1FF" # flags (iOS)
|
||||
103 103 | "\U00002702-\U000027B0"
|
||||
|
||||
RUF039_concat.py:101:5: RUF039 [*] First argument to `re.compile()` is not raw string
|
||||
|
|
||||
99 | "\U0001F600-\U0001F64F" # emoticons
|
||||
100 | "\U0001F300-\U0001F5FF" # symbols & pictographs
|
||||
101 | "\U0001F680-\U0001F6FF" # transport & map symbols
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ RUF039
|
||||
102 | "\U0001F1E0-\U0001F1FF" # flags (iOS)
|
||||
103 | "\U00002702-\U000027B0"
|
||||
|
|
||||
= help: Replace with raw string
|
||||
|
||||
ℹ Unsafe fix
|
||||
98 98 | "["
|
||||
99 99 | "\U0001F600-\U0001F64F" # emoticons
|
||||
100 100 | "\U0001F300-\U0001F5FF" # symbols & pictographs
|
||||
101 |- "\U0001F680-\U0001F6FF" # transport & map symbols
|
||||
101 |+ r"\U0001F680-\U0001F6FF" # transport & map symbols
|
||||
102 102 | "\U0001F1E0-\U0001F1FF" # flags (iOS)
|
||||
103 103 | "\U00002702-\U000027B0"
|
||||
104 104 | "\U000024C2-\U0001F251"
|
||||
|
||||
RUF039_concat.py:102:5: RUF039 [*] First argument to `re.compile()` is not raw string
|
||||
|
|
||||
100 | "\U0001F300-\U0001F5FF" # symbols & pictographs
|
||||
101 | "\U0001F680-\U0001F6FF" # transport & map symbols
|
||||
102 | "\U0001F1E0-\U0001F1FF" # flags (iOS)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ RUF039
|
||||
103 | "\U00002702-\U000027B0"
|
||||
104 | "\U000024C2-\U0001F251"
|
||||
|
|
||||
= help: Replace with raw string
|
||||
|
||||
ℹ Unsafe fix
|
||||
99 99 | "\U0001F600-\U0001F64F" # emoticons
|
||||
100 100 | "\U0001F300-\U0001F5FF" # symbols & pictographs
|
||||
101 101 | "\U0001F680-\U0001F6FF" # transport & map symbols
|
||||
102 |- "\U0001F1E0-\U0001F1FF" # flags (iOS)
|
||||
102 |+ r"\U0001F1E0-\U0001F1FF" # flags (iOS)
|
||||
103 103 | "\U00002702-\U000027B0"
|
||||
104 104 | "\U000024C2-\U0001F251"
|
||||
105 105 | "\u200d" # zero width joiner
|
||||
|
||||
RUF039_concat.py:103:5: RUF039 [*] First argument to `re.compile()` is not raw string
|
||||
|
|
||||
101 | "\U0001F680-\U0001F6FF" # transport & map symbols
|
||||
102 | "\U0001F1E0-\U0001F1FF" # flags (iOS)
|
||||
103 | "\U00002702-\U000027B0"
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ RUF039
|
||||
104 | "\U000024C2-\U0001F251"
|
||||
105 | "\u200d" # zero width joiner
|
||||
|
|
||||
= help: Replace with raw string
|
||||
|
||||
ℹ Unsafe fix
|
||||
100 100 | "\U0001F300-\U0001F5FF" # symbols & pictographs
|
||||
101 101 | "\U0001F680-\U0001F6FF" # transport & map symbols
|
||||
102 102 | "\U0001F1E0-\U0001F1FF" # flags (iOS)
|
||||
103 |- "\U00002702-\U000027B0"
|
||||
103 |+ r"\U00002702-\U000027B0"
|
||||
104 104 | "\U000024C2-\U0001F251"
|
||||
105 105 | "\u200d" # zero width joiner
|
||||
106 106 | "\u200c" # zero width non-joiner
|
||||
|
||||
RUF039_concat.py:104:5: RUF039 [*] First argument to `re.compile()` is not raw string
|
||||
|
|
||||
102 | "\U0001F1E0-\U0001F1FF" # flags (iOS)
|
||||
103 | "\U00002702-\U000027B0"
|
||||
104 | "\U000024C2-\U0001F251"
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ RUF039
|
||||
105 | "\u200d" # zero width joiner
|
||||
106 | "\u200c" # zero width non-joiner
|
||||
|
|
||||
= help: Replace with raw string
|
||||
|
||||
ℹ Unsafe fix
|
||||
101 101 | "\U0001F680-\U0001F6FF" # transport & map symbols
|
||||
102 102 | "\U0001F1E0-\U0001F1FF" # flags (iOS)
|
||||
103 103 | "\U00002702-\U000027B0"
|
||||
104 |- "\U000024C2-\U0001F251"
|
||||
104 |+ r"\U000024C2-\U0001F251"
|
||||
105 105 | "\u200d" # zero width joiner
|
||||
106 106 | "\u200c" # zero width non-joiner
|
||||
107 107 | "\\u200c" # must not be escaped in a raw string
|
||||
|
||||
RUF039_concat.py:105:5: RUF039 [*] First argument to `re.compile()` is not raw string
|
||||
|
|
||||
103 | "\U00002702-\U000027B0"
|
||||
104 | "\U000024C2-\U0001F251"
|
||||
105 | "\u200d" # zero width joiner
|
||||
| ^^^^^^^^ RUF039
|
||||
106 | "\u200c" # zero width non-joiner
|
||||
107 | "\\u200c" # must not be escaped in a raw string
|
||||
|
|
||||
= help: Replace with raw string
|
||||
|
||||
ℹ Unsafe fix
|
||||
102 102 | "\U0001F1E0-\U0001F1FF" # flags (iOS)
|
||||
103 103 | "\U00002702-\U000027B0"
|
||||
104 104 | "\U000024C2-\U0001F251"
|
||||
105 |- "\u200d" # zero width joiner
|
||||
105 |+ r"\u200d" # zero width joiner
|
||||
106 106 | "\u200c" # zero width non-joiner
|
||||
107 107 | "\\u200c" # must not be escaped in a raw string
|
||||
108 108 | "]+",
|
||||
|
||||
RUF039_concat.py:106:5: RUF039 [*] First argument to `re.compile()` is not raw string
|
||||
|
|
||||
104 | "\U000024C2-\U0001F251"
|
||||
105 | "\u200d" # zero width joiner
|
||||
106 | "\u200c" # zero width non-joiner
|
||||
| ^^^^^^^^ RUF039
|
||||
107 | "\\u200c" # must not be escaped in a raw string
|
||||
108 | "]+",
|
||||
|
|
||||
= help: Replace with raw string
|
||||
|
||||
ℹ Unsafe fix
|
||||
103 103 | "\U00002702-\U000027B0"
|
||||
104 104 | "\U000024C2-\U0001F251"
|
||||
105 105 | "\u200d" # zero width joiner
|
||||
106 |- "\u200c" # zero width non-joiner
|
||||
106 |+ r"\u200c" # zero width non-joiner
|
||||
107 107 | "\\u200c" # must not be escaped in a raw string
|
||||
108 108 | "]+",
|
||||
109 109 | flags=re.UNICODE,
|
||||
|
||||
RUF039_concat.py:107:5: RUF039 First argument to `re.compile()` is not raw string
|
||||
|
|
||||
105 | "\u200d" # zero width joiner
|
||||
106 | "\u200c" # zero width non-joiner
|
||||
107 | "\\u200c" # must not be escaped in a raw string
|
||||
| ^^^^^^^^^ RUF039
|
||||
108 | "]+",
|
||||
109 | flags=re.UNICODE,
|
||||
|
|
||||
= help: Replace with raw string
|
||||
|
||||
RUF039_concat.py:108:5: RUF039 [*] First argument to `re.compile()` is not raw string
|
||||
|
|
||||
106 | "\u200c" # zero width non-joiner
|
||||
107 | "\\u200c" # must not be escaped in a raw string
|
||||
108 | "]+",
|
||||
| ^^^^ RUF039
|
||||
109 | flags=re.UNICODE,
|
||||
110 | )
|
||||
|
|
||||
= help: Replace with raw string
|
||||
|
||||
ℹ Safe fix
|
||||
105 105 | "\u200d" # zero width joiner
|
||||
106 106 | "\u200c" # zero width non-joiner
|
||||
107 107 | "\\u200c" # must not be escaped in a raw string
|
||||
108 |- "]+",
|
||||
108 |+ r"]+",
|
||||
109 109 | flags=re.UNICODE,
|
||||
110 110 | )
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
---
|
||||
source: crates/ruff_linter/src/rules/ruff/mod.rs
|
||||
---
|
||||
RUF039_py_version_sensitive.py:3:12: RUF039 First argument to `re.compile()` is not raw string
|
||||
|
|
||||
1 | import re
|
||||
2 |
|
||||
3 | re.compile("\N{Partial Differential}") # with unsafe fix if python target is 3.8 or higher, else without fix
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF039
|
||||
|
|
||||
= help: Replace with raw string
|
||||
@@ -0,0 +1,17 @@
|
||||
---
|
||||
source: crates/ruff_linter/src/rules/ruff/mod.rs
|
||||
---
|
||||
RUF039_py_version_sensitive.py:3:12: RUF039 [*] First argument to `re.compile()` is not raw string
|
||||
|
|
||||
1 | import re
|
||||
2 |
|
||||
3 | re.compile("\N{Partial Differential}") # with unsafe fix if python target is 3.8 or higher, else without fix
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF039
|
||||
|
|
||||
= help: Replace with raw string
|
||||
|
||||
ℹ Unsafe fix
|
||||
1 1 | import re
|
||||
2 2 |
|
||||
3 |-re.compile("\N{Partial Differential}") # with unsafe fix if python target is 3.8 or higher, else without fix
|
||||
3 |+re.compile(r"\N{Partial Differential}") # with unsafe fix if python target is 3.8 or higher, else without fix
|
||||
@@ -708,23 +708,10 @@ pub struct ComparableTString<'a> {
|
||||
}
|
||||
|
||||
impl<'a> From<&'a ast::TStringValue> for ComparableTString<'a> {
|
||||
// The approach taken below necessarily deviates from the
|
||||
// corresponding implementation for [`ast::FStringValue`].
|
||||
// The reason is that a t-string value is composed of _three_
|
||||
// non-comparable parts: literals, f-string expressions, and
|
||||
// t-string interpolations. Since we have merged the AST nodes
|
||||
// that capture f-string expressions and t-string interpolations
|
||||
// into the shared [`ast::InterpolatedElement`], we must
|
||||
// be careful to distinguish between them here.
|
||||
// We model a [`ComparableTString`] on the actual
|
||||
// [CPython implementation] of a `string.templatelib.Template` object.
|
||||
//
|
||||
// Consequently, we model a [`ComparableTString`] on the actual
|
||||
// [CPython implementation] of a `string.templatelib.Template` object:
|
||||
// it is composed of `strings` and `interpolations`. In CPython,
|
||||
// the `strings` field is a tuple of honest strings (since f-strings
|
||||
// are evaluated). Our `strings` field will house both f-string
|
||||
// expressions and string literals.
|
||||
//
|
||||
// Finally, as in CPython, we must be careful to ensure that the length
|
||||
// As in CPython, we must be careful to ensure that the length
|
||||
// of `strings` is always one more than the length of `interpolations` -
|
||||
// that way we can recover the original reading order by interleaving
|
||||
// starting with `strings`. This is how we can tell the
|
||||
@@ -768,19 +755,6 @@ impl<'a> From<&'a ast::TStringValue> for ComparableTString<'a> {
|
||||
.push(ComparableInterpolatedStringElement::Literal("".into()));
|
||||
}
|
||||
|
||||
fn push_fstring_expression(&mut self, expression: &'a ast::InterpolatedElement) {
|
||||
if let Some(ComparableInterpolatedStringElement::Literal(last_literal)) =
|
||||
self.strings.last()
|
||||
{
|
||||
// Recall that we insert empty strings after
|
||||
// each interpolation. If we encounter an f-string
|
||||
// expression, we replace the empty string with it.
|
||||
if last_literal.is_empty() {
|
||||
self.strings.pop();
|
||||
}
|
||||
}
|
||||
self.strings.push(expression.into());
|
||||
}
|
||||
fn push_tstring_interpolation(&mut self, expression: &'a ast::InterpolatedElement) {
|
||||
self.interpolations.push(expression.into());
|
||||
self.start_new_literal();
|
||||
@@ -789,34 +763,13 @@ impl<'a> From<&'a ast::TStringValue> for ComparableTString<'a> {
|
||||
|
||||
let mut collector = Collector::default();
|
||||
|
||||
for part in value {
|
||||
match part {
|
||||
ast::TStringPart::Literal(string_literal) => {
|
||||
collector.push_literal(&string_literal.value);
|
||||
for element in value.elements() {
|
||||
match element {
|
||||
ast::InterpolatedStringElement::Literal(literal) => {
|
||||
collector.push_literal(&literal.value);
|
||||
}
|
||||
ast::TStringPart::TString(fstring) => {
|
||||
for element in &fstring.elements {
|
||||
match element {
|
||||
ast::InterpolatedStringElement::Literal(literal) => {
|
||||
collector.push_literal(&literal.value);
|
||||
}
|
||||
ast::InterpolatedStringElement::Interpolation(interpolation) => {
|
||||
collector.push_tstring_interpolation(interpolation);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::TStringPart::FString(fstring) => {
|
||||
for element in &fstring.elements {
|
||||
match element {
|
||||
ast::InterpolatedStringElement::Literal(literal) => {
|
||||
collector.push_literal(&literal.value);
|
||||
}
|
||||
ast::InterpolatedStringElement::Interpolation(expression) => {
|
||||
collector.push_fstring_expression(expression);
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::InterpolatedStringElement::Interpolation(interpolation) => {
|
||||
collector.push_tstring_interpolation(interpolation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -320,7 +320,7 @@ pub enum StringLikePartIter<'a> {
|
||||
String(std::slice::Iter<'a, ast::StringLiteral>),
|
||||
Bytes(std::slice::Iter<'a, ast::BytesLiteral>),
|
||||
FString(std::slice::Iter<'a, ast::FStringPart>),
|
||||
TString(std::slice::Iter<'a, ast::TStringPart>),
|
||||
TString(std::slice::Iter<'a, ast::TString>),
|
||||
}
|
||||
|
||||
impl<'a> Iterator for StringLikePartIter<'a> {
|
||||
@@ -339,16 +339,7 @@ impl<'a> Iterator for StringLikePartIter<'a> {
|
||||
ast::FStringPart::FString(f_string) => StringLikePart::FString(f_string),
|
||||
}
|
||||
}
|
||||
StringLikePartIter::TString(inner) => {
|
||||
let part = inner.next()?;
|
||||
match part {
|
||||
ast::TStringPart::Literal(string_literal) => {
|
||||
StringLikePart::String(string_literal)
|
||||
}
|
||||
ast::TStringPart::TString(t_string) => StringLikePart::TString(t_string),
|
||||
ast::TStringPart::FString(f_string) => StringLikePart::FString(f_string),
|
||||
}
|
||||
}
|
||||
StringLikePartIter::TString(inner) => StringLikePart::TString(inner.next()?),
|
||||
};
|
||||
|
||||
Some(part)
|
||||
@@ -378,16 +369,7 @@ impl DoubleEndedIterator for StringLikePartIter<'_> {
|
||||
ast::FStringPart::FString(f_string) => StringLikePart::FString(f_string),
|
||||
}
|
||||
}
|
||||
StringLikePartIter::TString(inner) => {
|
||||
let part = inner.next_back()?;
|
||||
match part {
|
||||
ast::TStringPart::Literal(string_literal) => {
|
||||
StringLikePart::String(string_literal)
|
||||
}
|
||||
ast::TStringPart::TString(t_string) => StringLikePart::TString(t_string),
|
||||
ast::TStringPart::FString(f_string) => StringLikePart::FString(f_string),
|
||||
}
|
||||
}
|
||||
StringLikePartIter::TString(inner) => StringLikePart::TString(inner.next_back()?),
|
||||
};
|
||||
|
||||
Some(part)
|
||||
|
||||
@@ -1274,6 +1274,7 @@ impl Truthiness {
|
||||
Self::Unknown
|
||||
}
|
||||
}
|
||||
Expr::TString(_) => Self::Truthy,
|
||||
Expr::List(ast::ExprList { elts, .. })
|
||||
| Expr::Set(ast::ExprSet { elts, .. })
|
||||
| Expr::Tuple(ast::ExprTuple { elts, .. }) => {
|
||||
@@ -1362,6 +1363,7 @@ fn is_non_empty_f_string(expr: &ast::ExprFString) -> bool {
|
||||
Expr::EllipsisLiteral(_) => true,
|
||||
Expr::List(_) => true,
|
||||
Expr::Tuple(_) => true,
|
||||
Expr::TString(_) => true,
|
||||
|
||||
// These expressions must resolve to the inner expression.
|
||||
Expr::If(ast::ExprIf { body, orelse, .. }) => inner(body) && inner(orelse),
|
||||
@@ -1386,7 +1388,6 @@ fn is_non_empty_f_string(expr: &ast::ExprFString) -> bool {
|
||||
// These literals may or may not be empty.
|
||||
Expr::FString(f_string) => is_non_empty_f_string(f_string),
|
||||
// These literals may or may not be empty.
|
||||
Expr::TString(f_string) => is_non_empty_t_string(f_string),
|
||||
Expr::StringLiteral(ast::ExprStringLiteral { value, .. }) => !value.is_empty(),
|
||||
Expr::BytesLiteral(ast::ExprBytesLiteral { value, .. }) => !value.is_empty(),
|
||||
}
|
||||
@@ -1403,76 +1404,6 @@ fn is_non_empty_f_string(expr: &ast::ExprFString) -> bool {
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns `true` if the expression definitely resolves to a non-empty string, when used as an
|
||||
/// f-string expression, or `false` if the expression may resolve to an empty string.
|
||||
fn is_non_empty_t_string(expr: &ast::ExprTString) -> bool {
|
||||
fn inner(expr: &Expr) -> bool {
|
||||
match expr {
|
||||
// When stringified, these expressions are always non-empty.
|
||||
Expr::Lambda(_) => true,
|
||||
Expr::Dict(_) => true,
|
||||
Expr::Set(_) => true,
|
||||
Expr::ListComp(_) => true,
|
||||
Expr::SetComp(_) => true,
|
||||
Expr::DictComp(_) => true,
|
||||
Expr::Compare(_) => true,
|
||||
Expr::NumberLiteral(_) => true,
|
||||
Expr::BooleanLiteral(_) => true,
|
||||
Expr::NoneLiteral(_) => true,
|
||||
Expr::EllipsisLiteral(_) => true,
|
||||
Expr::List(_) => true,
|
||||
Expr::Tuple(_) => true,
|
||||
|
||||
// These expressions must resolve to the inner expression.
|
||||
Expr::If(ast::ExprIf { body, orelse, .. }) => inner(body) && inner(orelse),
|
||||
Expr::Named(ast::ExprNamed { value, .. }) => inner(value),
|
||||
|
||||
// These expressions are complex. We can't determine whether they're empty or not.
|
||||
Expr::BoolOp(ast::ExprBoolOp { .. }) => false,
|
||||
Expr::BinOp(ast::ExprBinOp { .. }) => false,
|
||||
Expr::UnaryOp(ast::ExprUnaryOp { .. }) => false,
|
||||
Expr::Generator(_) => false,
|
||||
Expr::Await(_) => false,
|
||||
Expr::Yield(_) => false,
|
||||
Expr::YieldFrom(_) => false,
|
||||
Expr::Call(_) => false,
|
||||
Expr::Attribute(_) => false,
|
||||
Expr::Subscript(_) => false,
|
||||
Expr::Starred(_) => false,
|
||||
Expr::Name(_) => false,
|
||||
Expr::Slice(_) => false,
|
||||
Expr::IpyEscapeCommand(_) => false,
|
||||
|
||||
// These literals may or may not be empty.
|
||||
Expr::FString(f_string) => is_non_empty_f_string(f_string),
|
||||
// These literals may or may not be empty.
|
||||
Expr::TString(t_string) => is_non_empty_t_string(t_string),
|
||||
Expr::StringLiteral(ast::ExprStringLiteral { value, .. }) => !value.is_empty(),
|
||||
Expr::BytesLiteral(ast::ExprBytesLiteral { value, .. }) => !value.is_empty(),
|
||||
}
|
||||
}
|
||||
|
||||
expr.value.iter().any(|part| match part {
|
||||
ast::TStringPart::Literal(string_literal) => !string_literal.is_empty(),
|
||||
ast::TStringPart::TString(t_string) => {
|
||||
t_string.elements.iter().all(|element| match element {
|
||||
ast::InterpolatedStringElement::Literal(string_literal) => {
|
||||
!string_literal.is_empty()
|
||||
}
|
||||
ast::InterpolatedStringElement::Interpolation(t_string) => {
|
||||
inner(&t_string.expression)
|
||||
}
|
||||
})
|
||||
}
|
||||
ast::TStringPart::FString(f_string) => {
|
||||
f_string.elements.iter().all(|element| match element {
|
||||
InterpolatedStringElement::Literal(string_literal) => !string_literal.is_empty(),
|
||||
InterpolatedStringElement::Interpolation(f_string) => inner(&f_string.expression),
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns `true` if the expression definitely resolves to the empty string, when used as an f-string
|
||||
/// expression.
|
||||
fn is_empty_f_string(expr: &ast::ExprFString) -> bool {
|
||||
|
||||
@@ -29,6 +29,10 @@ impl Name {
|
||||
Self(compact_str::CompactString::const_new(name))
|
||||
}
|
||||
|
||||
pub fn shrink_to_fit(&mut self) {
|
||||
self.0.shrink_to_fit();
|
||||
}
|
||||
|
||||
pub fn as_str(&self) -> &str {
|
||||
self.0.as_str()
|
||||
}
|
||||
|
||||
@@ -171,18 +171,8 @@ impl ast::ExprTString {
|
||||
node_index: _,
|
||||
} = self;
|
||||
|
||||
for t_string_part in value {
|
||||
match t_string_part {
|
||||
ast::TStringPart::Literal(string_literal) => {
|
||||
visitor.visit_string_literal(string_literal);
|
||||
}
|
||||
ast::TStringPart::FString(f_string) => {
|
||||
visitor.visit_f_string(f_string);
|
||||
}
|
||||
ast::TStringPart::TString(t_string) => {
|
||||
visitor.visit_t_string(t_string);
|
||||
}
|
||||
}
|
||||
for t_string in value {
|
||||
visitor.visit_t_string(t_string);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -597,8 +597,8 @@ impl ExprTString {
|
||||
/// otherwise.
|
||||
pub const fn as_single_part_tstring(&self) -> Option<&TString> {
|
||||
match &self.value.inner {
|
||||
TStringValueInner::Single(TStringPart::TString(tstring)) => Some(tstring),
|
||||
_ => None,
|
||||
TStringValueInner::Single(tstring) => Some(tstring),
|
||||
TStringValueInner::Concatenated(_) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -614,7 +614,7 @@ impl TStringValue {
|
||||
/// Creates a new t-string literal with a single [`TString`] part.
|
||||
pub fn single(value: TString) -> Self {
|
||||
Self {
|
||||
inner: TStringValueInner::Single(TStringPart::TString(value)),
|
||||
inner: TStringValueInner::Single(value),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -625,7 +625,7 @@ impl TStringValue {
|
||||
///
|
||||
/// Panics if `values` has less than 2 elements.
|
||||
/// Use [`TStringValue::single`] instead.
|
||||
pub fn concatenated(values: Vec<TStringPart>) -> Self {
|
||||
pub fn concatenated(values: Vec<TString>) -> Self {
|
||||
assert!(
|
||||
values.len() > 1,
|
||||
"Use `TStringValue::single` to create single-part t-strings"
|
||||
@@ -640,78 +640,52 @@ impl TStringValue {
|
||||
matches!(self.inner, TStringValueInner::Concatenated(_))
|
||||
}
|
||||
|
||||
/// Returns a slice of all the [`TStringPart`]s contained in this value.
|
||||
pub fn as_slice(&self) -> &[TStringPart] {
|
||||
/// Returns a slice of all the [`TString`]s contained in this value.
|
||||
pub fn as_slice(&self) -> &[TString] {
|
||||
match &self.inner {
|
||||
TStringValueInner::Single(part) => std::slice::from_ref(part),
|
||||
TStringValueInner::Concatenated(parts) => parts,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a mutable slice of all the [`TStringPart`]s contained in this value.
|
||||
fn as_mut_slice(&mut self) -> &mut [TStringPart] {
|
||||
/// Returns a mutable slice of all the [`TString`]s contained in this value.
|
||||
fn as_mut_slice(&mut self) -> &mut [TString] {
|
||||
match &mut self.inner {
|
||||
TStringValueInner::Single(part) => std::slice::from_mut(part),
|
||||
TStringValueInner::Concatenated(parts) => parts,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an iterator over all the [`TStringPart`]s contained in this value.
|
||||
pub fn iter(&self) -> Iter<TStringPart> {
|
||||
/// Returns an iterator over all the [`TString`]s contained in this value.
|
||||
pub fn iter(&self) -> Iter<TString> {
|
||||
self.as_slice().iter()
|
||||
}
|
||||
|
||||
/// Returns an iterator over all the [`TStringPart`]s contained in this value
|
||||
/// Returns an iterator over all the [`TString`]s contained in this value
|
||||
/// that allows modification.
|
||||
pub fn iter_mut(&mut self) -> IterMut<TStringPart> {
|
||||
pub fn iter_mut(&mut self) -> IterMut<TString> {
|
||||
self.as_mut_slice().iter_mut()
|
||||
}
|
||||
|
||||
/// Returns an iterator over the [`StringLiteral`] parts contained in this value.
|
||||
///
|
||||
/// Note that this doesn't recurse into the t-string parts. For example,
|
||||
///
|
||||
/// ```python
|
||||
/// "foo" t"bar {x}" "baz" t"qux"
|
||||
/// ```
|
||||
///
|
||||
/// Here, the string literal parts returned would be `"foo"` and `"baz"`.
|
||||
pub fn literals(&self) -> impl Iterator<Item = &StringLiteral> {
|
||||
self.iter().filter_map(|part| part.as_literal())
|
||||
}
|
||||
|
||||
/// Returns an iterator over the [`TString`] parts contained in this value.
|
||||
///
|
||||
/// Note that this doesn't recurse into the t-string parts. For example,
|
||||
///
|
||||
/// ```python
|
||||
/// "foo" t"bar {x}" "baz" t"qux"
|
||||
/// ```
|
||||
///
|
||||
/// Here, the t-string parts returned would be `f"bar {x}"` and `f"qux"`.
|
||||
pub fn t_strings(&self) -> impl Iterator<Item = &TString> {
|
||||
self.iter().filter_map(|part| part.as_t_string())
|
||||
}
|
||||
|
||||
/// Returns an iterator over all the [`InterpolatedStringElement`] contained in this value.
|
||||
///
|
||||
/// An t-string element is what makes up an [`TString`] i.e., it is either a
|
||||
/// An interpolated string element is what makes up an [`TString`] i.e., it is either a
|
||||
/// string literal or an interpolation. In the following example,
|
||||
///
|
||||
/// ```python
|
||||
/// "foo" t"bar {x}" "baz" t"qux"
|
||||
/// t"foo" t"bar {x}" t"baz" t"qux"
|
||||
/// ```
|
||||
///
|
||||
/// The t-string elements returned would be string literal (`"bar "`),
|
||||
/// The interpolated string elements returned would be string literal (`"bar "`),
|
||||
/// interpolation (`x`) and string literal (`"qux"`).
|
||||
pub fn elements(&self) -> impl Iterator<Item = &InterpolatedStringElement> {
|
||||
self.t_strings().flat_map(|fstring| fstring.elements.iter())
|
||||
self.iter().flat_map(|tstring| tstring.elements.iter())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoIterator for &'a TStringValue {
|
||||
type Item = &'a TStringPart;
|
||||
type IntoIter = Iter<'a, TStringPart>;
|
||||
type Item = &'a TString;
|
||||
type IntoIter = Iter<'a, TString>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.iter()
|
||||
@@ -719,8 +693,8 @@ impl<'a> IntoIterator for &'a TStringValue {
|
||||
}
|
||||
|
||||
impl<'a> IntoIterator for &'a mut TStringValue {
|
||||
type Item = &'a mut TStringPart;
|
||||
type IntoIter = IterMut<'a, TStringPart>;
|
||||
type Item = &'a mut TString;
|
||||
type IntoIter = IterMut<'a, TString>;
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.iter_mut()
|
||||
}
|
||||
@@ -731,43 +705,10 @@ impl<'a> IntoIterator for &'a mut TStringValue {
|
||||
#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
|
||||
enum TStringValueInner {
|
||||
/// A single t-string i.e., `t"foo"`.
|
||||
///
|
||||
/// This is always going to be `TStringPart::TString` variant which is
|
||||
/// maintained by the `TStringValue::single` constructor.
|
||||
Single(TStringPart),
|
||||
Single(TString),
|
||||
|
||||
/// An implicitly concatenated t-string i.e., `"foo" t"bar {x}"`.
|
||||
Concatenated(Vec<TStringPart>),
|
||||
}
|
||||
|
||||
/// An t-string part which is either a string literal, an f-string,
|
||||
/// or a t-string.
|
||||
#[derive(Clone, Debug, PartialEq, is_macro::Is)]
|
||||
#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
|
||||
pub enum TStringPart {
|
||||
Literal(StringLiteral),
|
||||
FString(FString),
|
||||
TString(TString),
|
||||
}
|
||||
|
||||
impl TStringPart {
|
||||
pub fn quote_style(&self) -> Quote {
|
||||
match self {
|
||||
Self::Literal(string_literal) => string_literal.flags.quote_style(),
|
||||
Self::FString(f_string) => f_string.flags.quote_style(),
|
||||
Self::TString(t_string) => t_string.flags.quote_style(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Ranged for TStringPart {
|
||||
fn range(&self) -> TextRange {
|
||||
match self {
|
||||
TStringPart::Literal(string_literal) => string_literal.range(),
|
||||
TStringPart::FString(f_string) => f_string.range(),
|
||||
TStringPart::TString(t_string) => t_string.range(),
|
||||
}
|
||||
}
|
||||
/// An implicitly concatenated t-string i.e., `t"foo" t"bar {x}"`.
|
||||
Concatenated(Vec<TString>),
|
||||
}
|
||||
|
||||
pub trait StringFlags: Copy {
|
||||
@@ -1237,6 +1178,12 @@ pub struct TString {
|
||||
pub flags: TStringFlags,
|
||||
}
|
||||
|
||||
impl TString {
|
||||
pub fn quote_style(&self) -> Quote {
|
||||
self.flags.quote_style()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TString> for Expr {
|
||||
fn from(payload: TString) -> Self {
|
||||
ExprTString {
|
||||
|
||||
@@ -7,8 +7,8 @@ use crate::{
|
||||
self as ast, Alias, AnyParameterRef, Arguments, BoolOp, BytesLiteral, CmpOp, Comprehension,
|
||||
Decorator, ElifElseClause, ExceptHandler, Expr, ExprContext, FString, FStringPart,
|
||||
InterpolatedStringElement, Keyword, MatchCase, Operator, Parameter, Parameters, Pattern,
|
||||
PatternArguments, PatternKeyword, Stmt, StringLiteral, TString, TStringPart, TypeParam,
|
||||
TypeParamParamSpec, TypeParamTypeVar, TypeParamTypeVarTuple, TypeParams, UnaryOp, WithItem,
|
||||
PatternArguments, PatternKeyword, Stmt, StringLiteral, TString, TypeParam, TypeParamParamSpec,
|
||||
TypeParamTypeVar, TypeParamTypeVarTuple, TypeParams, UnaryOp, WithItem,
|
||||
};
|
||||
|
||||
/// A trait for AST visitors. Visits all nodes in the AST recursively in evaluation-order.
|
||||
@@ -547,14 +547,8 @@ pub fn walk_expr<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) {
|
||||
}
|
||||
}
|
||||
Expr::TString(ast::ExprTString { value, .. }) => {
|
||||
for part in value {
|
||||
match part {
|
||||
TStringPart::Literal(string_literal) => {
|
||||
visitor.visit_string_literal(string_literal);
|
||||
}
|
||||
TStringPart::FString(f_string) => visitor.visit_f_string(f_string),
|
||||
TStringPart::TString(t_string) => visitor.visit_t_string(t_string),
|
||||
}
|
||||
for t_string in value {
|
||||
visitor.visit_t_string(t_string);
|
||||
}
|
||||
}
|
||||
Expr::StringLiteral(ast::ExprStringLiteral { value, .. }) => {
|
||||
|
||||
@@ -533,18 +533,8 @@ pub fn walk_expr<V: Transformer + ?Sized>(visitor: &V, expr: &mut Expr) {
|
||||
}
|
||||
}
|
||||
Expr::TString(ast::ExprTString { value, .. }) => {
|
||||
for t_string_part in value.iter_mut() {
|
||||
match t_string_part {
|
||||
ast::TStringPart::Literal(string_literal) => {
|
||||
visitor.visit_string_literal(string_literal);
|
||||
}
|
||||
ast::TStringPart::FString(f_string) => {
|
||||
visitor.visit_f_string(f_string);
|
||||
}
|
||||
ast::TStringPart::TString(t_string) => {
|
||||
visitor.visit_t_string(t_string);
|
||||
}
|
||||
}
|
||||
for t_string in value.iter_mut() {
|
||||
visitor.visit_t_string(t_string);
|
||||
}
|
||||
}
|
||||
Expr::StringLiteral(ast::ExprStringLiteral { value, .. }) => {
|
||||
|
||||
@@ -51,28 +51,12 @@ fn concatenated_fstrings_compare_equal() -> Result<(), ParseError> {
|
||||
|
||||
#[test]
|
||||
fn concatenated_tstrings_compare_equal() -> Result<(), ParseError> {
|
||||
let split_contents = r#"t"{foo!r} this" r"\n raw" t" and {bar!s} that""#;
|
||||
let split_contents = r#"t"{foo!r} this" rt"\n raw" t" and {bar!s} that""#;
|
||||
let value_contents = r#"t"{foo!r} this\\n raw and {bar!s} that""#;
|
||||
|
||||
assert_comparable(split_contents, value_contents)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn concatenated_f_and_t_strings_interwoven_compare_equal() -> Result<(), ParseError> {
|
||||
let split_contents = r#"f"{foo} this " t"{bar}" "baz""#;
|
||||
let value_contents = r#"f"{foo}" t" this {bar}" "baz""#;
|
||||
|
||||
assert_comparable(split_contents, value_contents)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn concatenated_f_and_t_strings_compare_unequal_when_swapped() -> Result<(), ParseError> {
|
||||
let f_then_t_contents = r#"f"{foo!r} this" r"\n raw" t" and {bar!s} that""#;
|
||||
let t_then_f_contents = r#"t"{foo!r} this" r"\n raw" f" and {bar!s} that""#;
|
||||
|
||||
assert_noncomparable(f_then_t_contents, t_then_f_contents)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn t_strings_literal_order_matters_compare_unequal() -> Result<(), ParseError> {
|
||||
let interp_then_literal_contents = r#"t"{foo}bar""#;
|
||||
@@ -80,11 +64,3 @@ fn t_strings_literal_order_matters_compare_unequal() -> Result<(), ParseError> {
|
||||
|
||||
assert_noncomparable(interp_then_literal_contents, literal_then_interp_contents)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn t_strings_empty_concat_equal() -> Result<(), ParseError> {
|
||||
let empty_literal = r#""" t"hey{foo}""#;
|
||||
let empty_f_string = r#"f""t"hey{foo}""#;
|
||||
|
||||
assert_comparable(empty_literal, empty_f_string)
|
||||
}
|
||||
|
||||
@@ -5,7 +5,8 @@ expression: trace
|
||||
- ModModule
|
||||
- StmtExpr
|
||||
- ExprTString
|
||||
- StringLiteral
|
||||
- TString
|
||||
- InterpolatedStringLiteralElement
|
||||
- TString
|
||||
- InterpolatedStringLiteralElement
|
||||
- InterpolatedElement
|
||||
|
||||
@@ -4,7 +4,8 @@ expression: trace
|
||||
---
|
||||
- StmtExpr
|
||||
- ExprTString
|
||||
- StringLiteral
|
||||
- TString
|
||||
- InterpolatedStringLiteralElement
|
||||
- TString
|
||||
- InterpolatedStringLiteralElement
|
||||
- InterpolatedElement
|
||||
|
||||
@@ -148,7 +148,7 @@ fn f_strings() {
|
||||
|
||||
#[test]
|
||||
fn t_strings() {
|
||||
let source = r"'pre' t'foo {bar:.{x}f} baz'";
|
||||
let source = r"t'pre' t'foo {bar:.{x}f} baz'";
|
||||
|
||||
let trace = trace_source_order_visitation(source);
|
||||
|
||||
|
||||
@@ -157,7 +157,7 @@ fn f_strings() {
|
||||
|
||||
#[test]
|
||||
fn t_strings() {
|
||||
let source = r"'pre' t'foo {bar:.{x}f} baz'";
|
||||
let source = r"t'pre' t'foo {bar:.{x}f} baz'";
|
||||
|
||||
let trace = trace_visitation(source);
|
||||
|
||||
|
||||
@@ -1538,19 +1538,9 @@ impl<'a> Generator<'a> {
|
||||
|
||||
fn unparse_t_string_value(&mut self, value: &ast::TStringValue) {
|
||||
let mut first = true;
|
||||
for t_string_part in value {
|
||||
for t_string in value {
|
||||
self.p_delim(&mut first, " ");
|
||||
match t_string_part {
|
||||
ast::TStringPart::Literal(string_literal) => {
|
||||
self.unparse_string_literal(string_literal);
|
||||
}
|
||||
ast::TStringPart::FString(f_string) => {
|
||||
self.unparse_interpolated_string(&f_string.elements, f_string.flags.into());
|
||||
}
|
||||
ast::TStringPart::TString(t_string) => {
|
||||
self.unparse_interpolated_string(&t_string.elements, t_string.flags.into());
|
||||
}
|
||||
}
|
||||
self.unparse_interpolated_string(&t_string.elements, t_string.flags.into());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -104,16 +104,13 @@ f"{10 + len('bar')=}" f'{10 + len("bar")=}'
|
||||
# T-strings
|
||||
##############################################################################
|
||||
|
||||
# Escape `{` and `}` when merging a t-string with a string
|
||||
"a {not_a_variable}" t"b {10}" "c"
|
||||
|
||||
# Join, and break expressions
|
||||
t"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa{
|
||||
expression
|
||||
}bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" t"cccccccccccccccccccc {20999}" "more"
|
||||
}bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" t"cccccccccccccccccccc {20999}" t"more"
|
||||
|
||||
# Join, but don't break the expressions
|
||||
t"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa{expression}bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" t"cccccccccccccccccccc {20999}" "more"
|
||||
t"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa{expression}bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" t"cccccccccccccccccccc {20999}" t"more"
|
||||
|
||||
t"test{
|
||||
expression
|
||||
@@ -171,22 +168,11 @@ t"test" tR"test"
|
||||
|
||||
"single" f""""single"""
|
||||
|
||||
"single" t""""single"""
|
||||
t"single" t""""single"""
|
||||
|
||||
b"single" b"""triple"""
|
||||
|
||||
|
||||
##############################################################################
|
||||
# Don't join t-strings and f-strings
|
||||
##############################################################################
|
||||
|
||||
t"{interp}" f"{expr}"
|
||||
|
||||
f"{expr}" t"{interp}"
|
||||
|
||||
f"{expr}" "string" t"{interp}"
|
||||
|
||||
|
||||
##############################################################################
|
||||
# Join strings in with statements
|
||||
##############################################################################
|
||||
|
||||
@@ -345,7 +345,7 @@ a[
|
||||
b
|
||||
] = (
|
||||
t"ccccc{
|
||||
expression}ccccccccccc" "cccccccccccccccccccccccc" # comment
|
||||
expression}ccccccccccc" t"cccccccccccccccccccccccc" # comment
|
||||
)
|
||||
|
||||
# Same but starting with a joined string. They should both result in the same formatting.
|
||||
@@ -361,7 +361,7 @@ a[
|
||||
aaaaaaa,
|
||||
b
|
||||
] = t"ccccc{
|
||||
expression}ccccccccccc" "ccccccccccccccccccccccccccccccccccccccccccc" # comment
|
||||
expression}ccccccccccc" t"ccccccccccccccccccccccccccccccccccccccccccc" # comment
|
||||
|
||||
|
||||
# Split an overlong target, but join the string if it fits
|
||||
@@ -370,7 +370,7 @@ a[
|
||||
b
|
||||
].bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb = (
|
||||
t"ccccc{
|
||||
expression}ccccccccccc" "cccccccccccccccccccccccccccccc" # comment
|
||||
expression}ccccccccccc" t"cccccccccccccccccccccccccccccc" # comment
|
||||
)
|
||||
|
||||
# Split both if necessary and keep multiline
|
||||
@@ -379,66 +379,66 @@ a[
|
||||
b
|
||||
].bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb = (
|
||||
t"ccccc{
|
||||
expression}cccccccccccccccccccccccccccccccc" "ccccccccccccccccccccccccccccccc" # comment
|
||||
expression}cccccccccccccccccccccccccccccccc" t"ccccccccccccccccccccccccccccccc" # comment
|
||||
)
|
||||
|
||||
# Don't inline t-strings that contain expressions that are guaranteed to split, e.b. because of a magic trailing comma
|
||||
aaaaaaaaaaaaaaaaaa = t"testeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee{
|
||||
[a,]
|
||||
}" "moreeeeeeeeeeeeeeeeeeee" "test" # comment
|
||||
}" t"moreeeeeeeeeeeeeeeeeeee" t"test" # comment
|
||||
|
||||
aaaaaaaaaaaaaaaaaa = (
|
||||
t"testeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee{
|
||||
[a,]
|
||||
}" "moreeeeeeeeeeeeeeeeeeee" "test" # comment
|
||||
}" t"moreeeeeeeeeeeeeeeeeeee" t"test" # comment
|
||||
)
|
||||
|
||||
aaaaa[aaaaaaaaaaa] = t"testeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee{
|
||||
[a,]
|
||||
}" "moreeeeeeeeeeeeeeeeeeee" "test" # comment
|
||||
}" t"moreeeeeeeeeeeeeeeeeeee" t"test" # comment
|
||||
|
||||
aaaaa[aaaaaaaaaaa] = (t"testeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee{
|
||||
[a,]
|
||||
}" "moreeeeeeeeeeeeeeeeeeee" "test" # comment
|
||||
}" t"moreeeeeeeeeeeeeeeeeeee" t"test" # comment
|
||||
)
|
||||
|
||||
# Don't inline t-strings that contain commented expressions
|
||||
aaaaaaaaaaaaaaaaaa = (
|
||||
t"testeeeeeeeeeeeeeeeeeeeeeeeee{[
|
||||
a # comment
|
||||
]}" "moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
]}" t"moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
)
|
||||
|
||||
aaaaa[aaaaaaaaaaa] = (
|
||||
t"testeeeeeeeeeeeeeeeeeeeeeeeee{[
|
||||
a # comment
|
||||
]}" "moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
]}" t"moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
)
|
||||
|
||||
# Don't inline t-strings with multiline debug expressions:
|
||||
aaaaaaaaaaaaaaaaaa = (
|
||||
t"testeeeeeeeeeeeeeeeeeeeeeeeee{
|
||||
a=}" "moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
a=}" t"moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
)
|
||||
|
||||
aaaaaaaaaaaaaaaaaa = (
|
||||
t"testeeeeeeeeeeeeeeeeeeeeeeeee{a +
|
||||
b=}" "moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
b=}" t"moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
)
|
||||
|
||||
aaaaaaaaaaaaaaaaaa = (
|
||||
t"testeeeeeeeeeeeeeeeeeeeeeeeee{a
|
||||
=}" "moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
=}" t"moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
)
|
||||
|
||||
aaaaa[aaaaaaaaaaa] = (
|
||||
t"testeeeeeeeeeeeeeeeeeeeeeeeee{
|
||||
a=}" "moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
a=}" t"moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
)
|
||||
|
||||
aaaaa[aaaaaaaaaaa] = (
|
||||
t"testeeeeeeeeeeeeeeeeeeeeeeeee{a
|
||||
=}" "moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
=}" t"moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
)
|
||||
|
||||
|
||||
@@ -499,7 +499,7 @@ a = (
|
||||
)
|
||||
|
||||
logger.error(
|
||||
f"Failed to run task {task} for job"
|
||||
f"Failed to run task {task} for job"
|
||||
f"with id {str(job.id)}" # type: ignore[union-attr]
|
||||
)
|
||||
|
||||
|
||||
@@ -8,21 +8,21 @@ rt"Not-so-tricky \"quote"
|
||||
|
||||
# Regression test for tstrings dropping comments
|
||||
result_f = (
|
||||
'Traceback (most recent call last):\n'
|
||||
t'Traceback (most recent call last):\n'
|
||||
t' File "{__file__}", line {lineno_f+5}, in _check_recursive_traceback_display\n'
|
||||
' f()\n'
|
||||
t' f()\n'
|
||||
t' File "{__file__}", line {lineno_f+1}, in f\n'
|
||||
' f()\n'
|
||||
t' f()\n'
|
||||
t' File "{__file__}", line {lineno_f+1}, in f\n'
|
||||
' f()\n'
|
||||
t' f()\n'
|
||||
t' File "{__file__}", line {lineno_f+1}, in f\n'
|
||||
' f()\n'
|
||||
t' f()\n'
|
||||
# XXX: The following line changes depending on whether the tests
|
||||
# are run through the interactive interpreter or with -m
|
||||
# It also varies depending on the platform (stack size)
|
||||
# Fortunately, we don't care about exactness here, so we use regex
|
||||
r' \[Previous line repeated (\d+) more times\]' '\n'
|
||||
'RecursionError: maximum recursion depth exceeded\n'
|
||||
rt' \[Previous line repeated (\d+) more times\]' t'\n'
|
||||
t'RecursionError: maximum recursion depth exceeded\n'
|
||||
)
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ result_f = (
|
||||
(
|
||||
t'{1}'
|
||||
# comment 1
|
||||
''
|
||||
t''
|
||||
)
|
||||
|
||||
(
|
||||
@@ -655,7 +655,7 @@ hello {
|
||||
|
||||
# Implicit concatenated t-string containing quotes
|
||||
_ = (
|
||||
'This string should change its quotes to double quotes'
|
||||
t'This string should change its quotes to double quotes'
|
||||
t'This string uses double quotes in an expression {"it's a quote"}'
|
||||
t'This t-string does not use any quotes.'
|
||||
)
|
||||
|
||||
@@ -110,16 +110,13 @@ f"{10 + len('bar')=}" f'{10 + len("bar")=}'
|
||||
# T-strings
|
||||
##############################################################################
|
||||
|
||||
# Escape `{` and `}` when merging a t-string with a string
|
||||
"a {not_a_variable}" t"b {10}" "c"
|
||||
|
||||
# Join, and break expressions
|
||||
t"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa{
|
||||
expression
|
||||
}bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" t"cccccccccccccccccccc {20999}" "more"
|
||||
}bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" t"cccccccccccccccccccc {20999}" t"more"
|
||||
|
||||
# Join, but don't break the expressions
|
||||
t"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa{expression}bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" t"cccccccccccccccccccc {20999}" "more"
|
||||
t"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa{expression}bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" t"cccccccccccccccccccc {20999}" t"more"
|
||||
|
||||
t"test{
|
||||
expression
|
||||
@@ -177,22 +174,11 @@ t"test" tR"test"
|
||||
|
||||
"single" f""""single"""
|
||||
|
||||
"single" t""""single"""
|
||||
t"single" t""""single"""
|
||||
|
||||
b"single" b"""triple"""
|
||||
|
||||
|
||||
##############################################################################
|
||||
# Don't join t-strings and f-strings
|
||||
##############################################################################
|
||||
|
||||
t"{interp}" f"{expr}"
|
||||
|
||||
f"{expr}" t"{interp}"
|
||||
|
||||
f"{expr}" "string" t"{interp}"
|
||||
|
||||
|
||||
##############################################################################
|
||||
# Join strings in with statements
|
||||
##############################################################################
|
||||
@@ -521,9 +507,6 @@ f"{10 + len('bar')=}" f'{10 + len("bar")=}'
|
||||
# T-strings
|
||||
##############################################################################
|
||||
|
||||
# Escape `{` and `}` when merging a t-string with a string
|
||||
t"a {{not_a_variable}}b {10}c"
|
||||
|
||||
# Join, and break expressions
|
||||
t"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa{
|
||||
expression
|
||||
@@ -583,22 +566,11 @@ t"test" Rt"test"
|
||||
|
||||
"single" f""""single"""
|
||||
|
||||
"single" t""""single"""
|
||||
t"single" t""""single"""
|
||||
|
||||
b"single" b"""triple"""
|
||||
|
||||
|
||||
##############################################################################
|
||||
# Don't join t-strings and f-strings
|
||||
##############################################################################
|
||||
|
||||
t"{interp}" f"{expr}"
|
||||
|
||||
f"{expr}" t"{interp}"
|
||||
|
||||
f"{expr}" "string" t"{interp}"
|
||||
|
||||
|
||||
##############################################################################
|
||||
# Join strings in with statements
|
||||
##############################################################################
|
||||
@@ -905,7 +877,7 @@ f"aaaaaaaaaaaaaaaa \
|
||||
```diff
|
||||
--- Stable
|
||||
+++ Preview
|
||||
@@ -302,9 +302,12 @@
|
||||
@@ -288,9 +288,12 @@
|
||||
##############################################################################
|
||||
# Use can_omit_optional_parentheses layout to avoid an instability where the formatter
|
||||
# picks the can_omit_optional_parentheses layout when the strings are joined.
|
||||
|
||||
@@ -351,7 +351,7 @@ a[
|
||||
b
|
||||
] = (
|
||||
t"ccccc{
|
||||
expression}ccccccccccc" "cccccccccccccccccccccccc" # comment
|
||||
expression}ccccccccccc" t"cccccccccccccccccccccccc" # comment
|
||||
)
|
||||
|
||||
# Same but starting with a joined string. They should both result in the same formatting.
|
||||
@@ -367,7 +367,7 @@ a[
|
||||
aaaaaaa,
|
||||
b
|
||||
] = t"ccccc{
|
||||
expression}ccccccccccc" "ccccccccccccccccccccccccccccccccccccccccccc" # comment
|
||||
expression}ccccccccccc" t"ccccccccccccccccccccccccccccccccccccccccccc" # comment
|
||||
|
||||
|
||||
# Split an overlong target, but join the string if it fits
|
||||
@@ -376,7 +376,7 @@ a[
|
||||
b
|
||||
].bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb = (
|
||||
t"ccccc{
|
||||
expression}ccccccccccc" "cccccccccccccccccccccccccccccc" # comment
|
||||
expression}ccccccccccc" t"cccccccccccccccccccccccccccccc" # comment
|
||||
)
|
||||
|
||||
# Split both if necessary and keep multiline
|
||||
@@ -385,66 +385,66 @@ a[
|
||||
b
|
||||
].bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb = (
|
||||
t"ccccc{
|
||||
expression}cccccccccccccccccccccccccccccccc" "ccccccccccccccccccccccccccccccc" # comment
|
||||
expression}cccccccccccccccccccccccccccccccc" t"ccccccccccccccccccccccccccccccc" # comment
|
||||
)
|
||||
|
||||
# Don't inline t-strings that contain expressions that are guaranteed to split, e.b. because of a magic trailing comma
|
||||
aaaaaaaaaaaaaaaaaa = t"testeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee{
|
||||
[a,]
|
||||
}" "moreeeeeeeeeeeeeeeeeeee" "test" # comment
|
||||
}" t"moreeeeeeeeeeeeeeeeeeee" t"test" # comment
|
||||
|
||||
aaaaaaaaaaaaaaaaaa = (
|
||||
t"testeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee{
|
||||
[a,]
|
||||
}" "moreeeeeeeeeeeeeeeeeeee" "test" # comment
|
||||
}" t"moreeeeeeeeeeeeeeeeeeee" t"test" # comment
|
||||
)
|
||||
|
||||
aaaaa[aaaaaaaaaaa] = t"testeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee{
|
||||
[a,]
|
||||
}" "moreeeeeeeeeeeeeeeeeeee" "test" # comment
|
||||
}" t"moreeeeeeeeeeeeeeeeeeee" t"test" # comment
|
||||
|
||||
aaaaa[aaaaaaaaaaa] = (t"testeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee{
|
||||
[a,]
|
||||
}" "moreeeeeeeeeeeeeeeeeeee" "test" # comment
|
||||
}" t"moreeeeeeeeeeeeeeeeeeee" t"test" # comment
|
||||
)
|
||||
|
||||
# Don't inline t-strings that contain commented expressions
|
||||
aaaaaaaaaaaaaaaaaa = (
|
||||
t"testeeeeeeeeeeeeeeeeeeeeeeeee{[
|
||||
a # comment
|
||||
]}" "moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
]}" t"moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
)
|
||||
|
||||
aaaaa[aaaaaaaaaaa] = (
|
||||
t"testeeeeeeeeeeeeeeeeeeeeeeeee{[
|
||||
a # comment
|
||||
]}" "moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
]}" t"moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
)
|
||||
|
||||
# Don't inline t-strings with multiline debug expressions:
|
||||
aaaaaaaaaaaaaaaaaa = (
|
||||
t"testeeeeeeeeeeeeeeeeeeeeeeeee{
|
||||
a=}" "moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
a=}" t"moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
)
|
||||
|
||||
aaaaaaaaaaaaaaaaaa = (
|
||||
t"testeeeeeeeeeeeeeeeeeeeeeeeee{a +
|
||||
b=}" "moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
b=}" t"moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
)
|
||||
|
||||
aaaaaaaaaaaaaaaaaa = (
|
||||
t"testeeeeeeeeeeeeeeeeeeeeeeeee{a
|
||||
=}" "moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
=}" t"moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
)
|
||||
|
||||
aaaaa[aaaaaaaaaaa] = (
|
||||
t"testeeeeeeeeeeeeeeeeeeeeeeeee{
|
||||
a=}" "moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
a=}" t"moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
)
|
||||
|
||||
aaaaa[aaaaaaaaaaa] = (
|
||||
t"testeeeeeeeeeeeeeeeeeeeeeeeee{a
|
||||
=}" "moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
=}" t"moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
)
|
||||
|
||||
|
||||
@@ -505,7 +505,7 @@ a = (
|
||||
)
|
||||
|
||||
logger.error(
|
||||
f"Failed to run task {task} for job"
|
||||
f"Failed to run task {task} for job"
|
||||
f"with id {str(job.id)}" # type: ignore[union-attr]
|
||||
)
|
||||
|
||||
@@ -909,7 +909,7 @@ a[aaaaaaa, b] = t"ccccc{expression}ccccccccccccccccccccccccccccccccccc" # comme
|
||||
# The string gets parenthesized because it, with the inlined comment, exceeds the line length limit.
|
||||
a[aaaaaaa, b] = (
|
||||
t"ccccc{expression}ccccccccccc"
|
||||
"ccccccccccccccccccccccccccccccccccccccccccc"
|
||||
t"ccccccccccccccccccccccccccccccccccccccccccc"
|
||||
) # comment
|
||||
|
||||
|
||||
@@ -925,7 +925,7 @@ a[
|
||||
aaaaaaa, b
|
||||
].bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb = (
|
||||
t"ccccc{expression}cccccccccccccccccccccccccccccccc"
|
||||
"ccccccccccccccccccccccccccccccc"
|
||||
t"ccccccccccccccccccccccccccccccc"
|
||||
) # comment
|
||||
|
||||
# Don't inline t-strings that contain expressions that are guaranteed to split, e.b. because of a magic trailing comma
|
||||
@@ -935,8 +935,8 @@ aaaaaaaaaaaaaaaaaa = (
|
||||
a,
|
||||
]
|
||||
}"
|
||||
"moreeeeeeeeeeeeeeeeeeee"
|
||||
"test"
|
||||
t"moreeeeeeeeeeeeeeeeeeee"
|
||||
t"test"
|
||||
) # comment
|
||||
|
||||
aaaaaaaaaaaaaaaaaa = (
|
||||
@@ -945,8 +945,8 @@ aaaaaaaaaaaaaaaaaa = (
|
||||
a,
|
||||
]
|
||||
}"
|
||||
"moreeeeeeeeeeeeeeeeeeee"
|
||||
"test" # comment
|
||||
t"moreeeeeeeeeeeeeeeeeeee"
|
||||
t"test" # comment
|
||||
)
|
||||
|
||||
aaaaa[aaaaaaaaaaa] = (
|
||||
@@ -955,8 +955,8 @@ aaaaa[aaaaaaaaaaa] = (
|
||||
a,
|
||||
]
|
||||
}"
|
||||
"moreeeeeeeeeeeeeeeeeeee"
|
||||
"test"
|
||||
t"moreeeeeeeeeeeeeeeeeeee"
|
||||
t"test"
|
||||
) # comment
|
||||
|
||||
aaaaa[aaaaaaaaaaa] = (
|
||||
@@ -965,8 +965,8 @@ aaaaa[aaaaaaaaaaa] = (
|
||||
a,
|
||||
]
|
||||
}"
|
||||
"moreeeeeeeeeeeeeeeeeeee"
|
||||
"test" # comment
|
||||
t"moreeeeeeeeeeeeeeeeeeee"
|
||||
t"test" # comment
|
||||
)
|
||||
|
||||
# Don't inline t-strings that contain commented expressions
|
||||
@@ -976,7 +976,7 @@ aaaaaaaaaaaaaaaaaa = (
|
||||
a # comment
|
||||
]
|
||||
}"
|
||||
"moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
t"moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
)
|
||||
|
||||
aaaaa[aaaaaaaaaaa] = (
|
||||
@@ -985,38 +985,38 @@ aaaaa[aaaaaaaaaaa] = (
|
||||
a # comment
|
||||
]
|
||||
}"
|
||||
"moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
t"moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
)
|
||||
|
||||
# Don't inline t-strings with multiline debug expressions:
|
||||
aaaaaaaaaaaaaaaaaa = (
|
||||
t"testeeeeeeeeeeeeeeeeeeeeeeeee{
|
||||
a=}"
|
||||
"moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
t"moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
)
|
||||
|
||||
aaaaaaaaaaaaaaaaaa = (
|
||||
t"testeeeeeeeeeeeeeeeeeeeeeeeee{a +
|
||||
b=}"
|
||||
"moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
t"moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
)
|
||||
|
||||
aaaaaaaaaaaaaaaaaa = (
|
||||
t"testeeeeeeeeeeeeeeeeeeeeeeeee{a
|
||||
=}"
|
||||
"moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
t"moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
)
|
||||
|
||||
aaaaa[aaaaaaaaaaa] = (
|
||||
t"testeeeeeeeeeeeeeeeeeeeeeeeee{
|
||||
a=}"
|
||||
"moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
t"moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
)
|
||||
|
||||
aaaaa[aaaaaaaaaaa] = (
|
||||
t"testeeeeeeeeeeeeeeeeeeeeeeeee{a
|
||||
=}"
|
||||
"moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
t"moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -14,21 +14,21 @@ rt"Not-so-tricky \"quote"
|
||||
|
||||
# Regression test for tstrings dropping comments
|
||||
result_f = (
|
||||
'Traceback (most recent call last):\n'
|
||||
t'Traceback (most recent call last):\n'
|
||||
t' File "{__file__}", line {lineno_f+5}, in _check_recursive_traceback_display\n'
|
||||
' f()\n'
|
||||
t' f()\n'
|
||||
t' File "{__file__}", line {lineno_f+1}, in f\n'
|
||||
' f()\n'
|
||||
t' f()\n'
|
||||
t' File "{__file__}", line {lineno_f+1}, in f\n'
|
||||
' f()\n'
|
||||
t' f()\n'
|
||||
t' File "{__file__}", line {lineno_f+1}, in f\n'
|
||||
' f()\n'
|
||||
t' f()\n'
|
||||
# XXX: The following line changes depending on whether the tests
|
||||
# are run through the interactive interpreter or with -m
|
||||
# It also varies depending on the platform (stack size)
|
||||
# Fortunately, we don't care about exactness here, so we use regex
|
||||
r' \[Previous line repeated (\d+) more times\]' '\n'
|
||||
'RecursionError: maximum recursion depth exceeded\n'
|
||||
rt' \[Previous line repeated (\d+) more times\]' t'\n'
|
||||
t'RecursionError: maximum recursion depth exceeded\n'
|
||||
)
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ result_f = (
|
||||
(
|
||||
t'{1}'
|
||||
# comment 1
|
||||
''
|
||||
t''
|
||||
)
|
||||
|
||||
(
|
||||
@@ -661,7 +661,7 @@ hello {
|
||||
|
||||
# Implicit concatenated t-string containing quotes
|
||||
_ = (
|
||||
'This string should change its quotes to double quotes'
|
||||
t'This string should change its quotes to double quotes'
|
||||
t'This string uses double quotes in an expression {"it's a quote"}'
|
||||
t'This t-string does not use any quotes.'
|
||||
)
|
||||
@@ -761,22 +761,22 @@ rt"Not-so-tricky \"quote"
|
||||
|
||||
# Regression test for tstrings dropping comments
|
||||
result_f = (
|
||||
"Traceback (most recent call last):\n"
|
||||
t"Traceback (most recent call last):\n"
|
||||
t' File "{__file__}", line {lineno_f + 5}, in _check_recursive_traceback_display\n'
|
||||
" f()\n"
|
||||
t" f()\n"
|
||||
t' File "{__file__}", line {lineno_f + 1}, in f\n'
|
||||
" f()\n"
|
||||
t" f()\n"
|
||||
t' File "{__file__}", line {lineno_f + 1}, in f\n'
|
||||
" f()\n"
|
||||
t" f()\n"
|
||||
t' File "{__file__}", line {lineno_f + 1}, in f\n'
|
||||
" f()\n"
|
||||
t" f()\n"
|
||||
# XXX: The following line changes depending on whether the tests
|
||||
# are run through the interactive interpreter or with -m
|
||||
# It also varies depending on the platform (stack size)
|
||||
# Fortunately, we don't care about exactness here, so we use regex
|
||||
r" \[Previous line repeated (\d+) more times\]"
|
||||
"\n"
|
||||
"RecursionError: maximum recursion depth exceeded\n"
|
||||
rt" \[Previous line repeated (\d+) more times\]"
|
||||
t"\n"
|
||||
t"RecursionError: maximum recursion depth exceeded\n"
|
||||
)
|
||||
|
||||
|
||||
@@ -785,7 +785,7 @@ result_f = (
|
||||
(
|
||||
t"{1}"
|
||||
# comment 1
|
||||
""
|
||||
t""
|
||||
)
|
||||
|
||||
(
|
||||
@@ -1463,7 +1463,7 @@ hello {
|
||||
|
||||
# Implicit concatenated t-string containing quotes
|
||||
_ = (
|
||||
"This string should change its quotes to double quotes"
|
||||
t"This string should change its quotes to double quotes"
|
||||
t"This string uses double quotes in an expression {"it's a quote"}"
|
||||
t"This t-string does not use any quotes."
|
||||
)
|
||||
|
||||
@@ -3,4 +3,3 @@ t"{hey}"
|
||||
t'{there}'
|
||||
t"""what's
|
||||
happening?"""
|
||||
"implicitly"t"concatenated"
|
||||
|
||||
@@ -3,4 +3,3 @@ t"{hey}"
|
||||
t'{there}'
|
||||
t"""what's
|
||||
happening?"""
|
||||
"implicitly"t"concatenated"
|
||||
|
||||
@@ -17,7 +17,7 @@ t"{ foo = !s }"
|
||||
t"{ 1, 2 = }"
|
||||
t'{t"{3.1415=:.1f}":*^20}'
|
||||
|
||||
{"foo " t"bar {x + y} " "baz": 10}
|
||||
{t"foo " t"bar {x + y} " t"baz": 10}
|
||||
match foo:
|
||||
case "one":
|
||||
pass
|
||||
@@ -44,31 +44,18 @@ t"{x=!a}"
|
||||
t"{x:.3f!r =}"
|
||||
t"{x = !r :.3f}"
|
||||
t"{x:.3f=!r}"
|
||||
"hello" t"{x}"
|
||||
t"hello" t"{x}"
|
||||
t"{x}" t"{y}"
|
||||
t"{x}" "world"
|
||||
t"{x}" t"world"
|
||||
t"Invalid args in command: {command, *args}"
|
||||
"foo" t"{x}" "bar"
|
||||
t"foo" t"{x}" t"bar"
|
||||
(
|
||||
t"a"
|
||||
t"b"
|
||||
"c"
|
||||
t"c"
|
||||
rt"d"
|
||||
fr"e"
|
||||
tr"e"
|
||||
)
|
||||
|
||||
# With unicode strings
|
||||
u"foo" t"{bar}" "baz" " some"
|
||||
"foo" t"{bar}" u"baz" " some"
|
||||
"foo" t"{bar}" "baz" u" some"
|
||||
u"foo" t"bar {baz} really" u"bar" "no"
|
||||
|
||||
|
||||
# With f-strings
|
||||
f"{this}" t"{that}"
|
||||
t"{this}"f"{that}"
|
||||
t"{this}" "that" f"{other}"
|
||||
f"one {this} two" "that" t"three {other} four"
|
||||
|
||||
# Nesting
|
||||
t"{f"{t"{this}"}"}"
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
use std::cmp::Ordering;
|
||||
use std::ops::Deref;
|
||||
|
||||
use bitflags::bitflags;
|
||||
@@ -1256,7 +1255,6 @@ impl<'src> Parser<'src> {
|
||||
// t'{there}'
|
||||
// t"""what's
|
||||
// happening?"""
|
||||
// "implicitly"t"concatenated"
|
||||
|
||||
// test_err template_strings_py313
|
||||
// # parse_options: {"target-version": "3.13"}
|
||||
@@ -1264,7 +1262,6 @@ impl<'src> Parser<'src> {
|
||||
// t'{there}'
|
||||
// t"""what's
|
||||
// happening?"""
|
||||
// "implicitly"t"concatenated"
|
||||
let string_type = StringType::TString(
|
||||
self.parse_interpolated_string(InterpolatedStringKind::TString)
|
||||
.into(),
|
||||
@@ -1281,7 +1278,7 @@ impl<'src> Parser<'src> {
|
||||
|
||||
match strings.len() {
|
||||
// This is not possible as the function was called by matching against a
|
||||
// `String` or `FStringStart` token.
|
||||
// `String`, `FStringStart`, or `TStringStart` token.
|
||||
0 => unreachable!("Expected to parse at least one string"),
|
||||
// We need a owned value, hence the `pop` here.
|
||||
1 => match strings.pop().unwrap() {
|
||||
@@ -1322,58 +1319,84 @@ impl<'src> Parser<'src> {
|
||||
) -> Expr {
|
||||
assert!(strings.len() > 1);
|
||||
|
||||
let mut has_tstring = false;
|
||||
let mut has_fstring = false;
|
||||
let mut byte_literal_count = 0;
|
||||
let mut tstring_count = 0;
|
||||
for string in &strings {
|
||||
match string {
|
||||
StringType::FString(_) => has_fstring = true,
|
||||
StringType::TString(_) => has_tstring = true,
|
||||
StringType::TString(_) => tstring_count += 1,
|
||||
StringType::Bytes(_) => byte_literal_count += 1,
|
||||
StringType::Str(_) => {}
|
||||
}
|
||||
}
|
||||
let has_bytes = byte_literal_count > 0;
|
||||
let has_tstring = tstring_count > 0;
|
||||
|
||||
if has_bytes {
|
||||
match byte_literal_count.cmp(&strings.len()) {
|
||||
Ordering::Less => {
|
||||
// TODO(dhruvmanila): This is not an ideal recovery because the parser
|
||||
// replaces the byte literals with an invalid string literal node. Any
|
||||
// downstream tools can extract the raw bytes from the range.
|
||||
//
|
||||
// We could convert the node into a string and mark it as invalid
|
||||
// and would be clever to mark the type which is fewer in quantity.
|
||||
if byte_literal_count < strings.len() {
|
||||
// TODO(dhruvmanila): This is not an ideal recovery because the parser
|
||||
// replaces the byte literals with an invalid string literal node. Any
|
||||
// downstream tools can extract the raw bytes from the range.
|
||||
//
|
||||
// We could convert the node into a string and mark it as invalid
|
||||
// and would be clever to mark the type which is fewer in quantity.
|
||||
|
||||
// test_err mixed_bytes_and_non_bytes_literals
|
||||
// 'first' b'second'
|
||||
// f'first' b'second'
|
||||
// 'first' f'second' b'third'
|
||||
self.add_error(
|
||||
ParseErrorType::OtherError(
|
||||
"Bytes literal cannot be mixed with non-bytes literals".to_string(),
|
||||
),
|
||||
range,
|
||||
);
|
||||
}
|
||||
// Only construct a byte expression if all the literals are bytes
|
||||
// otherwise, we'll try either string, t-string, or f-string. This is to retain
|
||||
// as much information as possible.
|
||||
Ordering::Equal => {
|
||||
let mut values = Vec::with_capacity(strings.len());
|
||||
for string in strings {
|
||||
values.push(match string {
|
||||
StringType::Bytes(value) => value,
|
||||
_ => unreachable!("Expected `StringType::Bytes`"),
|
||||
});
|
||||
}
|
||||
return Expr::from(ast::ExprBytesLiteral {
|
||||
value: ast::BytesLiteralValue::concatenated(values),
|
||||
range,
|
||||
node_index: AtomicNodeIndex::dummy(),
|
||||
// test_err mixed_bytes_and_non_bytes_literals
|
||||
// 'first' b'second'
|
||||
// f'first' b'second'
|
||||
// 'first' f'second' b'third'
|
||||
self.add_error(
|
||||
ParseErrorType::OtherError(
|
||||
"Bytes literal cannot be mixed with non-bytes literals".to_string(),
|
||||
),
|
||||
range,
|
||||
);
|
||||
}
|
||||
// Only construct a byte expression if all the literals are bytes
|
||||
// otherwise, we'll try either string, t-string, or f-string. This is to retain
|
||||
// as much information as possible.
|
||||
else {
|
||||
let mut values = Vec::with_capacity(strings.len());
|
||||
for string in strings {
|
||||
values.push(match string {
|
||||
StringType::Bytes(value) => value,
|
||||
_ => unreachable!("Expected `StringType::Bytes`"),
|
||||
});
|
||||
}
|
||||
Ordering::Greater => unreachable!(),
|
||||
return Expr::from(ast::ExprBytesLiteral {
|
||||
value: ast::BytesLiteralValue::concatenated(values),
|
||||
range,
|
||||
node_index: AtomicNodeIndex::dummy(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if has_tstring {
|
||||
if tstring_count < strings.len() {
|
||||
self.add_error(
|
||||
ParseErrorType::OtherError(
|
||||
"cannot mix t-string literals with string or bytes literals".to_string(),
|
||||
),
|
||||
range,
|
||||
);
|
||||
}
|
||||
// Only construct a t-string expression if all the literals are t-strings
|
||||
// otherwise, we'll try either string or f-string. This is to retain
|
||||
// as much information as possible.
|
||||
else {
|
||||
let mut values = Vec::with_capacity(strings.len());
|
||||
for string in strings {
|
||||
values.push(match string {
|
||||
StringType::TString(value) => value,
|
||||
_ => unreachable!("Expected `StringType::TString`"),
|
||||
});
|
||||
}
|
||||
return Expr::from(ast::ExprTString {
|
||||
value: ast::TStringValue::concatenated(values),
|
||||
range,
|
||||
node_index: AtomicNodeIndex::dummy(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1414,36 +1437,17 @@ impl<'src> Parser<'src> {
|
||||
});
|
||||
}
|
||||
|
||||
if has_tstring {
|
||||
let mut parts = Vec::with_capacity(strings.len());
|
||||
for string in strings {
|
||||
match string {
|
||||
StringType::TString(tstring) => parts.push(ast::TStringPart::TString(tstring)),
|
||||
StringType::FString(fstring) => {
|
||||
parts.push(ruff_python_ast::TStringPart::FString(fstring));
|
||||
}
|
||||
StringType::Str(string) => parts.push(ast::TStringPart::Literal(string)),
|
||||
StringType::Bytes(bytes) => parts.push(ast::TStringPart::Literal(
|
||||
ast::StringLiteral::invalid(bytes.range()),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
return Expr::from(ast::ExprTString {
|
||||
value: ast::TStringValue::concatenated(parts),
|
||||
range,
|
||||
node_index: AtomicNodeIndex::dummy(),
|
||||
});
|
||||
}
|
||||
|
||||
let mut parts = Vec::with_capacity(strings.len());
|
||||
for string in strings {
|
||||
match string {
|
||||
StringType::FString(fstring) => parts.push(ast::FStringPart::FString(fstring)),
|
||||
StringType::TString(_) => {
|
||||
unreachable!("expected no tstring parts by this point")
|
||||
}
|
||||
StringType::Str(string) => parts.push(ast::FStringPart::Literal(string)),
|
||||
// Bytes and Template strings are invalid at this point
|
||||
// and stored as invalid string literal parts in the
|
||||
// f-string
|
||||
StringType::TString(tstring) => parts.push(ast::FStringPart::Literal(
|
||||
ast::StringLiteral::invalid(tstring.range()),
|
||||
)),
|
||||
StringType::Bytes(bytes) => parts.push(ast::FStringPart::Literal(
|
||||
ast::StringLiteral::invalid(bytes.range()),
|
||||
)),
|
||||
|
||||
@@ -13,18 +13,16 @@ expression: suite
|
||||
range: 0..3,
|
||||
value: TStringValue {
|
||||
inner: Single(
|
||||
TString(
|
||||
TString {
|
||||
range: 0..3,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
TString {
|
||||
range: 0..3,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
---
|
||||
source: crates/ruff_python_parser/src/string.rs
|
||||
expression: suite
|
||||
---
|
||||
[
|
||||
Expr(
|
||||
StmtExpr {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 0..18,
|
||||
value: TString(
|
||||
ExprTString {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 0..18,
|
||||
value: TStringValue {
|
||||
inner: Concatenated(
|
||||
[
|
||||
FString(
|
||||
FString {
|
||||
range: 0..9,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Literal(
|
||||
InterpolatedStringLiteralElement {
|
||||
range: 2..8,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "Hello ",
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: FStringFlags {
|
||||
quote_style: Single,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
},
|
||||
),
|
||||
TString(
|
||||
TString {
|
||||
range: 10..18,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Literal(
|
||||
InterpolatedStringLiteralElement {
|
||||
range: 12..17,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "world",
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Single,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
},
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
source: crates/ruff_python_parser/src/string.rs
|
||||
expression: suite
|
||||
---
|
||||
ParseError {
|
||||
error: OtherError(
|
||||
"cannot mix t-string literals with string or bytes literals",
|
||||
),
|
||||
location: 0..18,
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
---
|
||||
source: crates/ruff_python_parser/src/string.rs
|
||||
expression: suite
|
||||
---
|
||||
[
|
||||
Expr(
|
||||
StmtExpr {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 0..22,
|
||||
value: TString(
|
||||
ExprTString {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 0..22,
|
||||
value: TStringValue {
|
||||
inner: Concatenated(
|
||||
[
|
||||
FString(
|
||||
FString {
|
||||
range: 0..9,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Literal(
|
||||
InterpolatedStringLiteralElement {
|
||||
range: 2..8,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "Hello ",
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: FStringFlags {
|
||||
quote_style: Single,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
},
|
||||
),
|
||||
TString(
|
||||
TString {
|
||||
range: 10..18,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Literal(
|
||||
InterpolatedStringLiteralElement {
|
||||
range: 12..17,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "world",
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Single,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
},
|
||||
),
|
||||
Literal(
|
||||
StringLiteral {
|
||||
range: 19..22,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "!",
|
||||
flags: StringLiteralFlags {
|
||||
quote_style: Single,
|
||||
prefix: Empty,
|
||||
triple_quoted: false,
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
},
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
source: crates/ruff_python_parser/src/string.rs
|
||||
expression: suite
|
||||
---
|
||||
ParseError {
|
||||
error: OtherError(
|
||||
"cannot mix t-string literals with string or bytes literals",
|
||||
),
|
||||
location: 0..22,
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
---
|
||||
source: crates/ruff_python_parser/src/string.rs
|
||||
expression: suite
|
||||
---
|
||||
[
|
||||
Expr(
|
||||
StmtExpr {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 0..17,
|
||||
value: TString(
|
||||
ExprTString {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 0..17,
|
||||
value: TStringValue {
|
||||
inner: Concatenated(
|
||||
[
|
||||
Literal(
|
||||
StringLiteral {
|
||||
range: 0..8,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "Hello ",
|
||||
flags: StringLiteralFlags {
|
||||
quote_style: Single,
|
||||
prefix: Empty,
|
||||
triple_quoted: false,
|
||||
},
|
||||
},
|
||||
),
|
||||
TString(
|
||||
TString {
|
||||
range: 9..17,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Literal(
|
||||
InterpolatedStringLiteralElement {
|
||||
range: 11..16,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "world",
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Single,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
},
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
source: crates/ruff_python_parser/src/string.rs
|
||||
expression: suite
|
||||
---
|
||||
ParseError {
|
||||
error: OtherError(
|
||||
"cannot mix t-string literals with string or bytes literals",
|
||||
),
|
||||
location: 0..17,
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
---
|
||||
source: crates/ruff_python_parser/src/string.rs
|
||||
expression: suite
|
||||
---
|
||||
[
|
||||
Expr(
|
||||
StmtExpr {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 0..17,
|
||||
value: TString(
|
||||
ExprTString {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 0..17,
|
||||
value: TStringValue {
|
||||
inner: Concatenated(
|
||||
[
|
||||
Literal(
|
||||
StringLiteral {
|
||||
range: 0..8,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "Hello ",
|
||||
flags: StringLiteralFlags {
|
||||
quote_style: Single,
|
||||
prefix: Empty,
|
||||
triple_quoted: false,
|
||||
},
|
||||
},
|
||||
),
|
||||
TString(
|
||||
TString {
|
||||
range: 9..17,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Literal(
|
||||
InterpolatedStringLiteralElement {
|
||||
range: 11..16,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "world",
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Single,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
},
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
source: crates/ruff_python_parser/src/string.rs
|
||||
expression: suite
|
||||
---
|
||||
ParseError {
|
||||
error: OtherError(
|
||||
"cannot mix t-string literals with string or bytes literals",
|
||||
),
|
||||
location: 0..17,
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
---
|
||||
source: crates/ruff_python_parser/src/string.rs
|
||||
expression: suite
|
||||
---
|
||||
[
|
||||
Expr(
|
||||
StmtExpr {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 0..22,
|
||||
value: TString(
|
||||
ExprTString {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 0..22,
|
||||
value: TStringValue {
|
||||
inner: Concatenated(
|
||||
[
|
||||
Literal(
|
||||
StringLiteral {
|
||||
range: 0..8,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "Hello ",
|
||||
flags: StringLiteralFlags {
|
||||
quote_style: Single,
|
||||
prefix: Empty,
|
||||
triple_quoted: false,
|
||||
},
|
||||
},
|
||||
),
|
||||
TString(
|
||||
TString {
|
||||
range: 9..22,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Literal(
|
||||
InterpolatedStringLiteralElement {
|
||||
range: 11..16,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "world",
|
||||
},
|
||||
),
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 16..21,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: StringLiteral(
|
||||
ExprStringLiteral {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 17..20,
|
||||
value: StringLiteralValue {
|
||||
inner: Single(
|
||||
StringLiteral {
|
||||
range: 17..20,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "!",
|
||||
flags: StringLiteralFlags {
|
||||
quote_style: Double,
|
||||
prefix: Empty,
|
||||
triple_quoted: false,
|
||||
},
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Single,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
},
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
source: crates/ruff_python_parser/src/string.rs
|
||||
expression: suite
|
||||
---
|
||||
ParseError {
|
||||
error: OtherError(
|
||||
"cannot mix t-string literals with string or bytes literals",
|
||||
),
|
||||
location: 0..22,
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
---
|
||||
source: crates/ruff_python_parser/src/string.rs
|
||||
expression: suite
|
||||
---
|
||||
[
|
||||
Expr(
|
||||
StmtExpr {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 0..31,
|
||||
value: TString(
|
||||
ExprTString {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 0..31,
|
||||
value: TStringValue {
|
||||
inner: Concatenated(
|
||||
[
|
||||
Literal(
|
||||
StringLiteral {
|
||||
range: 0..8,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "Hello ",
|
||||
flags: StringLiteralFlags {
|
||||
quote_style: Single,
|
||||
prefix: Empty,
|
||||
triple_quoted: false,
|
||||
},
|
||||
},
|
||||
),
|
||||
TString(
|
||||
TString {
|
||||
range: 9..22,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Literal(
|
||||
InterpolatedStringLiteralElement {
|
||||
range: 11..16,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "world",
|
||||
},
|
||||
),
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 16..21,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: StringLiteral(
|
||||
ExprStringLiteral {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 17..20,
|
||||
value: StringLiteralValue {
|
||||
inner: Single(
|
||||
StringLiteral {
|
||||
range: 17..20,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "!",
|
||||
flags: StringLiteralFlags {
|
||||
quote_style: Double,
|
||||
prefix: Empty,
|
||||
triple_quoted: false,
|
||||
},
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Single,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
},
|
||||
),
|
||||
Literal(
|
||||
StringLiteral {
|
||||
range: 23..31,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "again!",
|
||||
flags: StringLiteralFlags {
|
||||
quote_style: Single,
|
||||
prefix: Empty,
|
||||
triple_quoted: false,
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
},
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
source: crates/ruff_python_parser/src/string.rs
|
||||
expression: suite
|
||||
---
|
||||
ParseError {
|
||||
error: OtherError(
|
||||
"cannot mix t-string literals with string or bytes literals",
|
||||
),
|
||||
location: 0..31,
|
||||
}
|
||||
@@ -13,60 +13,58 @@ expression: suite
|
||||
range: 0..18,
|
||||
value: TStringValue {
|
||||
inner: Single(
|
||||
TString(
|
||||
TString {
|
||||
range: 0..18,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 2..5,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 3..4,
|
||||
id: Name("a"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 5..10,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 7..8,
|
||||
id: Name("b"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
Literal(
|
||||
InterpolatedStringLiteralElement {
|
||||
range: 10..17,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "{foo}",
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
TString {
|
||||
range: 0..18,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 2..5,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 3..4,
|
||||
id: Name("a"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 5..10,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 7..8,
|
||||
id: Name("b"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
Literal(
|
||||
InterpolatedStringLiteralElement {
|
||||
range: 10..17,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "{foo}",
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
|
||||
@@ -13,57 +13,55 @@ expression: suite
|
||||
range: 0..13,
|
||||
value: TStringValue {
|
||||
inner: Single(
|
||||
TString(
|
||||
TString {
|
||||
range: 0..13,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 2..12,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Compare(
|
||||
ExprCompare {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 3..11,
|
||||
left: NumberLiteral(
|
||||
TString {
|
||||
range: 0..13,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 2..12,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Compare(
|
||||
ExprCompare {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 3..11,
|
||||
left: NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 3..5,
|
||||
value: Int(
|
||||
42,
|
||||
),
|
||||
},
|
||||
),
|
||||
ops: [
|
||||
Eq,
|
||||
],
|
||||
comparators: [
|
||||
NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 3..5,
|
||||
range: 9..11,
|
||||
value: Int(
|
||||
42,
|
||||
),
|
||||
},
|
||||
),
|
||||
ops: [
|
||||
Eq,
|
||||
],
|
||||
comparators: [
|
||||
NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 9..11,
|
||||
value: Int(
|
||||
42,
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
|
||||
@@ -13,87 +13,85 @@ expression: suite
|
||||
range: 0..16,
|
||||
value: TStringValue {
|
||||
inner: Single(
|
||||
TString(
|
||||
TString {
|
||||
range: 0..16,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 2..15,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 3..6,
|
||||
id: Name("foo"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: Some(
|
||||
InterpolatedStringFormatSpec {
|
||||
range: 7..14,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 7..14,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: StringLiteral(
|
||||
ExprStringLiteral {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 8..13,
|
||||
value: StringLiteralValue {
|
||||
inner: Concatenated(
|
||||
ConcatenatedStringLiteral {
|
||||
strings: [
|
||||
StringLiteral {
|
||||
range: 8..10,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "",
|
||||
flags: StringLiteralFlags {
|
||||
quote_style: Single,
|
||||
prefix: Empty,
|
||||
triple_quoted: false,
|
||||
},
|
||||
TString {
|
||||
range: 0..16,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 2..15,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 3..6,
|
||||
id: Name("foo"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: Some(
|
||||
InterpolatedStringFormatSpec {
|
||||
range: 7..14,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 7..14,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: StringLiteral(
|
||||
ExprStringLiteral {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 8..13,
|
||||
value: StringLiteralValue {
|
||||
inner: Concatenated(
|
||||
ConcatenatedStringLiteral {
|
||||
strings: [
|
||||
StringLiteral {
|
||||
range: 8..10,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "",
|
||||
flags: StringLiteralFlags {
|
||||
quote_style: Single,
|
||||
prefix: Empty,
|
||||
triple_quoted: false,
|
||||
},
|
||||
StringLiteral {
|
||||
range: 11..13,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "",
|
||||
flags: StringLiteralFlags {
|
||||
quote_style: Single,
|
||||
prefix: Empty,
|
||||
triple_quoted: false,
|
||||
},
|
||||
},
|
||||
StringLiteral {
|
||||
range: 11..13,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "",
|
||||
flags: StringLiteralFlags {
|
||||
quote_style: Single,
|
||||
prefix: Empty,
|
||||
triple_quoted: false,
|
||||
},
|
||||
],
|
||||
value: "",
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
],
|
||||
value: "",
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
|
||||
@@ -13,60 +13,58 @@ expression: suite
|
||||
range: 0..15,
|
||||
value: TStringValue {
|
||||
inner: Single(
|
||||
TString(
|
||||
TString {
|
||||
range: 0..15,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 2..14,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 3..6,
|
||||
id: Name("foo"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: Some(
|
||||
InterpolatedStringFormatSpec {
|
||||
range: 7..13,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 7..13,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 8..12,
|
||||
id: Name("spec"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
TString {
|
||||
range: 0..15,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 2..14,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 3..6,
|
||||
id: Name("foo"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: Some(
|
||||
InterpolatedStringFormatSpec {
|
||||
range: 7..13,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 7..13,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 8..12,
|
||||
id: Name("spec"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
|
||||
@@ -13,72 +13,70 @@ expression: suite
|
||||
range: 0..13,
|
||||
value: TStringValue {
|
||||
inner: Single(
|
||||
TString(
|
||||
TString {
|
||||
range: 0..13,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 2..12,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 3..6,
|
||||
id: Name("foo"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: Some(
|
||||
InterpolatedStringFormatSpec {
|
||||
range: 7..11,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 7..11,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: StringLiteral(
|
||||
ExprStringLiteral {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 8..10,
|
||||
value: StringLiteralValue {
|
||||
inner: Single(
|
||||
StringLiteral {
|
||||
range: 8..10,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "",
|
||||
flags: StringLiteralFlags {
|
||||
quote_style: Single,
|
||||
prefix: Empty,
|
||||
triple_quoted: false,
|
||||
},
|
||||
TString {
|
||||
range: 0..13,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 2..12,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 3..6,
|
||||
id: Name("foo"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: Some(
|
||||
InterpolatedStringFormatSpec {
|
||||
range: 7..11,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 7..11,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: StringLiteral(
|
||||
ExprStringLiteral {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 8..10,
|
||||
value: StringLiteralValue {
|
||||
inner: Single(
|
||||
StringLiteral {
|
||||
range: 8..10,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "",
|
||||
flags: StringLiteralFlags {
|
||||
quote_style: Single,
|
||||
prefix: Empty,
|
||||
triple_quoted: false,
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
|
||||
@@ -13,57 +13,55 @@ expression: suite
|
||||
range: 0..11,
|
||||
value: TStringValue {
|
||||
inner: Single(
|
||||
TString(
|
||||
TString {
|
||||
range: 0..11,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 2..10,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Compare(
|
||||
ExprCompare {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 3..9,
|
||||
left: NumberLiteral(
|
||||
TString {
|
||||
range: 0..11,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 2..10,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Compare(
|
||||
ExprCompare {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 3..9,
|
||||
left: NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 3..4,
|
||||
value: Int(
|
||||
1,
|
||||
),
|
||||
},
|
||||
),
|
||||
ops: [
|
||||
NotEq,
|
||||
],
|
||||
comparators: [
|
||||
NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 3..4,
|
||||
range: 8..9,
|
||||
value: Int(
|
||||
1,
|
||||
2,
|
||||
),
|
||||
},
|
||||
),
|
||||
ops: [
|
||||
NotEq,
|
||||
],
|
||||
comparators: [
|
||||
NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 8..9,
|
||||
value: Int(
|
||||
2,
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
|
||||
@@ -13,50 +13,48 @@ expression: suite
|
||||
range: 0..13,
|
||||
value: TStringValue {
|
||||
inner: Single(
|
||||
TString(
|
||||
TString {
|
||||
range: 0..13,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 2..12,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 3..6,
|
||||
id: Name("foo"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: Some(
|
||||
InterpolatedStringFormatSpec {
|
||||
range: 7..11,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Literal(
|
||||
InterpolatedStringLiteralElement {
|
||||
range: 7..11,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "spec",
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
TString {
|
||||
range: 0..13,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 2..12,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 3..6,
|
||||
id: Name("foo"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: Some(
|
||||
InterpolatedStringFormatSpec {
|
||||
range: 7..11,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Literal(
|
||||
InterpolatedStringLiteralElement {
|
||||
range: 7..11,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "spec",
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
|
||||
@@ -13,41 +13,39 @@ expression: suite
|
||||
range: 0..10,
|
||||
value: TStringValue {
|
||||
inner: Single(
|
||||
TString(
|
||||
TString {
|
||||
range: 0..10,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 2..9,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 3..4,
|
||||
id: Name("x"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: Some(
|
||||
DebugText {
|
||||
leading: "",
|
||||
trailing: " =",
|
||||
},
|
||||
),
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
TString {
|
||||
range: 0..10,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 2..9,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 3..4,
|
||||
id: Name("x"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: Some(
|
||||
DebugText {
|
||||
leading: "",
|
||||
trailing: " =",
|
||||
},
|
||||
),
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
|
||||
@@ -13,41 +13,39 @@ expression: suite
|
||||
range: 0..10,
|
||||
value: TStringValue {
|
||||
inner: Single(
|
||||
TString(
|
||||
TString {
|
||||
range: 0..10,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 2..9,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 3..4,
|
||||
id: Name("x"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: Some(
|
||||
DebugText {
|
||||
leading: "",
|
||||
trailing: "= ",
|
||||
},
|
||||
),
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
TString {
|
||||
range: 0..10,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 2..9,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 3..4,
|
||||
id: Name("x"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: Some(
|
||||
DebugText {
|
||||
leading: "",
|
||||
trailing: "= ",
|
||||
},
|
||||
),
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
|
||||
@@ -13,35 +13,33 @@ expression: suite
|
||||
range: 0..10,
|
||||
value: TStringValue {
|
||||
inner: Single(
|
||||
TString(
|
||||
TString {
|
||||
range: 0..10,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 2..9,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Yield(
|
||||
ExprYield {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 3..8,
|
||||
value: None,
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
TString {
|
||||
range: 0..10,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 2..9,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Yield(
|
||||
ExprYield {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 3..8,
|
||||
value: None,
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
---
|
||||
source: crates/ruff_python_parser/src/string.rs
|
||||
expression: suite
|
||||
---
|
||||
[
|
||||
Expr(
|
||||
StmtExpr {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 0..18,
|
||||
value: TString(
|
||||
ExprTString {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 0..18,
|
||||
value: TStringValue {
|
||||
inner: Concatenated(
|
||||
[
|
||||
Literal(
|
||||
StringLiteral {
|
||||
range: 0..9,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "Hello ",
|
||||
flags: StringLiteralFlags {
|
||||
quote_style: Single,
|
||||
prefix: Unicode,
|
||||
triple_quoted: false,
|
||||
},
|
||||
},
|
||||
),
|
||||
TString(
|
||||
TString {
|
||||
range: 10..18,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Literal(
|
||||
InterpolatedStringLiteralElement {
|
||||
range: 12..17,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "world",
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Single,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
},
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
source: crates/ruff_python_parser/src/string.rs
|
||||
expression: suite
|
||||
---
|
||||
ParseError {
|
||||
error: OtherError(
|
||||
"cannot mix t-string literals with string or bytes literals",
|
||||
),
|
||||
location: 0..18,
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
---
|
||||
source: crates/ruff_python_parser/src/string.rs
|
||||
expression: suite
|
||||
---
|
||||
[
|
||||
Expr(
|
||||
StmtExpr {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 0..22,
|
||||
value: TString(
|
||||
ExprTString {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 0..22,
|
||||
value: TStringValue {
|
||||
inner: Concatenated(
|
||||
[
|
||||
Literal(
|
||||
StringLiteral {
|
||||
range: 0..9,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "Hello ",
|
||||
flags: StringLiteralFlags {
|
||||
quote_style: Single,
|
||||
prefix: Unicode,
|
||||
triple_quoted: false,
|
||||
},
|
||||
},
|
||||
),
|
||||
TString(
|
||||
TString {
|
||||
range: 10..18,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Literal(
|
||||
InterpolatedStringLiteralElement {
|
||||
range: 12..17,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "world",
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Single,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
},
|
||||
),
|
||||
Literal(
|
||||
StringLiteral {
|
||||
range: 19..22,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "!",
|
||||
flags: StringLiteralFlags {
|
||||
quote_style: Single,
|
||||
prefix: Empty,
|
||||
triple_quoted: false,
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
},
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
source: crates/ruff_python_parser/src/string.rs
|
||||
expression: suite
|
||||
---
|
||||
ParseError {
|
||||
error: OtherError(
|
||||
"cannot mix t-string literals with string or bytes literals",
|
||||
),
|
||||
location: 0..22,
|
||||
}
|
||||
@@ -13,38 +13,36 @@ expression: suite
|
||||
range: 0..7,
|
||||
value: TStringValue {
|
||||
inner: Single(
|
||||
TString(
|
||||
TString {
|
||||
range: 0..7,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 3..6,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 4..5,
|
||||
id: Name("x"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Raw {
|
||||
uppercase_r: false,
|
||||
TString {
|
||||
range: 0..7,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 3..6,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 4..5,
|
||||
id: Name("x"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
triple_quoted: false,
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Raw {
|
||||
uppercase_r: false,
|
||||
},
|
||||
triple_quoted: false,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
|
||||
@@ -13,38 +13,36 @@ expression: suite
|
||||
range: 0..11,
|
||||
value: TStringValue {
|
||||
inner: Single(
|
||||
TString(
|
||||
TString {
|
||||
range: 0..11,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 5..8,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 6..7,
|
||||
id: Name("x"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Raw {
|
||||
uppercase_r: false,
|
||||
TString {
|
||||
range: 0..11,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 5..8,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 6..7,
|
||||
id: Name("x"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
triple_quoted: true,
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Raw {
|
||||
uppercase_r: false,
|
||||
},
|
||||
triple_quoted: true,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
|
||||
@@ -13,74 +13,72 @@ expression: suite
|
||||
range: 0..22,
|
||||
value: TStringValue {
|
||||
inner: Single(
|
||||
TString(
|
||||
TString {
|
||||
range: 0..22,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Literal(
|
||||
InterpolatedStringLiteralElement {
|
||||
range: 2..5,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "aaa",
|
||||
},
|
||||
),
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 5..10,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 6..9,
|
||||
id: Name("bbb"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
Literal(
|
||||
InterpolatedStringLiteralElement {
|
||||
range: 10..13,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "ccc",
|
||||
},
|
||||
),
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 13..18,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 14..17,
|
||||
id: Name("ddd"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
Literal(
|
||||
InterpolatedStringLiteralElement {
|
||||
range: 18..21,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "eee",
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
TString {
|
||||
range: 0..22,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Literal(
|
||||
InterpolatedStringLiteralElement {
|
||||
range: 2..5,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "aaa",
|
||||
},
|
||||
),
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 5..10,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 6..9,
|
||||
id: Name("bbb"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
Literal(
|
||||
InterpolatedStringLiteralElement {
|
||||
range: 10..13,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "ccc",
|
||||
},
|
||||
),
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 13..18,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 14..17,
|
||||
id: Name("ddd"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
Literal(
|
||||
InterpolatedStringLiteralElement {
|
||||
range: 18..21,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "eee",
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
|
||||
@@ -13,43 +13,41 @@ expression: suite
|
||||
range: 0..8,
|
||||
value: TStringValue {
|
||||
inner: Single(
|
||||
TString(
|
||||
TString {
|
||||
range: 0..8,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Literal(
|
||||
InterpolatedStringLiteralElement {
|
||||
range: 2..4,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "\\",
|
||||
},
|
||||
),
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 4..7,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 5..6,
|
||||
id: Name("x"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
TString {
|
||||
range: 0..8,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Literal(
|
||||
InterpolatedStringLiteralElement {
|
||||
range: 2..4,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "\\",
|
||||
},
|
||||
),
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 4..7,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 5..6,
|
||||
id: Name("x"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
|
||||
@@ -13,43 +13,41 @@ expression: suite
|
||||
range: 0..8,
|
||||
value: TStringValue {
|
||||
inner: Single(
|
||||
TString(
|
||||
TString {
|
||||
range: 0..8,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Literal(
|
||||
InterpolatedStringLiteralElement {
|
||||
range: 2..4,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "\n",
|
||||
},
|
||||
),
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 4..7,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 5..6,
|
||||
id: Name("x"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
TString {
|
||||
range: 0..8,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Literal(
|
||||
InterpolatedStringLiteralElement {
|
||||
range: 2..4,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "\n",
|
||||
},
|
||||
),
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 4..7,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 5..6,
|
||||
id: Name("x"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
|
||||
@@ -13,45 +13,43 @@ expression: suite
|
||||
range: 0..9,
|
||||
value: TStringValue {
|
||||
inner: Single(
|
||||
TString(
|
||||
TString {
|
||||
range: 0..9,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Literal(
|
||||
InterpolatedStringLiteralElement {
|
||||
range: 3..5,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "\\\n",
|
||||
},
|
||||
),
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 5..8,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 6..7,
|
||||
id: Name("x"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Raw {
|
||||
uppercase_r: false,
|
||||
TString {
|
||||
range: 0..9,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Literal(
|
||||
InterpolatedStringLiteralElement {
|
||||
range: 3..5,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "\\\n",
|
||||
},
|
||||
triple_quoted: false,
|
||||
),
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 5..8,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 6..7,
|
||||
id: Name("x"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Raw {
|
||||
uppercase_r: false,
|
||||
},
|
||||
triple_quoted: false,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
|
||||
@@ -13,41 +13,39 @@ expression: suite
|
||||
range: 0..10,
|
||||
value: TStringValue {
|
||||
inner: Single(
|
||||
TString(
|
||||
TString {
|
||||
range: 0..10,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 2..9,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 3..7,
|
||||
id: Name("user"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: Some(
|
||||
DebugText {
|
||||
leading: "",
|
||||
trailing: "=",
|
||||
},
|
||||
),
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
TString {
|
||||
range: 0..10,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 2..9,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 3..7,
|
||||
id: Name("user"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: Some(
|
||||
DebugText {
|
||||
leading: "",
|
||||
trailing: "=",
|
||||
},
|
||||
),
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
|
||||
@@ -13,77 +13,75 @@ expression: suite
|
||||
range: 0..38,
|
||||
value: TStringValue {
|
||||
inner: Single(
|
||||
TString(
|
||||
TString {
|
||||
range: 0..38,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Literal(
|
||||
InterpolatedStringLiteralElement {
|
||||
range: 2..6,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "mix ",
|
||||
},
|
||||
),
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 6..13,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 7..11,
|
||||
id: Name("user"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: Some(
|
||||
DebugText {
|
||||
leading: "",
|
||||
trailing: "=",
|
||||
},
|
||||
),
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
Literal(
|
||||
InterpolatedStringLiteralElement {
|
||||
range: 13..28,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: " with text and ",
|
||||
},
|
||||
),
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 28..37,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 29..35,
|
||||
id: Name("second"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: Some(
|
||||
DebugText {
|
||||
leading: "",
|
||||
trailing: "=",
|
||||
},
|
||||
),
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
TString {
|
||||
range: 0..38,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Literal(
|
||||
InterpolatedStringLiteralElement {
|
||||
range: 2..6,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "mix ",
|
||||
},
|
||||
),
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 6..13,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 7..11,
|
||||
id: Name("user"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: Some(
|
||||
DebugText {
|
||||
leading: "",
|
||||
trailing: "=",
|
||||
},
|
||||
),
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
Literal(
|
||||
InterpolatedStringLiteralElement {
|
||||
range: 13..28,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: " with text and ",
|
||||
},
|
||||
),
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 28..37,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 29..35,
|
||||
id: Name("second"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: Some(
|
||||
DebugText {
|
||||
leading: "",
|
||||
trailing: "=",
|
||||
},
|
||||
),
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
|
||||
@@ -13,55 +13,53 @@ expression: suite
|
||||
range: 0..14,
|
||||
value: TStringValue {
|
||||
inner: Single(
|
||||
TString(
|
||||
TString {
|
||||
range: 0..14,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 2..13,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 3..7,
|
||||
id: Name("user"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: Some(
|
||||
DebugText {
|
||||
leading: "",
|
||||
trailing: "=",
|
||||
},
|
||||
),
|
||||
conversion: None,
|
||||
format_spec: Some(
|
||||
InterpolatedStringFormatSpec {
|
||||
range: 9..12,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Literal(
|
||||
InterpolatedStringLiteralElement {
|
||||
range: 9..12,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: ">10",
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
TString {
|
||||
range: 0..14,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 2..13,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 3..7,
|
||||
id: Name("user"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: Some(
|
||||
DebugText {
|
||||
leading: "",
|
||||
trailing: "=",
|
||||
},
|
||||
),
|
||||
conversion: None,
|
||||
format_spec: Some(
|
||||
InterpolatedStringFormatSpec {
|
||||
range: 9..12,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Literal(
|
||||
InterpolatedStringLiteralElement {
|
||||
range: 9..12,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: ">10",
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
|
||||
@@ -13,43 +13,41 @@ expression: suite
|
||||
range: 0..11,
|
||||
value: TStringValue {
|
||||
inner: Single(
|
||||
TString(
|
||||
TString {
|
||||
range: 0..11,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Literal(
|
||||
InterpolatedStringLiteralElement {
|
||||
range: 4..5,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "\n",
|
||||
},
|
||||
),
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 5..8,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 6..7,
|
||||
id: Name("x"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: true,
|
||||
},
|
||||
TString {
|
||||
range: 0..11,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Literal(
|
||||
InterpolatedStringLiteralElement {
|
||||
range: 4..5,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
value: "\n",
|
||||
},
|
||||
),
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 5..8,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 6..7,
|
||||
id: Name("x"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: true,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
|
||||
@@ -850,58 +850,58 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_t_string_concat_1() {
|
||||
fn test_parse_t_string_concat_1_error() {
|
||||
let source = "'Hello ' t'world'";
|
||||
let suite = parse_suite(source).unwrap();
|
||||
let suite = parse_suite(source).unwrap_err();
|
||||
insta::assert_debug_snapshot!(suite);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_t_string_concat_2() {
|
||||
fn test_parse_t_string_concat_2_error() {
|
||||
let source = "'Hello ' t'world'";
|
||||
let suite = parse_suite(source).unwrap();
|
||||
let suite = parse_suite(source).unwrap_err();
|
||||
insta::assert_debug_snapshot!(suite);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_t_string_concat_3() {
|
||||
fn test_parse_t_string_concat_3_error() {
|
||||
let source = "'Hello ' t'world{\"!\"}'";
|
||||
let suite = parse_suite(source).unwrap();
|
||||
let suite = parse_suite(source).unwrap_err();
|
||||
insta::assert_debug_snapshot!(suite);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_t_string_concat_4() {
|
||||
fn test_parse_t_string_concat_4_error() {
|
||||
let source = "'Hello ' t'world{\"!\"}' 'again!'";
|
||||
let suite = parse_suite(source).unwrap();
|
||||
let suite = parse_suite(source).unwrap_err();
|
||||
insta::assert_debug_snapshot!(suite);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_u_t_string_concat_1() {
|
||||
fn test_parse_u_t_string_concat_1_error() {
|
||||
let source = "u'Hello ' t'world'";
|
||||
let suite = parse_suite(source).unwrap();
|
||||
let suite = parse_suite(source).unwrap_err();
|
||||
insta::assert_debug_snapshot!(suite);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_u_t_string_concat_2() {
|
||||
fn test_parse_u_t_string_concat_2_error() {
|
||||
let source = "u'Hello ' t'world' '!'";
|
||||
let suite = parse_suite(source).unwrap();
|
||||
let suite = parse_suite(source).unwrap_err();
|
||||
insta::assert_debug_snapshot!(suite);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_f_t_string_concat_1() {
|
||||
fn test_parse_f_t_string_concat_1_error() {
|
||||
let source = "f'Hello ' t'world'";
|
||||
let suite = parse_suite(source).unwrap();
|
||||
let suite = parse_suite(source).unwrap_err();
|
||||
insta::assert_debug_snapshot!(suite);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_f_t_string_concat_2() {
|
||||
fn test_parse_f_t_string_concat_2_error() {
|
||||
let source = "f'Hello ' t'world' '!'";
|
||||
let suite = parse_suite(source).unwrap();
|
||||
let suite = parse_suite(source).unwrap_err();
|
||||
insta::assert_debug_snapshot!(suite);
|
||||
}
|
||||
|
||||
|
||||
@@ -66,36 +66,34 @@ Module(
|
||||
range: 10..19,
|
||||
value: TStringValue {
|
||||
inner: Single(
|
||||
TString(
|
||||
TString {
|
||||
range: 10..19,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 12..18,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 13..14,
|
||||
id: Name("x"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: Str,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
TString {
|
||||
range: 10..19,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 12..18,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 13..14,
|
||||
id: Name("x"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: Str,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
|
||||
@@ -20,36 +20,34 @@ Module(
|
||||
range: 44..49,
|
||||
value: TStringValue {
|
||||
inner: Single(
|
||||
TString(
|
||||
TString {
|
||||
range: 44..49,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 46..48,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 47..47,
|
||||
id: Name(""),
|
||||
ctx: Invalid,
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
TString {
|
||||
range: 44..49,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 46..48,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 47..47,
|
||||
id: Name(""),
|
||||
ctx: Invalid,
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
@@ -66,36 +64,34 @@ Module(
|
||||
range: 50..57,
|
||||
value: TStringValue {
|
||||
inner: Single(
|
||||
TString(
|
||||
TString {
|
||||
range: 50..57,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 52..56,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 53..53,
|
||||
id: Name(""),
|
||||
ctx: Invalid,
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
TString {
|
||||
range: 50..57,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 52..56,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 53..53,
|
||||
id: Name(""),
|
||||
ctx: Invalid,
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
|
||||
@@ -20,36 +20,34 @@ Module(
|
||||
range: 44..52,
|
||||
value: TStringValue {
|
||||
inner: Single(
|
||||
TString(
|
||||
TString {
|
||||
range: 44..52,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 46..51,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 47..48,
|
||||
id: Name("x"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
TString {
|
||||
range: 44..52,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 46..51,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 47..48,
|
||||
id: Name("x"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
|
||||
@@ -20,36 +20,34 @@ Module(
|
||||
range: 44..54,
|
||||
value: TStringValue {
|
||||
inner: Single(
|
||||
TString(
|
||||
TString {
|
||||
range: 44..54,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 46..53,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 47..48,
|
||||
id: Name("x"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
TString {
|
||||
range: 44..54,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 46..53,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 47..48,
|
||||
id: Name("x"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
@@ -66,36 +64,34 @@ Module(
|
||||
range: 55..65,
|
||||
value: TStringValue {
|
||||
inner: Single(
|
||||
TString(
|
||||
TString {
|
||||
range: 55..65,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 57..64,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 58..59,
|
||||
id: Name("x"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
TString {
|
||||
range: 55..65,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 57..64,
|
||||
node_index: AtomicNodeIndex(..),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: AtomicNodeIndex(..),
|
||||
range: 58..59,
|
||||
id: Name("x"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: None,
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: TStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: false,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user