Compare commits
3 Commits
charlie/co
...
poc-of-ass
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d1a76d0011 | ||
|
|
86bc5394f1 | ||
|
|
eea082462c |
@@ -2155,15 +2155,18 @@ impl<Context> std::fmt::Debug for IndentIfGroupBreaks<'_, Context> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Changes the definition of *fits* for `content`. Instead of measuring it in *flat*, measure it with
|
||||
/// all line breaks expanded and test if no line exceeds the line width. The [`FitsExpanded`] acts
|
||||
/// as a expands boundary similar to best fitting, meaning that a [`hard_line_break`] will not cause the parent group to expand.
|
||||
/// Changes the definition of *fits* for `content`. It measures the width of all lines and allows
|
||||
/// the content inside of the [`fits_expanded`] to exceed the configured line width. The content
|
||||
/// coming before and after [`fits_expanded`] must fit into the configured line width.
|
||||
///
|
||||
/// The [`fits_expanded`] acts as a expands boundary similar to best fitting,
|
||||
/// meaning that a [`hard_line_break`] will not cause the parent group to expand.
|
||||
///
|
||||
/// Useful in conjunction with a group with a condition.
|
||||
///
|
||||
/// ## Examples
|
||||
/// The outer group with the binary expression remains *flat* regardless of the array expression
|
||||
/// that spans multiple lines.
|
||||
/// The outer group with the binary expression remains *flat* regardless of the array expression that
|
||||
/// spans multiple lines with items exceeding the configured line width.
|
||||
///
|
||||
/// ```
|
||||
/// # use ruff_formatter::{format, format_args, LineWidth, SimpleFormatOptions, write};
|
||||
@@ -2183,7 +2186,7 @@ impl<Context> std::fmt::Debug for IndentIfGroupBreaks<'_, Context> {
|
||||
/// token("["),
|
||||
/// soft_block_indent(&format_args![
|
||||
/// token("a,"), space(), token("# comment"), expand_parent(), soft_line_break_or_space(),
|
||||
/// token("b")
|
||||
/// token("'A very long string that exceeds the configured line width of 80 characters but the enclosing binary expression still fits.'")
|
||||
/// ]),
|
||||
/// token("]")
|
||||
/// ]))
|
||||
@@ -2194,7 +2197,7 @@ impl<Context> std::fmt::Debug for IndentIfGroupBreaks<'_, Context> {
|
||||
/// let formatted = format!(SimpleFormatContext::default(), [content])?;
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// "a + [\n\ta, # comment\n\tb\n]",
|
||||
/// "a + [\n\ta, # comment\n\t'A very long string that exceeds the configured line width of 80 characters but the enclosing binary expression still fits.'\n]",
|
||||
/// formatted.print()?.as_code()
|
||||
/// );
|
||||
/// # Ok(())
|
||||
|
||||
@@ -11,7 +11,7 @@ use unicode_width::UnicodeWidthChar;
|
||||
|
||||
use crate::format_element::tag::{GroupMode, LabelId, Tag};
|
||||
use crate::source_code::SourceCodeSlice;
|
||||
use crate::{IndentWidth, TagKind};
|
||||
use crate::{GroupId, IndentWidth, TagKind};
|
||||
use ruff_text_size::TextSize;
|
||||
|
||||
/// Language agnostic IR for formatting source code.
|
||||
@@ -34,7 +34,9 @@ pub enum FormatElement {
|
||||
SourcePosition(TextSize),
|
||||
|
||||
/// A ASCII only Token that contains no line breaks or tab characters.
|
||||
Token { text: &'static str },
|
||||
Token {
|
||||
text: &'static str,
|
||||
},
|
||||
|
||||
/// An arbitrary text that can contain tabs, newlines, and unicode characters.
|
||||
Text {
|
||||
@@ -57,6 +59,11 @@ pub enum FormatElement {
|
||||
/// deep cloning the IR when using the `best_fitting!` macro or `if_group_fits_on_line` and `if_group_breaks`.
|
||||
Interned(Interned),
|
||||
|
||||
GroupMode {
|
||||
id: GroupId,
|
||||
mode: PrintMode,
|
||||
},
|
||||
|
||||
/// A list of different variants representing the same content. The printer picks the best fitting content.
|
||||
/// Line breaks inside of a best fitting don't propagate to parent groups.
|
||||
BestFitting {
|
||||
@@ -97,6 +104,9 @@ impl std::fmt::Debug for FormatElement {
|
||||
.field("variants", variants)
|
||||
.field("mode", &mode)
|
||||
.finish(),
|
||||
FormatElement::GroupMode { id, mode } => {
|
||||
fmt.debug_tuple("GroupMode").field(id).field(mode).finish()
|
||||
}
|
||||
FormatElement::Interned(interned) => fmt.debug_list().entries(&**interned).finish(),
|
||||
FormatElement::Tag(tag) => fmt.debug_tuple("Tag").field(tag).finish(),
|
||||
FormatElement::SourcePosition(position) => {
|
||||
@@ -277,6 +287,7 @@ impl FormatElements for FormatElement {
|
||||
FormatElement::LineSuffixBoundary
|
||||
| FormatElement::Space
|
||||
| FormatElement::Tag(_)
|
||||
| FormatElement::GroupMode { .. }
|
||||
| FormatElement::Token { .. }
|
||||
| FormatElement::SourcePosition(_) => false,
|
||||
}
|
||||
|
||||
@@ -381,6 +381,17 @@ impl Format<IrFormatContext<'_>> for &[FormatElement] {
|
||||
write!(f, [token("])")])?;
|
||||
}
|
||||
|
||||
FormatElement::GroupMode { id, mode } => write!(
|
||||
f,
|
||||
[
|
||||
token("group_mode("),
|
||||
text(&std::format!("{id:?}"), None),
|
||||
token(", "),
|
||||
text(&std::format!("{mode:?}"), None),
|
||||
token(")")
|
||||
]
|
||||
)?,
|
||||
|
||||
FormatElement::Interned(interned) => {
|
||||
let interned_elements = &mut f.context_mut().printed_interned_elements;
|
||||
|
||||
|
||||
@@ -84,11 +84,14 @@ pub enum Tag {
|
||||
StartFitsExpanded(FitsExpanded),
|
||||
EndFitsExpanded,
|
||||
|
||||
/// Marks the start and end of a best-fitting variant.
|
||||
StartBestFittingEntry,
|
||||
EndBestFittingEntry,
|
||||
|
||||
/// Parenthesizes the content but only if adding the parentheses and indenting the content
|
||||
/// makes the content fit in the configured line width.
|
||||
///
|
||||
/// See [`crate::builders::best_fit_parenthesize`] for an in-depth explanation.
|
||||
StartBestFitParenthesize {
|
||||
id: Option<GroupId>,
|
||||
},
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
#![allow(dead_code)]
|
||||
|
||||
use crate::prelude::*;
|
||||
use std::cell::OnceCell;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
@@ -141,6 +141,10 @@ impl<'a> Printer<'a> {
|
||||
// Handled in `Document::propagate_expands()
|
||||
}
|
||||
|
||||
FormatElement::GroupMode { id, mode } => {
|
||||
self.state.group_modes.insert_print_mode(*id, *mode);
|
||||
}
|
||||
|
||||
FormatElement::SourcePosition(position) => {
|
||||
self.state.source_position = *position;
|
||||
self.push_marker();
|
||||
@@ -1183,7 +1187,7 @@ impl<'a, 'print> FitsMeasurer<'a, 'print> {
|
||||
// line break should be printed as regular line break
|
||||
return Ok(Fits::Yes);
|
||||
}
|
||||
MeasureMode::AllLines => {
|
||||
MeasureMode::AllLines | MeasureMode::AllLinesAllowTextOverflow => {
|
||||
// Continue measuring on the next line
|
||||
self.state.line_width = 0;
|
||||
self.state.pending_indent = args.indention();
|
||||
@@ -1219,6 +1223,10 @@ impl<'a, 'print> FitsMeasurer<'a, 'print> {
|
||||
}
|
||||
}
|
||||
|
||||
FormatElement::GroupMode { id, mode } => {
|
||||
self.group_modes_mut().insert_print_mode(*id, *mode);
|
||||
}
|
||||
|
||||
FormatElement::ExpandParent => {
|
||||
if self.must_be_flat {
|
||||
return Ok(Fits::No);
|
||||
@@ -1354,9 +1362,11 @@ impl<'a, 'print> FitsMeasurer<'a, 'print> {
|
||||
}
|
||||
|
||||
FormatElement::Tag(StartLineSuffix { reserved_width }) => {
|
||||
self.state.line_width += reserved_width;
|
||||
if self.state.line_width > self.options().line_width.into() {
|
||||
return Ok(Fits::No);
|
||||
if *reserved_width > 0 {
|
||||
self.state.line_width += reserved_width;
|
||||
if self.state.line_width > self.options().line_width.into() {
|
||||
return Ok(Fits::No);
|
||||
}
|
||||
}
|
||||
self.queue.skip_content(TagKind::LineSuffix);
|
||||
self.state.has_line_suffix = true;
|
||||
@@ -1370,32 +1380,42 @@ impl<'a, 'print> FitsMeasurer<'a, 'print> {
|
||||
condition,
|
||||
propagate_expand,
|
||||
})) => {
|
||||
let condition_met = match condition {
|
||||
Some(condition) => {
|
||||
let group_mode = match condition.group_id {
|
||||
Some(group_id) => self.group_modes().get_print_mode(group_id)?,
|
||||
None => args.mode(),
|
||||
match args.mode() {
|
||||
PrintMode::Expanded => {
|
||||
// As usual, nothing to measure
|
||||
self.stack.push(TagKind::FitsExpanded, args);
|
||||
}
|
||||
PrintMode::Flat => {
|
||||
let condition_met = match condition {
|
||||
Some(condition) => {
|
||||
let group_mode = match condition.group_id {
|
||||
Some(group_id) => {
|
||||
self.group_modes().get_print_mode(group_id)?
|
||||
}
|
||||
None => args.mode(),
|
||||
};
|
||||
|
||||
condition.mode == group_mode
|
||||
}
|
||||
None => true,
|
||||
};
|
||||
|
||||
condition.mode == group_mode
|
||||
}
|
||||
None => true,
|
||||
};
|
||||
if condition_met {
|
||||
// Measure in fully expanded mode and allow overflows
|
||||
self.stack.push(
|
||||
TagKind::FitsExpanded,
|
||||
args.with_measure_mode(MeasureMode::AllLinesAllowTextOverflow)
|
||||
.with_print_mode(PrintMode::Expanded),
|
||||
);
|
||||
} else {
|
||||
if propagate_expand.get() {
|
||||
return Ok(Fits::No);
|
||||
}
|
||||
|
||||
if condition_met {
|
||||
// Measure in fully expanded mode.
|
||||
self.stack.push(
|
||||
TagKind::FitsExpanded,
|
||||
args.with_print_mode(PrintMode::Expanded)
|
||||
.with_measure_mode(MeasureMode::AllLines),
|
||||
);
|
||||
} else {
|
||||
if propagate_expand.get() && args.mode().is_flat() {
|
||||
return Ok(Fits::No);
|
||||
// As usual
|
||||
self.stack.push(TagKind::FitsExpanded, args);
|
||||
}
|
||||
}
|
||||
|
||||
// As usual
|
||||
self.stack.push(TagKind::FitsExpanded, args);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1482,7 +1502,8 @@ impl<'a, 'print> FitsMeasurer<'a, 'print> {
|
||||
}
|
||||
match args.measure_mode() {
|
||||
MeasureMode::FirstLine => return Fits::Yes,
|
||||
MeasureMode::AllLines => {
|
||||
MeasureMode::AllLines
|
||||
| MeasureMode::AllLinesAllowTextOverflow => {
|
||||
self.state.line_width = 0;
|
||||
continue;
|
||||
}
|
||||
@@ -1498,7 +1519,9 @@ impl<'a, 'print> FitsMeasurer<'a, 'print> {
|
||||
}
|
||||
}
|
||||
|
||||
if self.state.line_width > self.options().line_width.into() {
|
||||
if self.state.line_width > self.options().line_width.into()
|
||||
&& !args.measure_mode().allows_text_overflow()
|
||||
{
|
||||
return Fits::No;
|
||||
}
|
||||
|
||||
@@ -1601,6 +1624,17 @@ enum MeasureMode {
|
||||
/// The content only fits if none of the lines exceed the print width. Lines are terminated by either
|
||||
/// a hard line break or a soft line break in [`PrintMode::Expanded`].
|
||||
AllLines,
|
||||
|
||||
/// Measures all lines and allows lines to exceed the configured line width. Useful when it only matters
|
||||
/// whether the content *before* and *after* fits.
|
||||
AllLinesAllowTextOverflow,
|
||||
}
|
||||
|
||||
impl MeasureMode {
|
||||
/// Returns `true` if this mode allows text exceeding the configured line width.
|
||||
const fn allows_text_overflow(self) -> bool {
|
||||
matches!(self, MeasureMode::AllLinesAllowTextOverflow)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BestFittingMode> for MeasureMode {
|
||||
|
||||
@@ -120,7 +120,6 @@ impl SourceMapGeneration {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Default)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub enum LineEnding {
|
||||
|
||||
@@ -394,3 +394,15 @@ z = (
|
||||
# c: and this comment
|
||||
+ a
|
||||
)
|
||||
|
||||
# Test for https://github.com/astral-sh/ruff/issues/7431
|
||||
if True:
|
||||
if True:
|
||||
if True:
|
||||
if True:
|
||||
msg += " " + _(
|
||||
"Since the role is not mentionable, it will be momentarily made mentionable "
|
||||
"when announcing a streamalert. Please make sure I have the correct "
|
||||
"permissions to manage this role, or else members of this role won't receive "
|
||||
"a notification."
|
||||
)
|
||||
|
||||
@@ -94,8 +94,3 @@ def f():
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = (
|
||||
True
|
||||
)
|
||||
|
||||
# Regression test for https://github.com/astral-sh/ruff/issues/7462
|
||||
if grid is not None:
|
||||
rgrid = (rgrid.rio.reproject_match(grid, nodata=fillvalue) # rio.reproject nodata is use to initlialize the destination array
|
||||
.where(~grid.isnull()))
|
||||
|
||||
@@ -153,3 +153,19 @@ def test():
|
||||
key9: value9,
|
||||
}
|
||||
), "Not what we expected and the message is too long to fit in one lineeeeeeeeeeeeeee"
|
||||
|
||||
# Test for https://github.com/astral-sh/ruff/issues/7246
|
||||
assert items == [
|
||||
"a very very very very very very very very very very very very very very very long string",
|
||||
]
|
||||
|
||||
assert package.files == [
|
||||
{
|
||||
"file": "pytest-3.5.0-py2.py3-none-any.whl",
|
||||
"hash": "sha256:6266f87ab64692112e5477eba395cfedda53b1933ccd29478e671e73b420c19c", # noqa: E501
|
||||
},
|
||||
{
|
||||
"file": "pytest-3.5.0.tar.gz",
|
||||
"hash": "sha256:fae491d1874f199537fd5872b5e1f0e74a009b979df9d53d1553fd03da1703e1", # noqa: E501
|
||||
},
|
||||
]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use ruff_formatter::{format_args, write, Argument, Arguments};
|
||||
use ruff_formatter::{format_args, write, Argument, Arguments, GroupId};
|
||||
use ruff_text_size::{Ranged, TextRange, TextSize};
|
||||
|
||||
use crate::context::{NodeLevel, WithNodeLevel};
|
||||
@@ -12,11 +12,28 @@ where
|
||||
{
|
||||
ParenthesizeIfExpands {
|
||||
inner: Argument::new(content),
|
||||
group_id: None,
|
||||
should_expand: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct ParenthesizeIfExpands<'a, 'ast> {
|
||||
inner: Argument<'a, PyFormatContext<'ast>>,
|
||||
group_id: Option<GroupId>,
|
||||
should_expand: bool,
|
||||
}
|
||||
|
||||
impl ParenthesizeIfExpands<'_, '_> {
|
||||
#[must_use]
|
||||
pub(crate) fn should_expand(mut self, expand: bool) -> Self {
|
||||
self.should_expand = expand;
|
||||
self
|
||||
}
|
||||
|
||||
pub(crate) fn with_group_id(mut self, group_id: GroupId) -> Self {
|
||||
self.group_id = Some(group_id);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> Format<PyFormatContext<'ast>> for ParenthesizeIfExpands<'_, 'ast> {
|
||||
@@ -30,7 +47,9 @@ impl<'ast> Format<PyFormatContext<'ast>> for ParenthesizeIfExpands<'_, 'ast> {
|
||||
if_group_breaks(&token("(")),
|
||||
soft_block_indent(&Arguments::from(&self.inner)),
|
||||
if_group_breaks(&token(")")),
|
||||
])]
|
||||
])
|
||||
.with_group_id(self.group_id)
|
||||
.should_expand(self.should_expand)]
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ use ruff_python_ast::{Constant, Expr, ExpressionRef, Operator};
|
||||
use ruff_python_trivia::CommentRanges;
|
||||
|
||||
use crate::builders::parenthesize_if_expands;
|
||||
use crate::comments::leading_comments;
|
||||
use crate::comments::{leading_comments, LeadingDanglingTrailingComments};
|
||||
use crate::context::{NodeLevel, WithNodeLevel};
|
||||
use crate::expression::parentheses::{
|
||||
is_expression_parenthesized, optional_parentheses, parenthesized, NeedsParentheses,
|
||||
@@ -179,6 +179,45 @@ pub(crate) struct MaybeParenthesizeExpression<'a> {
|
||||
parenthesize: Parenthesize,
|
||||
}
|
||||
|
||||
impl MaybeParenthesizeExpression<'_> {
|
||||
pub(crate) fn needs_parentheses(
|
||||
&self,
|
||||
context: &PyFormatContext,
|
||||
node_comments: &LeadingDanglingTrailingComments,
|
||||
) -> OptionalParentheses {
|
||||
let MaybeParenthesizeExpression {
|
||||
expression,
|
||||
parent,
|
||||
parenthesize,
|
||||
} = self;
|
||||
|
||||
let preserve_parentheses = parenthesize.is_optional()
|
||||
&& is_expression_parenthesized(
|
||||
(*expression).into(),
|
||||
context.comments().ranges(),
|
||||
context.source(),
|
||||
);
|
||||
|
||||
let has_comments = node_comments.has_leading() || node_comments.has_trailing_own_line();
|
||||
|
||||
// If the expression has comments, we always want to preserve the parentheses. This also
|
||||
// ensures that we correctly handle parenthesized comments, and don't need to worry about
|
||||
// them in the implementation below.
|
||||
if preserve_parentheses || has_comments {
|
||||
OptionalParentheses::Always
|
||||
} else {
|
||||
match expression.needs_parentheses(*parent, context) {
|
||||
OptionalParentheses::Always => OptionalParentheses::Always,
|
||||
// The reason to add parentheses is to avoid a syntax error when breaking an expression over multiple lines.
|
||||
// Therefore, it is unnecessary to add an additional pair of parentheses if an outer expression
|
||||
// is parenthesized.
|
||||
_ if context.node_level().is_parenthesized() => OptionalParentheses::Never,
|
||||
needs_parentheses => needs_parentheses,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Format<PyFormatContext<'_>> for MaybeParenthesizeExpression<'_> {
|
||||
fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> {
|
||||
let MaybeParenthesizeExpression {
|
||||
@@ -188,34 +227,9 @@ impl Format<PyFormatContext<'_>> for MaybeParenthesizeExpression<'_> {
|
||||
} = self;
|
||||
|
||||
let comments = f.context().comments();
|
||||
let preserve_parentheses = parenthesize.is_optional()
|
||||
&& is_expression_parenthesized(
|
||||
(*expression).into(),
|
||||
f.context().comments().ranges(),
|
||||
f.context().source(),
|
||||
);
|
||||
|
||||
let node_comments = comments.leading_dangling_trailing(*expression);
|
||||
|
||||
let has_comments = node_comments.has_leading() || node_comments.has_trailing_own_line();
|
||||
|
||||
// If the expression has comments, we always want to preserve the parentheses. This also
|
||||
// ensures that we correctly handle parenthesized comments, and don't need to worry about
|
||||
// them in the implementation below.
|
||||
if preserve_parentheses || has_comments {
|
||||
return expression.format().with_options(Parentheses::Always).fmt(f);
|
||||
}
|
||||
|
||||
let needs_parentheses = match expression.needs_parentheses(*parent, f.context()) {
|
||||
OptionalParentheses::Always => OptionalParentheses::Always,
|
||||
// The reason to add parentheses is to avoid a syntax error when breaking an expression over multiple lines.
|
||||
// Therefore, it is unnecessary to add an additional pair of parentheses if an outer expression
|
||||
// is parenthesized.
|
||||
_ if f.context().node_level().is_parenthesized() => OptionalParentheses::Never,
|
||||
needs_parentheses => needs_parentheses,
|
||||
};
|
||||
|
||||
match needs_parentheses {
|
||||
match self.needs_parentheses(f.context(), &node_comments) {
|
||||
OptionalParentheses::Multiline => match parenthesize {
|
||||
Parenthesize::IfBreaksOrIfRequired => {
|
||||
parenthesize_if_expands(&expression.format().with_options(Parentheses::Never))
|
||||
@@ -342,7 +356,7 @@ impl<'ast> IntoFormat<PyFormatContext<'ast>> for Expr {
|
||||
/// * The expression contains at least one parenthesized sub expression (optimization to avoid unnecessary work)
|
||||
///
|
||||
/// This mimics Black's [`_maybe_split_omitting_optional_parens`](https://github.com/psf/black/blob/d1248ca9beaf0ba526d265f4108836d89cf551b7/src/black/linegen.py#L746-L820)
|
||||
fn can_omit_optional_parentheses(expr: &Expr, context: &PyFormatContext) -> bool {
|
||||
pub(crate) fn can_omit_optional_parentheses(expr: &Expr, context: &PyFormatContext) -> bool {
|
||||
let mut visitor = CanOmitOptionalParenthesesVisitor::new(context);
|
||||
visitor.visit_subexpression(expr);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use ruff_formatter::prelude::tag::Condition;
|
||||
use ruff_formatter::{format_args, write, Argument, Arguments};
|
||||
use ruff_formatter::{format_args, write, Argument, Arguments, GroupId};
|
||||
use ruff_python_ast::node::AnyNodeRef;
|
||||
use ruff_python_ast::ExpressionRef;
|
||||
use ruff_python_trivia::CommentRanges;
|
||||
@@ -155,32 +155,34 @@ impl<'content, 'ast> FormatParenthesized<'content, 'ast> {
|
||||
|
||||
impl<'ast> Format<PyFormatContext<'ast>> for FormatParenthesized<'_, 'ast> {
|
||||
fn fmt(&self, f: &mut Formatter<PyFormatContext<'ast>>) -> FormatResult<()> {
|
||||
let inner = format_with(|f| {
|
||||
let current_level = f.context().node_level();
|
||||
|
||||
let content = format_with(|f| {
|
||||
group(&format_args![
|
||||
token(self.left),
|
||||
dangling_open_parenthesis_comments(self.comments),
|
||||
soft_block_indent(&Arguments::from(&self.content)),
|
||||
token(self.right)
|
||||
soft_block_indent(&Arguments::from(&self.content))
|
||||
])
|
||||
.fmt(f)
|
||||
});
|
||||
|
||||
let current_level = f.context().node_level();
|
||||
let inner = format_with(|f| {
|
||||
if let NodeLevel::Expression(Some(group_id)) = current_level {
|
||||
// Use fits expanded if there's an enclosing group that adds the optional parentheses.
|
||||
// This ensures that expanding this parenthesized expression does not expand the optional parentheses group.
|
||||
write!(
|
||||
f,
|
||||
[fits_expanded(&content)
|
||||
.with_condition(Some(Condition::if_group_fits_on_line(group_id)))]
|
||||
)
|
||||
} else {
|
||||
// It's not necessary to wrap the content if it is not inside of an optional_parentheses group.
|
||||
content.fmt(f)
|
||||
}
|
||||
});
|
||||
|
||||
let mut f = WithNodeLevel::new(NodeLevel::ParenthesizedExpression, f);
|
||||
|
||||
if let NodeLevel::Expression(Some(group_id)) = current_level {
|
||||
// Use fits expanded if there's an enclosing group that adds the optional parentheses.
|
||||
// This ensures that expanding this parenthesized expression does not expand the optional parentheses group.
|
||||
write!(
|
||||
f,
|
||||
[fits_expanded(&inner)
|
||||
.with_condition(Some(Condition::if_group_fits_on_line(group_id)))]
|
||||
)
|
||||
} else {
|
||||
// It's not necessary to wrap the content if it is not inside of an optional_parentheses group.
|
||||
write!(f, [inner])
|
||||
}
|
||||
write!(f, [token(self.left), inner, token(self.right)])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,18 +196,29 @@ where
|
||||
{
|
||||
FormatOptionalParentheses {
|
||||
content: Argument::new(content),
|
||||
group_id: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct FormatOptionalParentheses<'content, 'ast> {
|
||||
content: Argument<'content, PyFormatContext<'ast>>,
|
||||
group_id: Option<GroupId>,
|
||||
}
|
||||
|
||||
impl FormatOptionalParentheses<'_, '_> {
|
||||
pub(crate) fn with_group_id(mut self, group_id: GroupId) -> Self {
|
||||
self.group_id = Some(group_id);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> Format<PyFormatContext<'ast>> for FormatOptionalParentheses<'_, 'ast> {
|
||||
fn fmt(&self, f: &mut Formatter<PyFormatContext<'ast>>) -> FormatResult<()> {
|
||||
// The group id is used as a condition in [`in_parentheses_only_group`] to create a
|
||||
// conditional group that is only active if the optional parentheses group expands.
|
||||
let parens_id = f.group_id("optional_parentheses");
|
||||
let parens_id = self
|
||||
.group_id
|
||||
.unwrap_or_else(|| f.group_id("optional_parentheses"));
|
||||
|
||||
let mut f = WithNodeLevel::new(NodeLevel::Expression(Some(parens_id)), f);
|
||||
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
use ruff_formatter::prelude::{space, token};
|
||||
use ruff_formatter::write;
|
||||
use ruff_python_ast::StmtAssert;
|
||||
use ruff_formatter::{format_args, write};
|
||||
use ruff_python_ast::{Constant, Expr, ExprConstant, StmtAssert};
|
||||
|
||||
use crate::builders::parenthesize_if_expands;
|
||||
use crate::comments::{SourceComment, SuppressionKind};
|
||||
|
||||
use crate::expression::maybe_parenthesize_expression;
|
||||
use crate::expression::parentheses::Parenthesize;
|
||||
use crate::context::{NodeLevel, WithNodeLevel};
|
||||
use crate::expression::parentheses::{OptionalParentheses, Parentheses, Parenthesize};
|
||||
use crate::expression::{can_omit_optional_parentheses, maybe_parenthesize_expression};
|
||||
use crate::prelude::*;
|
||||
use crate::FormatNodeRule;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct FormatStmtAssert;
|
||||
@@ -19,14 +20,102 @@ impl FormatNodeRule<StmtAssert> for FormatStmtAssert {
|
||||
msg,
|
||||
} = item;
|
||||
|
||||
write!(
|
||||
f,
|
||||
[
|
||||
token("assert"),
|
||||
space(),
|
||||
maybe_parenthesize_expression(test, item, Parenthesize::IfBreaks)
|
||||
]
|
||||
)?;
|
||||
write!(f, [token("assert"), space()])?;
|
||||
|
||||
let parenthesize_test = maybe_parenthesize_expression(test, item, Parenthesize::IfBreaks);
|
||||
|
||||
if let Some(
|
||||
msg @ (Expr::FString(_)
|
||||
| Expr::Constant(ExprConstant {
|
||||
value: Constant::Str(_) | Constant::Bytes(_),
|
||||
..
|
||||
})),
|
||||
) = msg.as_deref()
|
||||
{
|
||||
let parenthesize_message =
|
||||
maybe_parenthesize_expression(msg, item, Parenthesize::IfBreaks);
|
||||
|
||||
let comments = f.context().comments();
|
||||
let test_comments = comments.leading_dangling_trailing(test.as_ref());
|
||||
let msg_comments = comments.leading_dangling_trailing(msg);
|
||||
|
||||
// TODO limit to can omit parentheses and has own parentheses
|
||||
if parenthesize_test.needs_parentheses(f.context(), &test_comments)
|
||||
== OptionalParentheses::Multiline
|
||||
&& parenthesize_message.needs_parentheses(f.context(), &msg_comments)
|
||||
== OptionalParentheses::BestFit
|
||||
&& can_omit_optional_parentheses(test, f.context())
|
||||
{
|
||||
let test_group_id = f.group_id("optional_parentheses");
|
||||
|
||||
let mut format_test = test.format().with_options(Parentheses::Never).memoized();
|
||||
let mut format_msg = msg.format().with_options(Parentheses::Never).memoized();
|
||||
|
||||
let test_breaks = {
|
||||
let f = &mut WithNodeLevel::new(NodeLevel::Expression(Some(test_group_id)), f);
|
||||
format_test.inspect(f)?.will_break()
|
||||
};
|
||||
|
||||
return if test_breaks || format_msg.inspect(f)?.will_break() {
|
||||
todo!()
|
||||
} else {
|
||||
best_fitting![
|
||||
// ---------------------------------------------------------------------
|
||||
// Variant 1:
|
||||
// Try to fit both expressions without parentheses
|
||||
format_args![
|
||||
group(&format_test).with_group_id(Some(test_group_id)),
|
||||
token(","),
|
||||
space(),
|
||||
format_msg
|
||||
],
|
||||
// ---------------------------------------------------------------------
|
||||
// Variant 2:
|
||||
// Try to parenthesize the string, but don't parenthesize the test just yet
|
||||
format_args![
|
||||
group(&format_test).with_group_id(Some(test_group_id)),
|
||||
token(","),
|
||||
space(),
|
||||
parenthesize_if_expands(&format_msg).should_expand(true)
|
||||
],
|
||||
// ---------------------------------------------------------------------
|
||||
// Variant 3:
|
||||
// Try to parenthesize both test and message
|
||||
format_args![
|
||||
parenthesize_if_expands(&format_test)
|
||||
.with_group_id(test_group_id)
|
||||
.should_expand(true),
|
||||
token(","),
|
||||
space(),
|
||||
parenthesize_if_expands(&format_msg).should_expand(true)
|
||||
],
|
||||
// ---------------------------------------------------------------------
|
||||
// Variant 4:
|
||||
// If it wasn't possible to make test and message fit by now, fallback to the first variant
|
||||
// and omit any optional parentheses.
|
||||
format_args![
|
||||
// Create an empty group that always fits. Necessary because the content
|
||||
// of format_test might refer the group id.
|
||||
format_with(|f| {
|
||||
f.write_element(FormatElement::GroupMode {
|
||||
id: test_group_id,
|
||||
mode: PrintMode::Flat,
|
||||
});
|
||||
Ok(())
|
||||
}),
|
||||
format_test,
|
||||
token(","),
|
||||
space(),
|
||||
format_msg
|
||||
],
|
||||
]
|
||||
.with_mode(BestFittingMode::AllLines)
|
||||
.fmt(f)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
maybe_parenthesize_expression(test, item, Parenthesize::IfBreaks).fmt(f)?;
|
||||
|
||||
if let Some(msg) = msg {
|
||||
write!(
|
||||
|
||||
@@ -193,41 +193,7 @@ class C:
|
||||
```diff
|
||||
--- Black
|
||||
+++ Ruff
|
||||
@@ -110,19 +110,20 @@
|
||||
value, is_going_to_be="too long to fit in a single line", srsly=True
|
||||
), "Not what we expected"
|
||||
|
||||
- assert {
|
||||
- key1: value1,
|
||||
- key2: value2,
|
||||
- key3: value3,
|
||||
- key4: value4,
|
||||
- key5: value5,
|
||||
- key6: value6,
|
||||
- key7: value7,
|
||||
- key8: value8,
|
||||
- key9: value9,
|
||||
- } == expected, (
|
||||
- "Not what we expected and the message is too long to fit in one line"
|
||||
- )
|
||||
+ assert (
|
||||
+ {
|
||||
+ key1: value1,
|
||||
+ key2: value2,
|
||||
+ key3: value3,
|
||||
+ key4: value4,
|
||||
+ key5: value5,
|
||||
+ key6: value6,
|
||||
+ key7: value7,
|
||||
+ key8: value8,
|
||||
+ key9: value9,
|
||||
+ }
|
||||
+ == expected
|
||||
+ ), "Not what we expected and the message is too long to fit in one line"
|
||||
|
||||
assert expected(
|
||||
value, is_going_to_be="too long to fit in a single line", srsly=True
|
||||
@@ -161,9 +162,7 @@
|
||||
@@ -161,9 +161,7 @@
|
||||
8 STORE_ATTR 0 (x)
|
||||
10 LOAD_CONST 0 (None)
|
||||
12 RETURN_VALUE
|
||||
@@ -355,20 +321,19 @@ class C:
|
||||
value, is_going_to_be="too long to fit in a single line", srsly=True
|
||||
), "Not what we expected"
|
||||
|
||||
assert (
|
||||
{
|
||||
key1: value1,
|
||||
key2: value2,
|
||||
key3: value3,
|
||||
key4: value4,
|
||||
key5: value5,
|
||||
key6: value6,
|
||||
key7: value7,
|
||||
key8: value8,
|
||||
key9: value9,
|
||||
}
|
||||
== expected
|
||||
), "Not what we expected and the message is too long to fit in one line"
|
||||
assert {
|
||||
key1: value1,
|
||||
key2: value2,
|
||||
key3: value3,
|
||||
key4: value4,
|
||||
key5: value5,
|
||||
key6: value6,
|
||||
key7: value7,
|
||||
key8: value8,
|
||||
key9: value9,
|
||||
} == expected, (
|
||||
"Not what we expected and the message is too long to fit in one line"
|
||||
)
|
||||
|
||||
assert expected(
|
||||
value, is_going_to_be="too long to fit in a single line", srsly=True
|
||||
|
||||
@@ -193,41 +193,7 @@ class C:
|
||||
```diff
|
||||
--- Black
|
||||
+++ Ruff
|
||||
@@ -110,19 +110,20 @@
|
||||
value, is_going_to_be="too long to fit in a single line", srsly=True
|
||||
), "Not what we expected"
|
||||
|
||||
- assert {
|
||||
- key1: value1,
|
||||
- key2: value2,
|
||||
- key3: value3,
|
||||
- key4: value4,
|
||||
- key5: value5,
|
||||
- key6: value6,
|
||||
- key7: value7,
|
||||
- key8: value8,
|
||||
- key9: value9,
|
||||
- } == expected, (
|
||||
- "Not what we expected and the message is too long to fit in one line"
|
||||
- )
|
||||
+ assert (
|
||||
+ {
|
||||
+ key1: value1,
|
||||
+ key2: value2,
|
||||
+ key3: value3,
|
||||
+ key4: value4,
|
||||
+ key5: value5,
|
||||
+ key6: value6,
|
||||
+ key7: value7,
|
||||
+ key8: value8,
|
||||
+ key9: value9,
|
||||
+ }
|
||||
+ == expected
|
||||
+ ), "Not what we expected and the message is too long to fit in one line"
|
||||
|
||||
assert expected(
|
||||
value, is_going_to_be="too long to fit in a single line", srsly=True
|
||||
@@ -161,9 +162,7 @@
|
||||
@@ -161,9 +161,7 @@
|
||||
8 STORE_ATTR 0 (x)
|
||||
10 LOAD_CONST 0 (None)
|
||||
12 RETURN_VALUE
|
||||
@@ -355,20 +321,19 @@ class C:
|
||||
value, is_going_to_be="too long to fit in a single line", srsly=True
|
||||
), "Not what we expected"
|
||||
|
||||
assert (
|
||||
{
|
||||
key1: value1,
|
||||
key2: value2,
|
||||
key3: value3,
|
||||
key4: value4,
|
||||
key5: value5,
|
||||
key6: value6,
|
||||
key7: value7,
|
||||
key8: value8,
|
||||
key9: value9,
|
||||
}
|
||||
== expected
|
||||
), "Not what we expected and the message is too long to fit in one line"
|
||||
assert {
|
||||
key1: value1,
|
||||
key2: value2,
|
||||
key3: value3,
|
||||
key4: value4,
|
||||
key5: value5,
|
||||
key6: value6,
|
||||
key7: value7,
|
||||
key8: value8,
|
||||
key9: value9,
|
||||
} == expected, (
|
||||
"Not what we expected and the message is too long to fit in one line"
|
||||
)
|
||||
|
||||
assert expected(
|
||||
value, is_going_to_be="too long to fit in a single line", srsly=True
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
---
|
||||
source: crates/ruff_python_formatter/tests/fixtures.rs
|
||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/trailing_comma_optional_parens3.py
|
||||
---
|
||||
## Input
|
||||
|
||||
```py
|
||||
if True:
|
||||
if True:
|
||||
if True:
|
||||
return _(
|
||||
"qweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweas "
|
||||
+ "qweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqwegqweasdzxcqweasdzxc.",
|
||||
"qweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqwe",
|
||||
) % {"reported_username": reported_username, "report_reason": report_reason}
|
||||
```
|
||||
|
||||
## Black Differences
|
||||
|
||||
```diff
|
||||
--- Black
|
||||
+++ Ruff
|
||||
@@ -1,8 +1,14 @@
|
||||
if True:
|
||||
if True:
|
||||
if True:
|
||||
- return _(
|
||||
- "qweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweas "
|
||||
- + "qweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqwegqweasdzxcqweasdzxc.",
|
||||
- "qweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqwe",
|
||||
- ) % {"reported_username": reported_username, "report_reason": report_reason}
|
||||
+ return (
|
||||
+ _(
|
||||
+ "qweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweas "
|
||||
+ + "qweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqwegqweasdzxcqweasdzxc.",
|
||||
+ "qweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqwe",
|
||||
+ )
|
||||
+ % {
|
||||
+ "reported_username": reported_username,
|
||||
+ "report_reason": report_reason,
|
||||
+ }
|
||||
+ )
|
||||
```
|
||||
|
||||
## Ruff Output
|
||||
|
||||
```py
|
||||
if True:
|
||||
if True:
|
||||
if True:
|
||||
return (
|
||||
_(
|
||||
"qweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweas "
|
||||
+ "qweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqwegqweasdzxcqweasdzxc.",
|
||||
"qweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqwe",
|
||||
)
|
||||
% {
|
||||
"reported_username": reported_username,
|
||||
"report_reason": report_reason,
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
## Black Output
|
||||
|
||||
```py
|
||||
if True:
|
||||
if True:
|
||||
if True:
|
||||
return _(
|
||||
"qweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweas "
|
||||
+ "qweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqwegqweasdzxcqweasdzxc.",
|
||||
"qweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqwe",
|
||||
) % {"reported_username": reported_username, "report_reason": report_reason}
|
||||
```
|
||||
|
||||
|
||||
@@ -400,6 +400,18 @@ z = (
|
||||
# c: and this comment
|
||||
+ a
|
||||
)
|
||||
|
||||
# Test for https://github.com/astral-sh/ruff/issues/7431
|
||||
if True:
|
||||
if True:
|
||||
if True:
|
||||
if True:
|
||||
msg += " " + _(
|
||||
"Since the role is not mentionable, it will be momentarily made mentionable "
|
||||
"when announcing a streamalert. Please make sure I have the correct "
|
||||
"permissions to manage this role, or else members of this role won't receive "
|
||||
"a notification."
|
||||
)
|
||||
```
|
||||
|
||||
## Output
|
||||
@@ -849,6 +861,18 @@ z = (
|
||||
# c: and this comment
|
||||
+ a
|
||||
)
|
||||
|
||||
# Test for https://github.com/astral-sh/ruff/issues/7431
|
||||
if True:
|
||||
if True:
|
||||
if True:
|
||||
if True:
|
||||
msg += " " + _(
|
||||
"Since the role is not mentionable, it will be momentarily made mentionable "
|
||||
"when announcing a streamalert. Please make sure I have the correct "
|
||||
"permissions to manage this role, or else members of this role won't receive "
|
||||
"a notification."
|
||||
)
|
||||
```
|
||||
|
||||
|
||||
|
||||
@@ -100,11 +100,6 @@ def f():
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = (
|
||||
True
|
||||
)
|
||||
|
||||
# Regression test for https://github.com/astral-sh/ruff/issues/7462
|
||||
if grid is not None:
|
||||
rgrid = (rgrid.rio.reproject_match(grid, nodata=fillvalue) # rio.reproject nodata is use to initlialize the destination array
|
||||
.where(~grid.isnull()))
|
||||
```
|
||||
|
||||
## Output
|
||||
@@ -227,15 +222,6 @@ def f():
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = (
|
||||
True
|
||||
)
|
||||
|
||||
|
||||
# Regression test for https://github.com/astral-sh/ruff/issues/7462
|
||||
if grid is not None:
|
||||
rgrid = rgrid.rio.reproject_match(
|
||||
grid, nodata=fillvalue
|
||||
).where( # rio.reproject nodata is use to initlialize the destination array
|
||||
~grid.isnull()
|
||||
)
|
||||
```
|
||||
|
||||
|
||||
|
||||
@@ -159,6 +159,22 @@ def test():
|
||||
key9: value9,
|
||||
}
|
||||
), "Not what we expected and the message is too long to fit in one lineeeeeeeeeeeeeee"
|
||||
|
||||
# Test for https://github.com/astral-sh/ruff/issues/7246
|
||||
assert items == [
|
||||
"a very very very very very very very very very very very very very very very long string",
|
||||
]
|
||||
|
||||
assert package.files == [
|
||||
{
|
||||
"file": "pytest-3.5.0-py2.py3-none-any.whl",
|
||||
"hash": "sha256:6266f87ab64692112e5477eba395cfedda53b1933ccd29478e671e73b420c19c", # noqa: E501
|
||||
},
|
||||
{
|
||||
"file": "pytest-3.5.0.tar.gz",
|
||||
"hash": "sha256:fae491d1874f199537fd5872b5e1f0e74a009b979df9d53d1553fd03da1703e1", # noqa: E501
|
||||
},
|
||||
]
|
||||
```
|
||||
|
||||
## Output
|
||||
@@ -195,80 +211,69 @@ assert (
|
||||
|
||||
|
||||
def test():
|
||||
assert (
|
||||
{
|
||||
key1: value1,
|
||||
key2: value2,
|
||||
key3: value3,
|
||||
key4: value4,
|
||||
key5: value5,
|
||||
key6: value6,
|
||||
key7: value7,
|
||||
key8: value8,
|
||||
key9: value9,
|
||||
}
|
||||
== expected
|
||||
), "Not what we expected and the message is too long to fit ineeeeee one line"
|
||||
assert {
|
||||
key1: value1,
|
||||
key2: value2,
|
||||
key3: value3,
|
||||
key4: value4,
|
||||
key5: value5,
|
||||
key6: value6,
|
||||
key7: value7,
|
||||
key8: value8,
|
||||
key9: value9,
|
||||
} == expected, (
|
||||
"Not what we expected and the message is too long to fit ineeeeee one line"
|
||||
)
|
||||
|
||||
assert (
|
||||
{
|
||||
key1: value1,
|
||||
key2: value2,
|
||||
key3: value3,
|
||||
key4: value4,
|
||||
key5: value5,
|
||||
key6: value6,
|
||||
key7: value7,
|
||||
key8: value8,
|
||||
key9: value9,
|
||||
}
|
||||
== expected
|
||||
), "Not what we expected and the message is too long to fit in one lineeeee"
|
||||
assert {
|
||||
key1: value1,
|
||||
key2: value2,
|
||||
key3: value3,
|
||||
key4: value4,
|
||||
key5: value5,
|
||||
key6: value6,
|
||||
key7: value7,
|
||||
key8: value8,
|
||||
key9: value9,
|
||||
} == expected, (
|
||||
"Not what we expected and the message is too long to fit in one lineeeee"
|
||||
)
|
||||
|
||||
assert (
|
||||
{
|
||||
key1: value1,
|
||||
key2: value2,
|
||||
key3: value3,
|
||||
key4: value4,
|
||||
key5: value5,
|
||||
key6: value6,
|
||||
key7: value7,
|
||||
key8: value8,
|
||||
key9: value9,
|
||||
}
|
||||
== expected
|
||||
), "Not what we expected and the message is too long to fit in one lineeeeeeeeeeeee"
|
||||
assert {
|
||||
key1: value1,
|
||||
key2: value2,
|
||||
key3: value3,
|
||||
key4: value4,
|
||||
key5: value5,
|
||||
key6: value6,
|
||||
key7: value7,
|
||||
key8: value8,
|
||||
key9: value9,
|
||||
} == expected, "Not what we expected and the message is too long to fit in one lineeeeeeeeeeeee"
|
||||
|
||||
assert (
|
||||
{
|
||||
key1: value1,
|
||||
key2: value2,
|
||||
key3: value3,
|
||||
key4: value4,
|
||||
key5: value5,
|
||||
key6: value6,
|
||||
key7: value7,
|
||||
key8: value8,
|
||||
key9: value9,
|
||||
}
|
||||
== expectedeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
|
||||
), "Not what we expected and the message is too long to fit in one lin"
|
||||
assert {
|
||||
key1: value1,
|
||||
key2: value2,
|
||||
key3: value3,
|
||||
key4: value4,
|
||||
key5: value5,
|
||||
key6: value6,
|
||||
key7: value7,
|
||||
key8: value8,
|
||||
key9: value9,
|
||||
} == expectedeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee, "Not what we expected and the message is too long to fit in one lin"
|
||||
|
||||
assert (
|
||||
{
|
||||
key1: value1,
|
||||
key2: value2,
|
||||
key3: value3,
|
||||
key4: value4,
|
||||
key5: value5,
|
||||
key6: value6,
|
||||
key7: value7,
|
||||
key8: value8,
|
||||
key9: value9,
|
||||
}
|
||||
== expectedeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
|
||||
), "Not what we expected and the message is too long to fit in one lineeeeeeeeeeeeeeeee"
|
||||
assert {
|
||||
key1: value1,
|
||||
key2: value2,
|
||||
key3: value3,
|
||||
key4: value4,
|
||||
key5: value5,
|
||||
key6: value6,
|
||||
key7: value7,
|
||||
key8: value8,
|
||||
key9: value9,
|
||||
} == expectedeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee, "Not what we expected and the message is too long to fit in one lineeeeeeeeeeeeeeeee"
|
||||
|
||||
assert expected == {
|
||||
key1: value1,
|
||||
@@ -282,20 +287,17 @@ def test():
|
||||
key9: value9,
|
||||
}, "Not what we expected and the message is too long to fit ineeeeee one line"
|
||||
|
||||
assert (
|
||||
expected
|
||||
== {
|
||||
key1: value1,
|
||||
key2: value2,
|
||||
key3: value3,
|
||||
key4: value4,
|
||||
key5: value5,
|
||||
key6: value6,
|
||||
key7: value7,
|
||||
key8: value8,
|
||||
key9: value9,
|
||||
}
|
||||
), "Not what we expected and the message is too long to fit in one lineeeeeeeeeeeeeeeeeeee"
|
||||
assert expected == {
|
||||
key1: value1,
|
||||
key2: value2,
|
||||
key3: value3,
|
||||
key4: value4,
|
||||
key5: value5,
|
||||
key6: value6,
|
||||
key7: value7,
|
||||
key8: value8,
|
||||
key9: value9,
|
||||
}, "Not what we expected and the message is too long to fit in one lineeeeeeeeeeeeeeeeeeee"
|
||||
|
||||
assert (
|
||||
expectedeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
|
||||
@@ -310,22 +312,38 @@ def test():
|
||||
key8: value8,
|
||||
key9: value9,
|
||||
}
|
||||
), "Not what we expected and the message is too long to fit in one lin"
|
||||
), (
|
||||
"Not what we expected and the message is too long to fit in one lin"
|
||||
)
|
||||
|
||||
assert (
|
||||
expectedeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
|
||||
== {
|
||||
key1: value1,
|
||||
key2: value2,
|
||||
key3: value3,
|
||||
key4: value4,
|
||||
key5: value5,
|
||||
key6: value6,
|
||||
key7: value7,
|
||||
key8: value8,
|
||||
key9: value9,
|
||||
}
|
||||
), "Not what we expected and the message is too long to fit in one lineeeeeeeeeeeeeee"
|
||||
assert expectedeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee == {
|
||||
key1: value1,
|
||||
key2: value2,
|
||||
key3: value3,
|
||||
key4: value4,
|
||||
key5: value5,
|
||||
key6: value6,
|
||||
key7: value7,
|
||||
key8: value8,
|
||||
key9: value9,
|
||||
}, "Not what we expected and the message is too long to fit in one lineeeeeeeeeeeeeee"
|
||||
|
||||
|
||||
# Test for https://github.com/astral-sh/ruff/issues/7246
|
||||
assert items == [
|
||||
"a very very very very very very very very very very very very very very very long string",
|
||||
]
|
||||
|
||||
assert package.files == [
|
||||
{
|
||||
"file": "pytest-3.5.0-py2.py3-none-any.whl",
|
||||
"hash": "sha256:6266f87ab64692112e5477eba395cfedda53b1933ccd29478e671e73b420c19c", # noqa: E501
|
||||
},
|
||||
{
|
||||
"file": "pytest-3.5.0.tar.gz",
|
||||
"hash": "sha256:fae491d1874f199537fd5872b5e1f0e74a009b979df9d53d1553fd03da1703e1", # noqa: E501
|
||||
},
|
||||
]
|
||||
```
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user