diff --git a/python/src/com/jetbrains/python/formatter/PyBlock.java b/python/src/com/jetbrains/python/formatter/PyBlock.java
index 9a627e37d3c2..11e6933ec6b4 100644
--- a/python/src/com/jetbrains/python/formatter/PyBlock.java
+++ b/python/src/com/jetbrains/python/formatter/PyBlock.java
@@ -28,6 +28,7 @@ import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ArrayUtil;
import com.jetbrains.python.PyElementTypes;
import com.jetbrains.python.PyTokenTypes;
+import com.jetbrains.python.PythonDialectsTokenSetProvider;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.PyPsiUtils;
import org.jetbrains.annotations.NotNull;
@@ -446,7 +447,7 @@ public class PyBlock implements ASTBlock {
if (TreeUtil.findParent(child, PyElementTypes.FSTRING_FRAGMENT) != null) {
childWrap = Wrap.createWrap(WrapType.NONE, false);
}
-
+
return new PyBlock(this, child, childAlignment, childIndent, childWrap, myContext);
}
@@ -829,6 +830,10 @@ public class PyBlock implements ASTBlock {
final IElementType childType2 = psi2.getNode().getElementType();
child2 = getSubBlockByNode(node2);
+ if (isInsideFStringFragmentWithEqualsSign(myNode)) {
+ return Spacing.getReadOnlySpacing();
+ }
+
if ((childType1 == PyTokenTypes.EQ || childType2 == PyTokenTypes.EQ)) {
final PyNamedParameter namedParameter = as(myNode.getPsi(), PyNamedParameter.class);
if (namedParameter != null && namedParameter.getAnnotation() != null) {
@@ -1171,4 +1176,16 @@ public class PyBlock implements ASTBlock {
public boolean isLeaf() {
return myNode.getFirstChildNode() == null;
}
+
+ private static final TokenSet stopAtTokens = TokenSet.orSet(TokenSet.create(PyElementTypes.FSTRING_NODE),
+ PythonDialectsTokenSetProvider.INSTANCE.getStatementTokens());
+
+ private static boolean isInsideFStringFragmentWithEqualsSign(@NotNull ASTNode node) {
+ final ASTNode fStringFragmentParent = node.getElementType() == PyElementTypes.FSTRING_FRAGMENT
+ ? node
+ : TreeUtil.findParent(node, TokenSet.create(PyElementTypes.FSTRING_FRAGMENT),
+ stopAtTokens);
+ if (fStringFragmentParent == null) return false;
+ return fStringFragmentParent.findChildByType(PyTokenTypes.EQ) != null;
+ }
}
diff --git a/python/src/com/jetbrains/python/parsing/ExpressionParsing.java b/python/src/com/jetbrains/python/parsing/ExpressionParsing.java
index 568af6d58d1a..4203ba3dc0b7 100644
--- a/python/src/com/jetbrains/python/parsing/ExpressionParsing.java
+++ b/python/src/com/jetbrains/python/parsing/ExpressionParsing.java
@@ -172,7 +172,8 @@ public class ExpressionParsing extends Parsing {
PyTokenTypes.FSTRING_FRAGMENT_FORMAT_START,
PyTokenTypes.FSTRING_FRAGMENT_END,
PyTokenTypes.FSTRING_END,
- PyTokenTypes.STATEMENT_BREAK)) {
+ PyTokenTypes.STATEMENT_BREAK,
+ PyTokenTypes.EQ)) {
nextToken();
recovery = true;
}
@@ -183,6 +184,8 @@ public class ExpressionParsing extends Parsing {
else {
recoveryMarker.drop();
}
+
+ matchToken(PyTokenTypes.EQ);
final boolean hasTypeConversion = matchToken(PyTokenTypes.FSTRING_FRAGMENT_TYPE_CONVERSION);
final boolean hasFormatPart = atToken(PyTokenTypes.FSTRING_FRAGMENT_FORMAT_START);
if (hasFormatPart) {
@@ -195,6 +198,7 @@ public class ExpressionParsing extends Parsing {
errorMessage = "type conversion, " + errorMessage;
}
}
+
checkMatches(PyTokenTypes.FSTRING_FRAGMENT_END, errorMessage);
marker.setCustomEdgeTokenBinders(null, CONSUME_COMMENTS_AND_SPACES_TO_LEFT);
marker.done(PyElementTypes.FSTRING_FRAGMENT);
diff --git a/python/src/com/jetbrains/python/validation/CompatibilityVisitor.java b/python/src/com/jetbrains/python/validation/CompatibilityVisitor.java
index ff54c9a57364..b6254b2a3a52 100644
--- a/python/src/com/jetbrains/python/validation/CompatibilityVisitor.java
+++ b/python/src/com/jetbrains/python/validation/CompatibilityVisitor.java
@@ -691,4 +691,15 @@ public abstract class CompatibilityVisitor extends PyAnnotator {
" not support positional-only parameters",
node);
}
+
+ @Override
+ public void visitPyFStringFragment(PyFStringFragment node) {
+ super.visitPyFStringFragment(node);
+
+ final ASTNode equalitySignInFStringFragment = node.getNode().findChildByType(PyTokenTypes.EQ);
+ if (equalitySignInFStringFragment != null) {
+ registerForAllMatchingVersions(level -> level.isOlderThan(LanguageLevel.PYTHON38) && registerForLanguageLevel(level),
+ " not support equality signs in f-strings", equalitySignInFStringFragment.getPsi());
+ }
+ }
}
diff --git a/python/testData/formatter/spacesAroundEqualsSignInFStringFragment.py b/python/testData/formatter/spacesAroundEqualsSignInFStringFragment.py
new file mode 100644
index 000000000000..2b3d0a47c7b1
--- /dev/null
+++ b/python/testData/formatter/spacesAroundEqualsSignInFStringFragment.py
@@ -0,0 +1,8 @@
+print(f'{ math.pi = :.2f }')
+s1 = f'{math.pi = :.2f}'
+s2 = f'{f"{3.1415=:.1f}":*^20}'
+s3 = f'{ 0 == 1 }'
+s4 = f'{ 12345 + x = }'
+s5 = f'''{
+ 3
+ = }'''
\ No newline at end of file
diff --git a/python/testData/formatter/spacesAroundEqualsSignInFStringFragment_after.py b/python/testData/formatter/spacesAroundEqualsSignInFStringFragment_after.py
new file mode 100644
index 000000000000..b5ac3de290c0
--- /dev/null
+++ b/python/testData/formatter/spacesAroundEqualsSignInFStringFragment_after.py
@@ -0,0 +1,8 @@
+print(f'{ math.pi = :.2f }')
+s1 = f'{math.pi = :.2f}'
+s2 = f'{f"{3.1415=:.1f}":*^20}'
+s3 = f'{0 == 1}'
+s4 = f'{ 12345 + x = }'
+s5 = f'''{
+ 3
+ = }'''
diff --git a/python/testData/inspections/PyCompatibilityInspection/equalitySignInFStrings.py b/python/testData/inspections/PyCompatibilityInspection/equalitySignInFStrings.py
new file mode 100644
index 000000000000..d5212da63f0a
--- /dev/null
+++ b/python/testData/inspections/PyCompatibilityInspection/equalitySignInFStrings.py
@@ -0,0 +1,3 @@
+import math
+print(f'{math.pi =:.2f}')
+print(f'{f"{3.1415=:.1f}":*^20}')
\ No newline at end of file
diff --git a/python/testData/psi/FStringEqualitySign.py b/python/testData/psi/FStringEqualitySign.py
new file mode 100644
index 000000000000..34ec4dcabdb3
--- /dev/null
+++ b/python/testData/psi/FStringEqualitySign.py
@@ -0,0 +1,19 @@
+import math
+s1 = f'{math.pi = :.2f}'
+s2 = f'{f"{3.1415=:.1f}":*^20}'
+s3 = f'{0 == 1}'
+x = 'A string'
+s4 = f'{x=!s}'
+x = 2.71828
+s5 = f'{x=:.2f}'
+s6 = f'{x=:}'
+s7 = f'{x=!r:^20}'
+s8 = f'{x=!s:^20}'
+s9 = f'{x= !a:^20}'
+s10 = f'{3 * x + 15=}'
+pi = 'π'
+s11 = f'alpha α {pi = } ω omega'
+s12 = f'''{
+ 3
+ =}'''
+s13 = f'{"="}'
\ No newline at end of file
diff --git a/python/testData/psi/FStringEqualitySign.txt b/python/testData/psi/FStringEqualitySign.txt
new file mode 100644
index 000000000000..fd8ae03707a2
--- /dev/null
+++ b/python/testData/psi/FStringEqualitySign.txt
@@ -0,0 +1,319 @@
+PyFile:FStringEqualitySign.py
+ PyImportStatement
+ PsiElement(Py:IMPORT_KEYWORD)('import')
+ PsiWhiteSpace(' ')
+ PyImportElement:math
+ PyReferenceExpression: math
+ PsiElement(Py:IDENTIFIER)('math')
+ PsiWhiteSpace('\n')
+ PyAssignmentStatement
+ PyTargetExpression: s1
+ PsiElement(Py:IDENTIFIER)('s1')
+ PsiWhiteSpace(' ')
+ PsiElement(Py:EQ)('=')
+ PsiWhiteSpace(' ')
+ PyStringLiteralExpression: {math.pi = :.2f}
+ PyFormattedStringElement
+ PsiElement(Py:FSTRING_START)('f'')
+ PyFStringFragment
+ PsiElement(Py:FSTRING_FRAGMENT_START)('{')
+ PyReferenceExpression: pi
+ PyReferenceExpression: math
+ PsiElement(Py:IDENTIFIER)('math')
+ PsiElement(Py:DOT)('.')
+ PsiElement(Py:IDENTIFIER)('pi')
+ PsiWhiteSpace(' ')
+ PsiElement(Py:EQ)('=')
+ PsiWhiteSpace(' ')
+ PyFStringFragmentFormatPart
+ PsiElement(Py:FSTRING_FRAGMENT_FORMAT_START)(':')
+ PsiElement(Py:FSTRING_TEXT)('.2f')
+ PsiElement(Py:FSTRING_FRAGMENT_END)('}')
+ PsiElement(Py:FSTRING_END)(''')
+ PsiWhiteSpace('\n')
+ PyAssignmentStatement
+ PyTargetExpression: s2
+ PsiElement(Py:IDENTIFIER)('s2')
+ PsiWhiteSpace(' ')
+ PsiElement(Py:EQ)('=')
+ PsiWhiteSpace(' ')
+ PyStringLiteralExpression: {f"{3.1415=:.1f}":*^20}
+ PyFormattedStringElement
+ PsiElement(Py:FSTRING_START)('f'')
+ PyFStringFragment
+ PsiElement(Py:FSTRING_FRAGMENT_START)('{')
+ PyStringLiteralExpression: {3.1415=:.1f}
+ PyFormattedStringElement
+ PsiElement(Py:FSTRING_START)('f"')
+ PyFStringFragment
+ PsiElement(Py:FSTRING_FRAGMENT_START)('{')
+ PyNumericLiteralExpression
+ PsiElement(Py:FLOAT_LITERAL)('3.1415')
+ PsiElement(Py:EQ)('=')
+ PyFStringFragmentFormatPart
+ PsiElement(Py:FSTRING_FRAGMENT_FORMAT_START)(':')
+ PsiElement(Py:FSTRING_TEXT)('.1f')
+ PsiElement(Py:FSTRING_FRAGMENT_END)('}')
+ PsiElement(Py:FSTRING_END)('"')
+ PyFStringFragmentFormatPart
+ PsiElement(Py:FSTRING_FRAGMENT_FORMAT_START)(':')
+ PsiElement(Py:FSTRING_TEXT)('*^20')
+ PsiElement(Py:FSTRING_FRAGMENT_END)('}')
+ PsiElement(Py:FSTRING_END)(''')
+ PsiWhiteSpace('\n')
+ PyAssignmentStatement
+ PyTargetExpression: s3
+ PsiElement(Py:IDENTIFIER)('s3')
+ PsiWhiteSpace(' ')
+ PsiElement(Py:EQ)('=')
+ PsiWhiteSpace(' ')
+ PyStringLiteralExpression: {0 == 1}
+ PyFormattedStringElement
+ PsiElement(Py:FSTRING_START)('f'')
+ PyFStringFragment
+ PsiElement(Py:FSTRING_FRAGMENT_START)('{')
+ PyBinaryExpression
+ PyNumericLiteralExpression
+ PsiElement(Py:INTEGER_LITERAL)('0')
+ PsiWhiteSpace(' ')
+ PsiElement(Py:EQEQ)('==')
+ PsiWhiteSpace(' ')
+ PyNumericLiteralExpression
+ PsiElement(Py:INTEGER_LITERAL)('1')
+ PsiElement(Py:FSTRING_FRAGMENT_END)('}')
+ PsiElement(Py:FSTRING_END)(''')
+ PsiWhiteSpace('\n')
+ PyAssignmentStatement
+ PyTargetExpression: x
+ PsiElement(Py:IDENTIFIER)('x')
+ PsiWhiteSpace(' ')
+ PsiElement(Py:EQ)('=')
+ PsiWhiteSpace(' ')
+ PyStringLiteralExpression: A string
+ PsiElement(Py:SINGLE_QUOTED_STRING)(''A string'')
+ PsiWhiteSpace('\n')
+ PyAssignmentStatement
+ PyTargetExpression: s4
+ PsiElement(Py:IDENTIFIER)('s4')
+ PsiWhiteSpace(' ')
+ PsiElement(Py:EQ)('=')
+ PsiWhiteSpace(' ')
+ PyStringLiteralExpression: {x=!s}
+ PyFormattedStringElement
+ PsiElement(Py:FSTRING_START)('f'')
+ PyFStringFragment
+ PsiElement(Py:FSTRING_FRAGMENT_START)('{')
+ PyReferenceExpression: x
+ PsiElement(Py:IDENTIFIER)('x')
+ PsiElement(Py:EQ)('=')
+ PsiElement(Py:FSTRING_FRAGMENT_TYPE_CONVERSION)('!s')
+ PsiElement(Py:FSTRING_FRAGMENT_END)('}')
+ PsiElement(Py:FSTRING_END)(''')
+ PsiWhiteSpace('\n')
+ PyAssignmentStatement
+ PyTargetExpression: x
+ PsiElement(Py:IDENTIFIER)('x')
+ PsiWhiteSpace(' ')
+ PsiElement(Py:EQ)('=')
+ PsiWhiteSpace(' ')
+ PyNumericLiteralExpression
+ PsiElement(Py:FLOAT_LITERAL)('2.71828')
+ PsiWhiteSpace('\n')
+ PyAssignmentStatement
+ PyTargetExpression: s5
+ PsiElement(Py:IDENTIFIER)('s5')
+ PsiWhiteSpace(' ')
+ PsiElement(Py:EQ)('=')
+ PsiWhiteSpace(' ')
+ PyStringLiteralExpression: {x=:.2f}
+ PyFormattedStringElement
+ PsiElement(Py:FSTRING_START)('f'')
+ PyFStringFragment
+ PsiElement(Py:FSTRING_FRAGMENT_START)('{')
+ PyReferenceExpression: x
+ PsiElement(Py:IDENTIFIER)('x')
+ PsiElement(Py:EQ)('=')
+ PyFStringFragmentFormatPart
+ PsiElement(Py:FSTRING_FRAGMENT_FORMAT_START)(':')
+ PsiElement(Py:FSTRING_TEXT)('.2f')
+ PsiElement(Py:FSTRING_FRAGMENT_END)('}')
+ PsiElement(Py:FSTRING_END)(''')
+ PsiWhiteSpace('\n')
+ PyAssignmentStatement
+ PyTargetExpression: s6
+ PsiElement(Py:IDENTIFIER)('s6')
+ PsiWhiteSpace(' ')
+ PsiElement(Py:EQ)('=')
+ PsiWhiteSpace(' ')
+ PyStringLiteralExpression: {x=:}
+ PyFormattedStringElement
+ PsiElement(Py:FSTRING_START)('f'')
+ PyFStringFragment
+ PsiElement(Py:FSTRING_FRAGMENT_START)('{')
+ PyReferenceExpression: x
+ PsiElement(Py:IDENTIFIER)('x')
+ PsiElement(Py:EQ)('=')
+ PyFStringFragmentFormatPart
+ PsiElement(Py:FSTRING_FRAGMENT_FORMAT_START)(':')
+ PsiElement(Py:FSTRING_FRAGMENT_END)('}')
+ PsiElement(Py:FSTRING_END)(''')
+ PsiWhiteSpace('\n')
+ PyAssignmentStatement
+ PyTargetExpression: s7
+ PsiElement(Py:IDENTIFIER)('s7')
+ PsiWhiteSpace(' ')
+ PsiElement(Py:EQ)('=')
+ PsiWhiteSpace(' ')
+ PyStringLiteralExpression: {x=!r:^20}
+ PyFormattedStringElement
+ PsiElement(Py:FSTRING_START)('f'')
+ PyFStringFragment
+ PsiElement(Py:FSTRING_FRAGMENT_START)('{')
+ PyReferenceExpression: x
+ PsiElement(Py:IDENTIFIER)('x')
+ PsiElement(Py:EQ)('=')
+ PsiElement(Py:FSTRING_FRAGMENT_TYPE_CONVERSION)('!r')
+ PyFStringFragmentFormatPart
+ PsiElement(Py:FSTRING_FRAGMENT_FORMAT_START)(':')
+ PsiElement(Py:FSTRING_TEXT)('^20')
+ PsiElement(Py:FSTRING_FRAGMENT_END)('}')
+ PsiElement(Py:FSTRING_END)(''')
+ PsiWhiteSpace('\n')
+ PyAssignmentStatement
+ PyTargetExpression: s8
+ PsiElement(Py:IDENTIFIER)('s8')
+ PsiWhiteSpace(' ')
+ PsiElement(Py:EQ)('=')
+ PsiWhiteSpace(' ')
+ PyStringLiteralExpression: {x=!s:^20}
+ PyFormattedStringElement
+ PsiElement(Py:FSTRING_START)('f'')
+ PyFStringFragment
+ PsiElement(Py:FSTRING_FRAGMENT_START)('{')
+ PyReferenceExpression: x
+ PsiElement(Py:IDENTIFIER)('x')
+ PsiElement(Py:EQ)('=')
+ PsiElement(Py:FSTRING_FRAGMENT_TYPE_CONVERSION)('!s')
+ PyFStringFragmentFormatPart
+ PsiElement(Py:FSTRING_FRAGMENT_FORMAT_START)(':')
+ PsiElement(Py:FSTRING_TEXT)('^20')
+ PsiElement(Py:FSTRING_FRAGMENT_END)('}')
+ PsiElement(Py:FSTRING_END)(''')
+ PsiWhiteSpace('\n')
+ PyAssignmentStatement
+ PyTargetExpression: s9
+ PsiElement(Py:IDENTIFIER)('s9')
+ PsiWhiteSpace(' ')
+ PsiElement(Py:EQ)('=')
+ PsiWhiteSpace(' ')
+ PyStringLiteralExpression: {x= !a:^20}
+ PyFormattedStringElement
+ PsiElement(Py:FSTRING_START)('f'')
+ PyFStringFragment
+ PsiElement(Py:FSTRING_FRAGMENT_START)('{')
+ PyReferenceExpression: x
+ PsiElement(Py:IDENTIFIER)('x')
+ PsiElement(Py:EQ)('=')
+ PsiWhiteSpace(' ')
+ PsiElement(Py:FSTRING_FRAGMENT_TYPE_CONVERSION)('!a')
+ PyFStringFragmentFormatPart
+ PsiElement(Py:FSTRING_FRAGMENT_FORMAT_START)(':')
+ PsiElement(Py:FSTRING_TEXT)('^20')
+ PsiElement(Py:FSTRING_FRAGMENT_END)('}')
+ PsiElement(Py:FSTRING_END)(''')
+ PsiWhiteSpace('\n')
+ PyAssignmentStatement
+ PyTargetExpression: s10
+ PsiElement(Py:IDENTIFIER)('s10')
+ PsiWhiteSpace(' ')
+ PsiElement(Py:EQ)('=')
+ PsiWhiteSpace(' ')
+ PyStringLiteralExpression: {3 * x + 15=}
+ PyFormattedStringElement
+ PsiElement(Py:FSTRING_START)('f'')
+ PyFStringFragment
+ PsiElement(Py:FSTRING_FRAGMENT_START)('{')
+ PyBinaryExpression
+ PyBinaryExpression
+ PyNumericLiteralExpression
+ PsiElement(Py:INTEGER_LITERAL)('3')
+ PsiWhiteSpace(' ')
+ PsiElement(Py:MULT)('*')
+ PsiWhiteSpace(' ')
+ PyReferenceExpression: x
+ PsiElement(Py:IDENTIFIER)('x')
+ PsiWhiteSpace(' ')
+ PsiElement(Py:PLUS)('+')
+ PsiWhiteSpace(' ')
+ PyNumericLiteralExpression
+ PsiElement(Py:INTEGER_LITERAL)('15')
+ PsiElement(Py:EQ)('=')
+ PsiElement(Py:FSTRING_FRAGMENT_END)('}')
+ PsiElement(Py:FSTRING_END)(''')
+ PsiWhiteSpace('\n')
+ PyAssignmentStatement
+ PyTargetExpression: pi
+ PsiElement(Py:IDENTIFIER)('pi')
+ PsiWhiteSpace(' ')
+ PsiElement(Py:EQ)('=')
+ PsiWhiteSpace(' ')
+ PyStringLiteralExpression: π
+ PsiElement(Py:SINGLE_QUOTED_STRING)(''π'')
+ PsiWhiteSpace('\n')
+ PyAssignmentStatement
+ PyTargetExpression: s11
+ PsiElement(Py:IDENTIFIER)('s11')
+ PsiWhiteSpace(' ')
+ PsiElement(Py:EQ)('=')
+ PsiWhiteSpace(' ')
+ PyStringLiteralExpression: alpha α {pi = } ω omega
+ PyFormattedStringElement
+ PsiElement(Py:FSTRING_START)('f'')
+ PsiElement(Py:FSTRING_TEXT)('alpha α ')
+ PyFStringFragment
+ PsiElement(Py:FSTRING_FRAGMENT_START)('{')
+ PyReferenceExpression: pi
+ PsiElement(Py:IDENTIFIER)('pi')
+ PsiWhiteSpace(' ')
+ PsiElement(Py:EQ)('=')
+ PsiWhiteSpace(' ')
+ PsiElement(Py:FSTRING_FRAGMENT_END)('}')
+ PsiElement(Py:FSTRING_TEXT)(' ω omega')
+ PsiElement(Py:FSTRING_END)(''')
+ PsiWhiteSpace('\n')
+ PyAssignmentStatement
+ PyTargetExpression: s12
+ PsiElement(Py:IDENTIFIER)('s12')
+ PsiWhiteSpace(' ')
+ PsiElement(Py:EQ)('=')
+ PsiWhiteSpace(' ')
+ PyStringLiteralExpression: {
+ 3
+ =}
+ PyFormattedStringElement
+ PsiElement(Py:FSTRING_START)('f'''')
+ PyFStringFragment
+ PsiElement(Py:FSTRING_FRAGMENT_START)('{')
+ PsiWhiteSpace('\n ')
+ PyNumericLiteralExpression
+ PsiElement(Py:INTEGER_LITERAL)('3')
+ PsiWhiteSpace('\n ')
+ PsiElement(Py:EQ)('=')
+ PsiElement(Py:FSTRING_FRAGMENT_END)('}')
+ PsiElement(Py:FSTRING_END)(''''')
+ PsiWhiteSpace('\n')
+ PyAssignmentStatement
+ PyTargetExpression: s13
+ PsiElement(Py:IDENTIFIER)('s13')
+ PsiWhiteSpace(' ')
+ PsiElement(Py:EQ)('=')
+ PsiWhiteSpace(' ')
+ PyStringLiteralExpression: {"="}
+ PyFormattedStringElement
+ PsiElement(Py:FSTRING_START)('f'')
+ PyFStringFragment
+ PsiElement(Py:FSTRING_FRAGMENT_START)('{')
+ PyStringLiteralExpression: =
+ PsiElement(Py:SINGLE_QUOTED_STRING)('"="')
+ PsiElement(Py:FSTRING_FRAGMENT_END)('}')
+ PsiElement(Py:FSTRING_END)(''')
\ No newline at end of file
diff --git a/python/testSrc/com/jetbrains/python/PyFormatterTest.java b/python/testSrc/com/jetbrains/python/PyFormatterTest.java
index 18e31ff5366b..da922afd7515 100644
--- a/python/testSrc/com/jetbrains/python/PyFormatterTest.java
+++ b/python/testSrc/com/jetbrains/python/PyFormatterTest.java
@@ -954,4 +954,9 @@ public class PyFormatterTest extends PyTestCase {
public void testSpacesAroundFStringFragmentExpressionStripped() {
runWithLanguageLevel(LanguageLevel.PYTHON36, this::doTest);
}
+
+ // PY-36009
+ public void testSpacesAroundEqualsSignInFStringFragment() {
+ doTest();
+ }
}
diff --git a/python/testSrc/com/jetbrains/python/PythonParsingTest.java b/python/testSrc/com/jetbrains/python/PythonParsingTest.java
index da529b973460..1b4d6aee04b5 100644
--- a/python/testSrc/com/jetbrains/python/PythonParsingTest.java
+++ b/python/testSrc/com/jetbrains/python/PythonParsingTest.java
@@ -901,6 +901,11 @@ public class PythonParsingTest extends ParsingTestCase {
doTest(LanguageLevel.PYTHON38);
}
+ // PY-36009
+ public void testFStringEqualitySign() {
+ doTest(LanguageLevel.PYTHON37);
+ }
+
public void doTest() {
doTest(LanguageLevel.PYTHON26);
}
diff --git a/python/testSrc/com/jetbrains/python/inspections/PyCompatibilityInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyCompatibilityInspectionTest.java
index b331df12110a..3828507ef1ce 100644
--- a/python/testSrc/com/jetbrains/python/inspections/PyCompatibilityInspectionTest.java
+++ b/python/testSrc/com/jetbrains/python/inspections/PyCompatibilityInspectionTest.java
@@ -215,6 +215,11 @@ public class PyCompatibilityInspectionTest extends PyInspectionTestCase {
doTest(LanguageLevel.PYTHON34);
}
+ // PY-36009
+ public void testEqualitySignInFStrings() {
+ doTest(LanguageLevel.PYTHON38);
+ }
+
public void testInputFromSixLib() {
doTest(LanguageLevel.PYTHON27);
}