Prefer expanding parenthesized expressions before operands

<!--
Thank you for contributing to Ruff! To help us out with reviewing, please consider the following:

- Does this pull request include a summary of the change? (See below.)
- Does this pull request include a descriptive title?
- Does this pull request include references to any relevant issues?
-->

## Summary

This PR implements Black's behavior where it first splits off parenthesized expressions before splitting before operands to avoid unnecessary parentheses:

```python
# We want 
if a + [ 
	b,
	c
]: 
	pass

# Rather than
if (
    a
    + [b, c]
): 
	pass
```

This is implemented by using the new IR elements introduced in #5596. 

* We give the group wrapping the optional parentheses an ID (`parentheses_id`)
* We use `conditional_group` for the lower priority groups  (all non-parenthesized expressions) with the condition that the `parentheses_id` group breaks (we want to split before operands only if the parentheses are necessary)
* We use `fits_expanded` to wrap all other parenthesized expressions (lists, dicts, sets), to prevent that expanding e.g. a list expands the `parentheses_id` group. We gate the `fits_expand` to only apply if the `parentheses_id` group fits (because we  prefer `a\n+[b, c]` over expanding `[b, c]` if the whole expression gets parenthesized).

We limit using `fits_expanded` and `conditional_group` only to expressions that themselves are not in parentheses (checking the conditions isn't free)

## Test Plan

It increases the Jaccard index for Django from 0.915 to 0.917

## Incompatibilites

There are two incompatibilities left that I'm aware of (there may be more, I didn't go through all snapshot differences). 

### Long string literals
I  commented on the regression. The issue is that a very long string (or any content without a split point) may not fit when only breaking the right side. The formatter than inserts the optional parentheses. But this is kind of useless because the overlong string will still not fit, because there are no new split points. 

I think we should ignore this incompatibility for now


### Expressions on statement level

I don't fully understand the logic behind this yet, but black doesn't break before the operators for the following example even though the expression exceeds the configured line width

```python
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa < bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb > ccccccccccccccccccccccccccccc == ddddddddddddddddddddd
```

But it would if the expression is used inside of a condition. 

What I understand so far is that Black doesn't insert optional parentheses on the expression statement level (and a few other places) and, therefore, only breaks after opening parentheses. I propose to keep this deviation for now to avoid overlong-lines and use the compatibility report to make a decision if we should implement the same behavior.
This commit is contained in:
Micha Reiser 2023-07-11 14:07:39 +02:00 committed by GitHub
parent d30e9125eb
commit 715250a179
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 680 additions and 943 deletions

View file

@ -203,33 +203,7 @@ class C:
print(i)
xxxxxxxxxxxxxxxx = Yyyy2YyyyyYyyyyy(
push_manager=context.request.resource_manager,
@@ -47,113 +47,46 @@
def omitting_trailers(self) -> None:
get_collection(
hey_this_is_a_very_long_call, it_has_funny_attributes, really=True
- )[OneLevelIndex]
+ )[
+ OneLevelIndex
+ ]
get_collection(
hey_this_is_a_very_long_call, it_has_funny_attributes, really=True
- )[OneLevelIndex][TwoLevelIndex][ThreeLevelIndex][FourLevelIndex]
+ )[
+ OneLevelIndex
+ ][
+ TwoLevelIndex
+ ][
+ ThreeLevelIndex
+ ][
+ FourLevelIndex
+ ]
d[0][1][2][3][4][5][6][7][8][9][10][11][12][13][14][15][16][17][18][19][20][21][
22
]
assignment = (
- some.rather.elaborate.rule() and another.rule.ending_with.index[123]
+ some.rather.elaborate.rule()
+ and another.rule.ending_with.index[123]
@@ -59,101 +59,23 @@
)
def easy_asserts(self) -> None:
@ -340,7 +314,7 @@ class C:
%3d 0 LOAD_FAST 1 (x)
2 LOAD_CONST 1 (1)
4 COMPARE_OP 2 (==)
@@ -161,21 +94,8 @@
@@ -161,21 +83,8 @@
8 STORE_ATTR 0 (x)
10 LOAD_CONST 0 (None)
12 RETURN_VALUE
@ -419,26 +393,15 @@ class C:
def omitting_trailers(self) -> None:
get_collection(
hey_this_is_a_very_long_call, it_has_funny_attributes, really=True
)[
OneLevelIndex
]
)[OneLevelIndex]
get_collection(
hey_this_is_a_very_long_call, it_has_funny_attributes, really=True
)[
OneLevelIndex
][
TwoLevelIndex
][
ThreeLevelIndex
][
FourLevelIndex
]
)[OneLevelIndex][TwoLevelIndex][ThreeLevelIndex][FourLevelIndex]
d[0][1][2][3][4][5][6][7][8][9][10][11][12][13][14][15][16][17][18][19][20][21][
22
]
assignment = (
some.rather.elaborate.rule()
and another.rule.ending_with.index[123]
some.rather.elaborate.rule() and another.rule.ending_with.index[123]
)
def easy_asserts(self) -> None:

View file

@ -203,33 +203,7 @@ class C:
print(i)
xxxxxxxxxxxxxxxx = Yyyy2YyyyyYyyyyy(
push_manager=context.request.resource_manager,
@@ -47,113 +47,46 @@
def omitting_trailers(self) -> None:
get_collection(
hey_this_is_a_very_long_call, it_has_funny_attributes, really=True
- )[OneLevelIndex]
+ )[
+ OneLevelIndex
+ ]
get_collection(
hey_this_is_a_very_long_call, it_has_funny_attributes, really=True
- )[OneLevelIndex][TwoLevelIndex][ThreeLevelIndex][FourLevelIndex]
+ )[
+ OneLevelIndex
+ ][
+ TwoLevelIndex
+ ][
+ ThreeLevelIndex
+ ][
+ FourLevelIndex
+ ]
d[0][1][2][3][4][5][6][7][8][9][10][11][12][13][14][15][16][17][18][19][20][21][
22
]
assignment = (
- some.rather.elaborate.rule() and another.rule.ending_with.index[123]
+ some.rather.elaborate.rule()
+ and another.rule.ending_with.index[123]
@@ -59,101 +59,23 @@
)
def easy_asserts(self) -> None:
@ -340,7 +314,7 @@ class C:
%3d 0 LOAD_FAST 1 (x)
2 LOAD_CONST 1 (1)
4 COMPARE_OP 2 (==)
@@ -161,21 +94,8 @@
@@ -161,21 +83,8 @@
8 STORE_ATTR 0 (x)
10 LOAD_CONST 0 (None)
12 RETURN_VALUE
@ -419,26 +393,15 @@ class C:
def omitting_trailers(self) -> None:
get_collection(
hey_this_is_a_very_long_call, it_has_funny_attributes, really=True
)[
OneLevelIndex
]
)[OneLevelIndex]
get_collection(
hey_this_is_a_very_long_call, it_has_funny_attributes, really=True
)[
OneLevelIndex
][
TwoLevelIndex
][
ThreeLevelIndex
][
FourLevelIndex
]
)[OneLevelIndex][TwoLevelIndex][ThreeLevelIndex][FourLevelIndex]
d[0][1][2][3][4][5][6][7][8][9][10][11][12][13][14][15][16][17][18][19][20][21][
22
]
assignment = (
some.rather.elaborate.rule()
and another.rule.ending_with.index[123]
some.rather.elaborate.rule() and another.rule.ending_with.index[123]
)
def easy_asserts(self) -> None:

View file

@ -113,61 +113,15 @@ def g():
prev = leaf.prev_sibling
if not prev:
@@ -25,23 +25,31 @@
return NO
if prevp.type == token.EQUAL:
- if prevp.parent and prevp.parent.type in {
- syms.typedargslist,
- syms.varargslist,
- syms.parameters,
- syms.arglist,
- syms.argument,
- }:
+ if (
+ prevp.parent
+ and prevp.parent.type
+ in {
+ syms.typedargslist,
+ syms.varargslist,
+ syms.parameters,
+ syms.arglist,
+ syms.argument,
+ }
+ ):
return NO
elif prevp.type == token.DOUBLESTAR:
- if prevp.parent and prevp.parent.type in {
- syms.typedargslist,
- syms.varargslist,
- syms.parameters,
- syms.arglist,
- syms.dictsetmaker,
- }:
+ if (
+ prevp.parent
+ and prevp.parent.type
+ in {
+ syms.typedargslist,
+ syms.varargslist,
+ syms.parameters,
+ syms.arglist,
+ syms.dictsetmaker,
+ }
+ ):
return NO
@@ -49,7 +57,6 @@
@@ -48,7 +48,6 @@
###############################################################################
# SECTION BECAUSE SECTIONS
###############################################################################
-
def g():
NO = ""
SPACE = " "
@@ -67,7 +74,7 @@
@@ -67,7 +66,7 @@
return DOUBLESPACE
# Another comment because more comments
@ -176,29 +130,6 @@ def g():
prev = leaf.prev_sibling
if not prev:
@@ -79,11 +86,15 @@
return NO
if prevp.type == token.EQUAL:
- if prevp.parent and prevp.parent.type in {
- syms.typedargslist,
- syms.varargslist,
- syms.parameters,
- syms.arglist,
- syms.argument,
- }:
+ if (
+ prevp.parent
+ and prevp.parent.type
+ in {
+ syms.typedargslist,
+ syms.varargslist,
+ syms.parameters,
+ syms.arglist,
+ syms.argument,
+ }
+ ):
return NO
```
## Ruff Output
@ -231,31 +162,23 @@ def f():
return NO
if prevp.type == token.EQUAL:
if (
prevp.parent
and prevp.parent.type
in {
syms.typedargslist,
syms.varargslist,
syms.parameters,
syms.arglist,
syms.argument,
}
):
if prevp.parent and prevp.parent.type in {
syms.typedargslist,
syms.varargslist,
syms.parameters,
syms.arglist,
syms.argument,
}:
return NO
elif prevp.type == token.DOUBLESTAR:
if (
prevp.parent
and prevp.parent.type
in {
syms.typedargslist,
syms.varargslist,
syms.parameters,
syms.arglist,
syms.dictsetmaker,
}
):
if prevp.parent and prevp.parent.type in {
syms.typedargslist,
syms.varargslist,
syms.parameters,
syms.arglist,
syms.dictsetmaker,
}:
return NO
@ -292,17 +215,13 @@ def g():
return NO
if prevp.type == token.EQUAL:
if (
prevp.parent
and prevp.parent.type
in {
syms.typedargslist,
syms.varargslist,
syms.parameters,
syms.arglist,
syms.argument,
}
):
if prevp.parent and prevp.parent.type in {
syms.typedargslist,
syms.varargslist,
syms.parameters,
syms.arglist,
syms.argument,
}:
return NO
```

View file

@ -73,26 +73,7 @@ some_module.some_function(
```diff
--- Black
+++ Ruff
@@ -35,7 +35,9 @@
x = {
"a": 1,
"b": 2,
- }["a"]
+ }[
+ "a"
+ ]
if (
a
== {
@@ -47,14 +49,16 @@
"f": 6,
"g": 7,
"h": 8,
- }["a"]
+ }[
+ "a"
+ ]
):
@@ -52,9 +52,9 @@
pass
@ -105,7 +86,7 @@ some_module.some_function(
json = {
"k": {
"k2": {
@@ -80,18 +84,14 @@
@@ -80,18 +80,14 @@
pass
@ -170,9 +151,7 @@ def f(
x = {
"a": 1,
"b": 2,
}[
"a"
]
}["a"]
if (
a
== {
@ -184,9 +163,7 @@ def f(
"f": 6,
"g": 7,
"h": 8,
}[
"a"
]
}["a"]
):
pass

View file

@ -93,7 +93,7 @@ async def main():
```diff
--- Black
+++ Ruff
@@ -8,59 +8,70 @@
@@ -8,28 +8,33 @@
# Remove brackets for short coroutine/task
async def main():
@ -122,10 +122,8 @@ async def main():
async def main():
- await asyncio.sleep(1) # Hello
+ (
+ await (
+ asyncio.sleep(1) # Hello
+ )
+ await (
+ asyncio.sleep(1) # Hello
+ )
@ -135,50 +133,7 @@ async def main():
# Long lines
async def main():
- await asyncio.gather(
- asyncio.sleep(1),
- asyncio.sleep(1),
- asyncio.sleep(1),
- asyncio.sleep(1),
- asyncio.sleep(1),
- asyncio.sleep(1),
- asyncio.sleep(1),
+ (
+ await asyncio.gather(
+ asyncio.sleep(1),
+ asyncio.sleep(1),
+ asyncio.sleep(1),
+ asyncio.sleep(1),
+ asyncio.sleep(1),
+ asyncio.sleep(1),
+ asyncio.sleep(1),
+ )
)
# Same as above but with magic trailing comma in function
async def main():
- await asyncio.gather(
- asyncio.sleep(1),
- asyncio.sleep(1),
- asyncio.sleep(1),
- asyncio.sleep(1),
- asyncio.sleep(1),
- asyncio.sleep(1),
- asyncio.sleep(1),
+ (
+ await asyncio.gather(
+ asyncio.sleep(1),
+ asyncio.sleep(1),
+ asyncio.sleep(1),
+ asyncio.sleep(1),
+ asyncio.sleep(1),
+ asyncio.sleep(1),
+ asyncio.sleep(1),
+ )
)
@@ -60,7 +65,7 @@
# Cr@zY Br@ck3Tz
async def main():
@ -187,7 +142,7 @@ async def main():
# Keep brackets around non power operations and nested awaits
@@ -78,16 +89,16 @@
@@ -78,16 +83,16 @@
async def main():
@ -243,10 +198,8 @@ async def main():
async def main():
(
await (
asyncio.sleep(1) # Hello
)
await (
asyncio.sleep(1) # Hello
)
@ -256,31 +209,27 @@ async def main():
# Long lines
async def main():
(
await asyncio.gather(
asyncio.sleep(1),
asyncio.sleep(1),
asyncio.sleep(1),
asyncio.sleep(1),
asyncio.sleep(1),
asyncio.sleep(1),
asyncio.sleep(1),
)
await asyncio.gather(
asyncio.sleep(1),
asyncio.sleep(1),
asyncio.sleep(1),
asyncio.sleep(1),
asyncio.sleep(1),
asyncio.sleep(1),
asyncio.sleep(1),
)
# Same as above but with magic trailing comma in function
async def main():
(
await asyncio.gather(
asyncio.sleep(1),
asyncio.sleep(1),
asyncio.sleep(1),
asyncio.sleep(1),
asyncio.sleep(1),
asyncio.sleep(1),
asyncio.sleep(1),
)
await asyncio.gather(
asyncio.sleep(1),
asyncio.sleep(1),
asyncio.sleep(1),
asyncio.sleep(1),
asyncio.sleep(1),
asyncio.sleep(1),
asyncio.sleep(1),
)

View file

@ -64,7 +64,7 @@ assert (
importA
0
@@ -25,34 +15,33 @@
@@ -25,9 +15,7 @@
class A:
def foo(self):
for _ in range(10):
@ -75,46 +75,7 @@ assert (
def test(self, othr):
- return 1 == 2 and (
- name,
- description,
- self.default,
- self.selected,
- self.auto_generated,
- self.parameters,
- self.meta_data,
- self.schedule,
- ) == (
- name,
- description,
- othr.default,
- othr.selected,
- othr.auto_generated,
- othr.parameters,
- othr.meta_data,
- othr.schedule,
+ return (
+ 1 == 2
+ and (
+ name,
+ description,
+ self.default,
+ self.selected,
+ self.auto_generated,
+ self.parameters,
+ self.meta_data,
+ self.schedule,
+ )
+ == (
+ name,
+ description,
+ othr.default,
+ othr.selected,
+ othr.auto_generated,
+ othr.parameters,
+ othr.meta_data,
+ othr.schedule,
+ )
@@ -52,7 +40,4 @@
)
@ -149,28 +110,24 @@ class A:
def test(self, othr):
return (
1 == 2
and (
name,
description,
self.default,
self.selected,
self.auto_generated,
self.parameters,
self.meta_data,
self.schedule,
)
== (
name,
description,
othr.default,
othr.selected,
othr.auto_generated,
othr.parameters,
othr.meta_data,
othr.schedule,
)
return 1 == 2 and (
name,
description,
self.default,
self.selected,
self.auto_generated,
self.parameters,
self.meta_data,
self.schedule,
) == (
name,
description,
othr.default,
othr.selected,
othr.auto_generated,
othr.parameters,
othr.meta_data,
othr.schedule,
)

View file

@ -37,17 +37,7 @@ class A:
```diff
--- Black
+++ Ruff
@@ -1,18 +1,16 @@
-if e1234123412341234.winerror not in (
- _winapi.ERROR_SEM_TIMEOUT,
- _winapi.ERROR_PIPE_BUSY,
-) or _check_timeout(t):
+if (
+ e1234123412341234.winerror
+ not in (_winapi.ERROR_SEM_TIMEOUT, _winapi.ERROR_PIPE_BUSY)
+ or _check_timeout(t)
+):
pass
@@ -6,13 +6,10 @@
if x:
if y:
@ -65,36 +55,15 @@ class A:
class X:
@@ -26,9 +24,14 @@
class A:
def b(self):
- if self.connection.mysql_is_mariadb and (
- 10,
- 4,
- 3,
- ) < self.connection.mysql_version < (10, 5, 2):
+ if (
+ self.connection.mysql_is_mariadb
+ and (
+ 10,
+ 4,
+ 3,
+ )
+ < self.connection.mysql_version
+ < (10, 5, 2)
+ ):
pass
```
## Ruff Output
```py
if (
e1234123412341234.winerror
not in (_winapi.ERROR_SEM_TIMEOUT, _winapi.ERROR_PIPE_BUSY)
or _check_timeout(t)
):
if e1234123412341234.winerror not in (
_winapi.ERROR_SEM_TIMEOUT,
_winapi.ERROR_PIPE_BUSY,
) or _check_timeout(t):
pass
if x:
@ -116,16 +85,11 @@ class X:
class A:
def b(self):
if (
self.connection.mysql_is_mariadb
and (
10,
4,
3,
)
< self.connection.mysql_version
< (10, 5, 2)
):
if self.connection.mysql_is_mariadb and (
10,
4,
3,
) < self.connection.mysql_version < (10, 5, 2):
pass
```

View file

@ -1,52 +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_parens2.py
---
## Input
```py
if (e123456.get_tk_patchlevel() >= (8, 6, 0, 'final') or
(8, 5, 8) <= get_tk_patchlevel() < (8, 6)):
pass
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -1,6 +1,5 @@
-if e123456.get_tk_patchlevel() >= (8, 6, 0, "final") or (
- 8,
- 5,
- 8,
-) <= get_tk_patchlevel() < (8, 6):
+if (
+ e123456.get_tk_patchlevel() >= (8, 6, 0, "final")
+ or (8, 5, 8) <= get_tk_patchlevel() < (8, 6)
+):
pass
```
## Ruff Output
```py
if (
e123456.get_tk_patchlevel() >= (8, 6, 0, "final")
or (8, 5, 8) <= get_tk_patchlevel() < (8, 6)
):
pass
```
## Black Output
```py
if e123456.get_tk_patchlevel() >= (8, 6, 0, "final") or (
8,
5,
8,
) <= get_tk_patchlevel() < (8, 6):
pass
```

View file

@ -0,0 +1,77 @@
---
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}
```

View file

@ -56,19 +56,7 @@ assert xxxxxxxxx.xxxxxxxxx.xxxxxxxxx(
# Example from https://github.com/psf/black/issues/3229
@@ -32,19 +30,18 @@
"refreshToken": refresh_token,
},
api_key=api_key,
- )["extensions"]["sdk"]["token"]
+ )[
+ "extensions"
+ ][
+ "sdk"
+ ][
+ "token"
+ ]
@@ -37,14 +35,7 @@
# Edge case where a bug in a working-in-progress version of
# https://github.com/psf/black/pull/3370 causes an infinite recursion.
@ -122,13 +110,7 @@ def refresh_token(self, device_family, refresh_token, api_key):
"refreshToken": refresh_token,
},
api_key=api_key,
)[
"extensions"
][
"sdk"
][
"token"
]
)["extensions"]["sdk"]["token"]
# Edge case where a bug in a working-in-progress version of

View file

@ -476,9 +476,9 @@ if (
# Unstable formatting in https://github.com/realtyem/synapse-unraid/blob/unraid_develop/synapse/handlers/presence.py
for user_id in set(
target_user_ids
) - {NOT_IMPLEMENTED_set_value for value in NOT_IMPLEMENTED_set}:
for user_id in (
set(target_user_ids) - {NOT_IMPLEMENTED_set_value for value in NOT_IMPLEMENTED_set}
):
updates.append(UserPresenceState.default(user_id))
# Keeps parenthesized left hand sides

View file

@ -110,28 +110,24 @@ a < b > c == d
< ddddddddddddddddddddddddddddddddddddddddddd
)
return (
1 == 2
and (
name,
description,
self_default,
self_selected,
self_auto_generated,
self_parameters,
self_meta_data,
self_schedule,
)
== (
name,
description,
othr_default,
othr_selected,
othr_auto_generated,
othr_parameters,
othr_meta_data,
othr_schedule,
)
return 1 == 2 and (
name,
description,
self_default,
self_selected,
self_auto_generated,
self_parameters,
self_meta_data,
self_schedule,
) == (
name,
description,
othr_default,
othr_selected,
othr_auto_generated,
othr_parameters,
othr_meta_data,
othr_schedule,
)
(

View file

@ -256,13 +256,10 @@ if aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa & (
):
pass
if (
not (
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
)
& aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
):
if not (
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
) & aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:
pass

View file

@ -143,8 +143,10 @@ raise (
+ cccccccccccccccccccccc
+ ddddddddddddddddddddddddd
)
raise aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbb + (
cccccccccccccccccccccc + ddddddddddddddddddddddddd
raise (
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ bbbbbbbbbbbbbbbbbbbbbbbbbb
+ (cccccccccccccccccccccc + ddddddddddddddddddddddddd)
)
raise (
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa