This is an automated email from the ASF dual-hosted git repository.

hansva pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/hop.git


The following commit(s) were added to refs/heads/main by this push:
     new 95efe22b3f issue #7470 : Python script support, also for Hop Web 
(#7475)
95efe22b3f is described below

commit 95efe22b3f5add03ff8f4f6a99377a866810e5d7
Author: Matt Casters <[email protected]>
AuthorDate: Fri Jul 10 09:26:19 2026 +0200

    issue #7470 : Python script support, also for Hop Web (#7475)
---
 .../hop/workflow/actions/shell/ActionShell.java    |   28 +
 .../shell/messages/messages_en_US.properties       |    2 +
 .../shell/ActionShellReferencedObjectTest.java     |   85 +
 .../apache/hop/workflow/actions/sql/ActionSql.java |   29 +
 .../actions/sql/messages/messages_en_US.properties |    1 +
 .../actions/sql/ActionSqlReferencedObjectTest.java |   85 +
 .../transforms/types/BatExplorerFileType.java      |   65 +
 .../transforms/types/PythonExplorerFileType.java   |   66 +
 .../types/PythonExplorerFileTypeHandler.java       |   37 +
 .../transforms/types/ShellExplorerFileType.java    |   65 +
 .../textfile/src/main/resources/python.svg         |   33 +
 .../types/PythonExplorerFileTypeTest.java          |   91 +
 .../hop/ui/hopgui/ContentEditorTm4eSupport.java    |    7 +-
 .../hopgui/RuleBasedSourceViewerConfiguration.java |    5 +-
 .../org/apache/hop/ui/hopgui/grammars/python.json  | 4213 ++++++++++++++++++++
 .../ui/hopgui/ContentEditorTm4eSupportTest.java    |   47 +
 16 files changed, 4856 insertions(+), 3 deletions(-)

diff --git 
a/plugins/actions/shell/src/main/java/org/apache/hop/workflow/actions/shell/ActionShell.java
 
b/plugins/actions/shell/src/main/java/org/apache/hop/workflow/actions/shell/ActionShell.java
index 506581a8c1..14725046a3 100644
--- 
a/plugins/actions/shell/src/main/java/org/apache/hop/workflow/actions/shell/ActionShell.java
+++ 
b/plugins/actions/shell/src/main/java/org/apache/hop/workflow/actions/shell/ActionShell.java
@@ -39,6 +39,7 @@ import org.apache.hop.core.RowMetaAndData;
 import org.apache.hop.core.annotations.Action;
 import org.apache.hop.core.exception.HopException;
 import org.apache.hop.core.exception.HopXmlException;
+import org.apache.hop.core.file.IHasFilename;
 import org.apache.hop.core.logging.FileLoggingEventListener;
 import org.apache.hop.core.logging.HopLogStore;
 import org.apache.hop.core.logging.LogLevel;
@@ -655,4 +656,31 @@ public class ActionShell extends ActionBase {
               
AndValidator.putValidators(ActionValidatorUtils.notBlankValidator()));
     }
   }
+
+  @Override
+  public String[] getReferencedObjectDescriptions() {
+    if (insertScript) {
+      return null;
+    }
+    return new String[] {
+      BaseMessages.getString(PKG, "ActionShell.ReferencedObject.Description"),
+    };
+  }
+
+  @Override
+  public boolean[] isReferencedObjectEnabled() {
+    if (insertScript) {
+      return null;
+    }
+    return new boolean[] {!Utils.isEmpty(filename)};
+  }
+
+  @Override
+  public IHasFilename loadReferencedObject(
+      int index, IHopMetadataProvider metadataProvider, IVariables variables) 
throws HopException {
+    if (index != 0 || insertScript || Utils.isEmpty(filename)) {
+      throw new HopException(BaseMessages.getString(PKG, 
"ActionShell.NoScriptFileSpecified"));
+    }
+    return () -> filename;
+  }
 }
diff --git 
a/plugins/actions/shell/src/main/resources/org/apache/hop/workflow/actions/shell/messages/messages_en_US.properties
 
b/plugins/actions/shell/src/main/resources/org/apache/hop/workflow/actions/shell/messages/messages_en_US.properties
index b192625918..b8704ab1fe 100644
--- 
a/plugins/actions/shell/src/main/resources/org/apache/hop/workflow/actions/shell/messages/messages_en_US.properties
+++ 
b/plugins/actions/shell/src/main/resources/org/apache/hop/workflow/actions/shell/messages/messages_en_US.properties
@@ -42,6 +42,8 @@ ActionShell.Logfile.IncludeTime.Label=Include time in logfile
 ActionShell.LogfileExtension.Label=Extension of logfile
 ActionShell.Loglevel.Label=Log level
 ActionShell.LogSettings.Group.Label=Logging settings
+ActionShell.NoScriptFileSpecified=Please specify script filename\!
+ActionShell.ReferencedObject.Description=Shell script
 ActionShell.Name=Shell
 ActionShell.Name.Label=Action name
 ActionShell.NameOfLogfile.Label=Name of logfile
diff --git 
a/plugins/actions/shell/src/test/java/org/apache/hop/workflow/actions/shell/ActionShellReferencedObjectTest.java
 
b/plugins/actions/shell/src/test/java/org/apache/hop/workflow/actions/shell/ActionShellReferencedObjectTest.java
new file mode 100644
index 0000000000..b1e1fe5f6b
--- /dev/null
+++ 
b/plugins/actions/shell/src/test/java/org/apache/hop/workflow/actions/shell/ActionShellReferencedObjectTest.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hop.workflow.actions.shell;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.apache.hop.core.exception.HopException;
+import org.apache.hop.core.file.IHasFilename;
+import org.apache.hop.core.variables.Variables;
+import org.apache.hop.junit.rules.RestoreHopEngineEnvironmentExtension;
+import org.apache.hop.metadata.serializer.memory.MemoryMetadataProvider;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+class ActionShellReferencedObjectTest {
+
+  @RegisterExtension
+  static RestoreHopEngineEnvironmentExtension env = new 
RestoreHopEngineEnvironmentExtension();
+
+  @Test
+  void noReferencesWhenScriptIsInline() {
+    ActionShell action = new ActionShell();
+    action.insertScript = true;
+    action.setFilename("/some/script.sh");
+
+    assertNull(action.getReferencedObjectDescriptions());
+    assertNull(action.isReferencedObjectEnabled());
+  }
+
+  @Test
+  void referencedObjectDisabledWhenFilenameEmpty() {
+    ActionShell action = new ActionShell();
+    action.insertScript = false;
+    action.setFilename("");
+
+    assertEquals(1, action.getReferencedObjectDescriptions().length);
+    assertFalse(action.isReferencedObjectEnabled()[0]);
+  }
+
+  @Test
+  void referencedObjectEnabledWhenFilenameSet() throws HopException {
+    ActionShell action = new ActionShell();
+    action.insertScript = false;
+    action.setFilename("${PROJECT_HOME}/scripts/setup.sh");
+
+    assertEquals(1, action.getReferencedObjectDescriptions().length);
+    assertTrue(action.isReferencedObjectEnabled()[0]);
+
+    IHasFilename reference =
+        action.loadReferencedObject(0, new MemoryMetadataProvider(), new 
Variables());
+    assertNotNull(reference);
+    assertEquals("${PROJECT_HOME}/scripts/setup.sh", reference.getFilename());
+  }
+
+  @Test
+  void loadReferencedObjectRejectsInvalidIndex() {
+    ActionShell action = new ActionShell();
+    action.insertScript = false;
+    action.setFilename("/scripts/setup.sh");
+
+    assertThrows(
+        HopException.class,
+        () -> action.loadReferencedObject(1, new MemoryMetadataProvider(), new 
Variables()));
+  }
+}
diff --git 
a/plugins/actions/sql/src/main/java/org/apache/hop/workflow/actions/sql/ActionSql.java
 
b/plugins/actions/sql/src/main/java/org/apache/hop/workflow/actions/sql/ActionSql.java
index cd6e654698..814762671f 100644
--- 
a/plugins/actions/sql/src/main/java/org/apache/hop/workflow/actions/sql/ActionSql.java
+++ 
b/plugins/actions/sql/src/main/java/org/apache/hop/workflow/actions/sql/ActionSql.java
@@ -33,6 +33,8 @@ import org.apache.hop.core.annotations.ActionTransformType;
 import org.apache.hop.core.database.Database;
 import org.apache.hop.core.database.DatabaseMeta;
 import org.apache.hop.core.exception.HopDatabaseException;
+import org.apache.hop.core.exception.HopException;
+import org.apache.hop.core.file.IHasFilename;
 import org.apache.hop.core.util.Utils;
 import org.apache.hop.core.variables.IVariables;
 import org.apache.hop.core.vfs.HopVfs;
@@ -248,4 +250,31 @@ public class ActionSql extends ActionBase implements 
Cloneable, IAction {
             remarks,
             
AndValidator.putValidators(ActionValidatorUtils.notBlankValidator()));
   }
+
+  @Override
+  public String[] getReferencedObjectDescriptions() {
+    if (!sqlFromFile) {
+      return null;
+    }
+    return new String[] {
+      BaseMessages.getString(PKG, "ActionSQL.ReferencedObject.Description"),
+    };
+  }
+
+  @Override
+  public boolean[] isReferencedObjectEnabled() {
+    if (!sqlFromFile) {
+      return null;
+    }
+    return new boolean[] {!Utils.isEmpty(sqlFilename)};
+  }
+
+  @Override
+  public IHasFilename loadReferencedObject(
+      int index, IHopMetadataProvider metadataProvider, IVariables variables) 
throws HopException {
+    if (index != 0 || !sqlFromFile || Utils.isEmpty(sqlFilename)) {
+      throw new HopException(BaseMessages.getString(PKG, 
"ActionSQL.NoSQLFileSpecified"));
+    }
+    return () -> sqlFilename;
+  }
 }
diff --git 
a/plugins/actions/sql/src/main/resources/org/apache/hop/workflow/actions/sql/messages/messages_en_US.properties
 
b/plugins/actions/sql/src/main/resources/org/apache/hop/workflow/actions/sql/messages/messages_en_US.properties
index 47825a9e1a..c912da207b 100644
--- 
a/plugins/actions/sql/src/main/resources/org/apache/hop/workflow/actions/sql/messages/messages_en_US.properties
+++ 
b/plugins/actions/sql/src/main/resources/org/apache/hop/workflow/actions/sql/messages/messages_en_US.properties
@@ -35,6 +35,7 @@ ActionSQL.Name.Default=SQL
 ActionSQL.Name.Label=Action name
 ActionSQL.NoDatabaseConnection=No database connection is defined.
 ActionSQL.NoSQLFileSpecified=Please specify SQL filename\!
+ActionSQL.ReferencedObject.Description=SQL file
 ActionSQL.Position.Label=Line {0} Column {1}
 ActionSQL.Script.Label=SQL Script\: 
 ActionSQL.SendOneStatement.Label=Send SQL as single statement
diff --git 
a/plugins/actions/sql/src/test/java/org/apache/hop/workflow/actions/sql/ActionSqlReferencedObjectTest.java
 
b/plugins/actions/sql/src/test/java/org/apache/hop/workflow/actions/sql/ActionSqlReferencedObjectTest.java
new file mode 100644
index 0000000000..581a2fc2b6
--- /dev/null
+++ 
b/plugins/actions/sql/src/test/java/org/apache/hop/workflow/actions/sql/ActionSqlReferencedObjectTest.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hop.workflow.actions.sql;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.apache.hop.core.exception.HopException;
+import org.apache.hop.core.file.IHasFilename;
+import org.apache.hop.core.variables.Variables;
+import org.apache.hop.junit.rules.RestoreHopEngineEnvironmentExtension;
+import org.apache.hop.metadata.serializer.memory.MemoryMetadataProvider;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+class ActionSqlReferencedObjectTest {
+
+  @RegisterExtension
+  static RestoreHopEngineEnvironmentExtension env = new 
RestoreHopEngineEnvironmentExtension();
+
+  @Test
+  void noReferencesWhenSqlIsInline() {
+    ActionSql action = new ActionSql();
+    action.setSqlFromFile(false);
+    action.setSqlFilename("/some/query.sql");
+
+    assertNull(action.getReferencedObjectDescriptions());
+    assertNull(action.isReferencedObjectEnabled());
+  }
+
+  @Test
+  void referencedObjectDisabledWhenFilenameEmpty() {
+    ActionSql action = new ActionSql();
+    action.setSqlFromFile(true);
+    action.setSqlFilename("");
+
+    assertEquals(1, action.getReferencedObjectDescriptions().length);
+    assertFalse(action.isReferencedObjectEnabled()[0]);
+  }
+
+  @Test
+  void referencedObjectEnabledWhenFilenameSet() throws HopException {
+    ActionSql action = new ActionSql();
+    action.setSqlFromFile(true);
+    action.setSqlFilename("${PROJECT_HOME}/queries/setup.sql");
+
+    assertEquals(1, action.getReferencedObjectDescriptions().length);
+    assertTrue(action.isReferencedObjectEnabled()[0]);
+
+    IHasFilename reference =
+        action.loadReferencedObject(0, new MemoryMetadataProvider(), new 
Variables());
+    assertNotNull(reference);
+    assertEquals("${PROJECT_HOME}/queries/setup.sql", reference.getFilename());
+  }
+
+  @Test
+  void loadReferencedObjectRejectsInvalidIndex() {
+    ActionSql action = new ActionSql();
+    action.setSqlFromFile(true);
+    action.setSqlFilename("/queries/setup.sql");
+
+    assertThrows(
+        HopException.class,
+        () -> action.loadReferencedObject(1, new MemoryMetadataProvider(), new 
Variables()));
+  }
+}
diff --git 
a/plugins/transforms/textfile/src/main/java/org/apache/hop/pipeline/transforms/types/BatExplorerFileType.java
 
b/plugins/transforms/textfile/src/main/java/org/apache/hop/pipeline/transforms/types/BatExplorerFileType.java
new file mode 100644
index 0000000000..e3d1796686
--- /dev/null
+++ 
b/plugins/transforms/textfile/src/main/java/org/apache/hop/pipeline/transforms/types/BatExplorerFileType.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hop.pipeline.transforms.types;
+
+import org.apache.hop.core.exception.HopException;
+import org.apache.hop.core.variables.IVariables;
+import org.apache.hop.ui.hopgui.HopGui;
+import org.apache.hop.ui.hopgui.file.HopFileTypePlugin;
+import org.apache.hop.ui.hopgui.file.IHopFileType;
+import org.apache.hop.ui.hopgui.file.IHopFileTypeHandler;
+import org.apache.hop.ui.hopgui.file.empty.EmptyHopFileTypeHandler;
+import org.apache.hop.ui.hopgui.perspective.explorer.ExplorerFile;
+import org.apache.hop.ui.hopgui.perspective.explorer.ExplorerPerspective;
+import 
org.apache.hop.ui.hopgui.perspective.explorer.file.capabilities.FileTypeCapabilities;
+import 
org.apache.hop.ui.hopgui.perspective.explorer.file.types.text.BaseTextExplorerFileType;
+
+@HopFileTypePlugin(
+    id = "BatExplorerFileType",
+    name = "Windows Batch File Type",
+    description = "Batch file handling in the explorer perspective",
+    image = "ui/images/script.svg")
+public class BatExplorerFileType extends 
BaseTextExplorerFileType<TextExplorerFileTypeHandler> {
+
+  public BatExplorerFileType() {
+    super(
+        "Batch file",
+        ".bat",
+        new String[] {"*.bat", "*.BAT"},
+        new String[] {"Batch files"},
+        FileTypeCapabilities.getCapabilities(
+            IHopFileType.CAPABILITY_SAVE,
+            IHopFileType.CAPABILITY_SAVE_AS,
+            IHopFileType.CAPABILITY_CLOSE,
+            IHopFileType.CAPABILITY_FILE_HISTORY,
+            IHopFileType.CAPABILITY_COPY,
+            IHopFileType.CAPABILITY_SELECT));
+  }
+
+  @Override
+  public TextExplorerFileTypeHandler createFileTypeHandler(
+      HopGui hopGui, ExplorerPerspective perspective, ExplorerFile file) {
+    return new TextExplorerFileTypeHandler(hopGui, perspective, file);
+  }
+
+  @Override
+  public IHopFileTypeHandler newFile(HopGui hopGui, IVariables 
parentVariableSpace)
+      throws HopException {
+    return new EmptyHopFileTypeHandler();
+  }
+}
diff --git 
a/plugins/transforms/textfile/src/main/java/org/apache/hop/pipeline/transforms/types/PythonExplorerFileType.java
 
b/plugins/transforms/textfile/src/main/java/org/apache/hop/pipeline/transforms/types/PythonExplorerFileType.java
new file mode 100644
index 0000000000..3d61448134
--- /dev/null
+++ 
b/plugins/transforms/textfile/src/main/java/org/apache/hop/pipeline/transforms/types/PythonExplorerFileType.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hop.pipeline.transforms.types;
+
+import org.apache.hop.core.exception.HopException;
+import org.apache.hop.core.variables.IVariables;
+import org.apache.hop.ui.hopgui.HopGui;
+import org.apache.hop.ui.hopgui.file.HopFileTypePlugin;
+import org.apache.hop.ui.hopgui.file.IHopFileType;
+import org.apache.hop.ui.hopgui.file.IHopFileTypeHandler;
+import org.apache.hop.ui.hopgui.file.empty.EmptyHopFileTypeHandler;
+import org.apache.hop.ui.hopgui.perspective.explorer.ExplorerFile;
+import org.apache.hop.ui.hopgui.perspective.explorer.ExplorerPerspective;
+import 
org.apache.hop.ui.hopgui.perspective.explorer.file.capabilities.FileTypeCapabilities;
+import 
org.apache.hop.ui.hopgui.perspective.explorer.file.types.text.BaseTextExplorerFileType;
+
+@HopFileTypePlugin(
+    id = "PythonExplorerFileType",
+    name = "Python Script File Type",
+    description = "Python file handling in the explorer perspective",
+    image = "python.svg")
+public class PythonExplorerFileType
+    extends BaseTextExplorerFileType<PythonExplorerFileTypeHandler> {
+
+  public PythonExplorerFileType() {
+    super(
+        "Python script",
+        ".py",
+        new String[] {"*.py"},
+        new String[] {"Python scripts"},
+        FileTypeCapabilities.getCapabilities(
+            IHopFileType.CAPABILITY_SAVE,
+            IHopFileType.CAPABILITY_SAVE_AS,
+            IHopFileType.CAPABILITY_CLOSE,
+            IHopFileType.CAPABILITY_FILE_HISTORY,
+            IHopFileType.CAPABILITY_COPY,
+            IHopFileType.CAPABILITY_SELECT));
+  }
+
+  @Override
+  public PythonExplorerFileTypeHandler createFileTypeHandler(
+      HopGui hopGui, ExplorerPerspective perspective, ExplorerFile file) {
+    return new PythonExplorerFileTypeHandler(hopGui, perspective, file);
+  }
+
+  @Override
+  public IHopFileTypeHandler newFile(HopGui hopGui, IVariables 
parentVariableSpace)
+      throws HopException {
+    return new EmptyHopFileTypeHandler();
+  }
+}
diff --git 
a/plugins/transforms/textfile/src/main/java/org/apache/hop/pipeline/transforms/types/PythonExplorerFileTypeHandler.java
 
b/plugins/transforms/textfile/src/main/java/org/apache/hop/pipeline/transforms/types/PythonExplorerFileTypeHandler.java
new file mode 100644
index 0000000000..9f2a1967b6
--- /dev/null
+++ 
b/plugins/transforms/textfile/src/main/java/org/apache/hop/pipeline/transforms/types/PythonExplorerFileTypeHandler.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hop.pipeline.transforms.types;
+
+import org.apache.hop.ui.hopgui.HopGui;
+import org.apache.hop.ui.hopgui.perspective.explorer.ExplorerFile;
+import org.apache.hop.ui.hopgui.perspective.explorer.ExplorerPerspective;
+import 
org.apache.hop.ui.hopgui.perspective.explorer.file.types.text.BaseTextExplorerFileTypeHandler;
+
+/** Handler for Python script files in the file explorer perspective 
(syntax-highlighted edit). */
+public class PythonExplorerFileTypeHandler extends 
BaseTextExplorerFileTypeHandler {
+
+  public PythonExplorerFileTypeHandler(
+      HopGui hopGui, ExplorerPerspective perspective, ExplorerFile 
explorerFile) {
+    super(hopGui, perspective, explorerFile);
+  }
+
+  @Override
+  protected String getLanguageId() {
+    return "python";
+  }
+}
diff --git 
a/plugins/transforms/textfile/src/main/java/org/apache/hop/pipeline/transforms/types/ShellExplorerFileType.java
 
b/plugins/transforms/textfile/src/main/java/org/apache/hop/pipeline/transforms/types/ShellExplorerFileType.java
new file mode 100644
index 0000000000..c95ae4f29c
--- /dev/null
+++ 
b/plugins/transforms/textfile/src/main/java/org/apache/hop/pipeline/transforms/types/ShellExplorerFileType.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hop.pipeline.transforms.types;
+
+import org.apache.hop.core.exception.HopException;
+import org.apache.hop.core.variables.IVariables;
+import org.apache.hop.ui.hopgui.HopGui;
+import org.apache.hop.ui.hopgui.file.HopFileTypePlugin;
+import org.apache.hop.ui.hopgui.file.IHopFileType;
+import org.apache.hop.ui.hopgui.file.IHopFileTypeHandler;
+import org.apache.hop.ui.hopgui.file.empty.EmptyHopFileTypeHandler;
+import org.apache.hop.ui.hopgui.perspective.explorer.ExplorerFile;
+import org.apache.hop.ui.hopgui.perspective.explorer.ExplorerPerspective;
+import 
org.apache.hop.ui.hopgui.perspective.explorer.file.capabilities.FileTypeCapabilities;
+import 
org.apache.hop.ui.hopgui.perspective.explorer.file.types.text.BaseTextExplorerFileType;
+
+@HopFileTypePlugin(
+    id = "ShellExplorerFileType",
+    name = "Shell File Type",
+    description = "Shell file handling in the explorer perspective",
+    image = "ui/images/script.svg")
+public class ShellExplorerFileType extends 
BaseTextExplorerFileType<TextExplorerFileTypeHandler> {
+
+  public ShellExplorerFileType() {
+    super(
+        "Shell Script",
+        ".sh",
+        new String[] {"*.sh"},
+        new String[] {"Shell scripts"},
+        FileTypeCapabilities.getCapabilities(
+            IHopFileType.CAPABILITY_SAVE,
+            IHopFileType.CAPABILITY_SAVE_AS,
+            IHopFileType.CAPABILITY_CLOSE,
+            IHopFileType.CAPABILITY_FILE_HISTORY,
+            IHopFileType.CAPABILITY_COPY,
+            IHopFileType.CAPABILITY_SELECT));
+  }
+
+  @Override
+  public TextExplorerFileTypeHandler createFileTypeHandler(
+      HopGui hopGui, ExplorerPerspective perspective, ExplorerFile file) {
+    return new TextExplorerFileTypeHandler(hopGui, perspective, file);
+  }
+
+  @Override
+  public IHopFileTypeHandler newFile(HopGui hopGui, IVariables 
parentVariableSpace)
+      throws HopException {
+    return new EmptyHopFileTypeHandler();
+  }
+}
diff --git a/plugins/transforms/textfile/src/main/resources/python.svg 
b/plugins/transforms/textfile/src/main/resources/python.svg
new file mode 100644
index 0000000000..f11a7387b3
--- /dev/null
+++ b/plugins/transforms/textfile/src/main/resources/python.svg
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg";
+     x="0px" y="0px" width="110px" height="110px"
+     viewBox="0.21 -0.077 110 110"
+     enable-background="new 0.21 -0.077 110 110" xml:space="preserve">
+  <linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="63.8159" 
y1="56.6829"
+                  x2="118.4934" y2="1.8225"
+                  gradientTransform="matrix(1 0 0 -1 -53.2974 66.4321)">
+      <stop offset="0" style="stop-color:#387EB8"/>
+      <stop offset="1" style="stop-color:#366994"/>
+  </linearGradient>
+    <path fill="url(#SVGID_1_)"
+          
d="M55.023-0.077c-25.971,0-26.25,10.081-26.25,12.156c0,3.148,0,12.594,0,12.594h26.75v3.781
+        
c0,0-27.852,0-37.375,0c-7.949,0-17.938,4.833-17.938,26.25c0,19.673,7.792,27.281,15.656,
+        27.281c2.335,0,9.344,0,9.344,0 
s0-9.765,0-13.125c0-5.491,2.721-15.656,15.406-15.656c15.91,
+        0,19.971,0,26.531,0c3.902,0,14.906-1.696,14.906-14.406 
c0-13.452,0-17.89,
+        0-24.219C82.054,11.426,81.515-0.077,55.023-0.077z 
M40.273,8.392c2.662,0,4.813,2.15,
+        4.813,4.813 
c0,2.661-2.151,4.813-4.813,4.813s-4.813-2.151-4.813-4.813C35.46,10.542,
+        37.611,8.392,40.273,8.392z"/>
+    <linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="97.0444" 
y1="21.6321"
+                    x2="155.6665" y2="-34.5308"
+                    gradientTransform="matrix(1 0 0 -1 -53.2974 66.4321)">
+        <stop offset="0" style="stop-color:#FFE052"/>
+        <stop offset="1" style="stop-color:#FFC331"/>
+    </linearGradient>
+    <path fill="url(#SVGID_2_)" 
d="M55.397,109.923c25.959,0,26.282-10.271,26.282-12.156c0-3.148,
+      0-12.594,0-12.594H54.897v-3.781 
c0,0,28.032,0,37.375,0c8.009,0,17.938-4.954,
+      
17.938-26.25c0-23.322-10.538-27.281-15.656-27.281c-2.336,0-9.344,0-9.344,0 
s0,10.216,
+      
0,13.125c0,5.491-2.631,15.656-15.406,15.656c-15.91,0-19.476,0-26.532,0c-3.892,0-14.906,1.896-14.906,14.406
+      
c0,14.475,0,18.265,0,24.219C28.366,100.497,31.562,109.923,55.397,109.923z 
M70.148,101.454c-2.662,
+      0-4.813-2.151-4.813-4.813 
s2.15-4.813,4.813-4.813c2.661,0,4.813,2.151,4.813,4.813S72.809,101.454,
+      70.148,101.454z"/>
+</svg>
\ No newline at end of file
diff --git 
a/plugins/transforms/textfile/src/test/java/org/apache/hop/pipeline/transforms/types/PythonExplorerFileTypeTest.java
 
b/plugins/transforms/textfile/src/test/java/org/apache/hop/pipeline/transforms/types/PythonExplorerFileTypeTest.java
new file mode 100644
index 0000000000..1e0b25af3a
--- /dev/null
+++ 
b/plugins/transforms/textfile/src/test/java/org/apache/hop/pipeline/transforms/types/PythonExplorerFileTypeTest.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hop.pipeline.transforms.types;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.lang.reflect.Method;
+import org.apache.hop.ui.hopgui.file.IHopFileType;
+import 
org.apache.hop.ui.hopgui.perspective.explorer.file.types.text.BaseTextExplorerFileTypeHandler;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+class PythonExplorerFileTypeTest {
+
+  private PythonExplorerFileType fileType;
+
+  @BeforeEach
+  void setUp() {
+    fileType = new PythonExplorerFileType();
+  }
+
+  @Test
+  void testConstructor() {
+    assertNotNull(fileType);
+  }
+
+  @Test
+  void testGetDefaultFileExtension() {
+    assertEquals(".py", fileType.getDefaultFileExtension());
+  }
+
+  @Test
+  void testGetFilterExtensions() {
+    String[] extensions = fileType.getFilterExtensions();
+    assertNotNull(extensions);
+    assertEquals(1, extensions.length);
+    assertEquals("*.py", extensions[0]);
+  }
+
+  @Test
+  void testGetFilterNames() {
+    String[] names = fileType.getFilterNames();
+    assertNotNull(names);
+    assertEquals(1, names.length);
+    assertEquals("Python scripts", names[0]);
+  }
+
+  @Test
+  void testHasExpectedCapabilities() {
+    assertTrue(fileType.hasCapability(IHopFileType.CAPABILITY_SAVE));
+    assertTrue(fileType.hasCapability(IHopFileType.CAPABILITY_SAVE_AS));
+    assertTrue(fileType.hasCapability(IHopFileType.CAPABILITY_CLOSE));
+    assertTrue(fileType.hasCapability(IHopFileType.CAPABILITY_FILE_HISTORY));
+    assertTrue(fileType.hasCapability(IHopFileType.CAPABILITY_COPY));
+    assertTrue(fileType.hasCapability(IHopFileType.CAPABILITY_SELECT));
+    assertFalse(fileType.hasCapability(IHopFileType.CAPABILITY_NEW));
+  }
+
+  @Test
+  void testCreateFileTypeHandlerReturnsPythonHandler() {
+    assertInstanceOf(
+        PythonExplorerFileTypeHandler.class, 
fileType.createFileTypeHandler(null, null, null));
+  }
+
+  @Test
+  void testHandlerReturnsPythonLanguageId() throws Exception {
+    PythonExplorerFileTypeHandler handler = new 
PythonExplorerFileTypeHandler(null, null, null);
+    Method method = 
BaseTextExplorerFileTypeHandler.class.getDeclaredMethod("getLanguageId");
+    method.setAccessible(true);
+    assertEquals("python", method.invoke(handler));
+  }
+}
diff --git 
a/rcp/src/main/java/org/apache/hop/ui/hopgui/ContentEditorTm4eSupport.java 
b/rcp/src/main/java/org/apache/hop/ui/hopgui/ContentEditorTm4eSupport.java
index d80f68d1d0..5725c07b68 100644
--- a/rcp/src/main/java/org/apache/hop/ui/hopgui/ContentEditorTm4eSupport.java
+++ b/rcp/src/main/java/org/apache/hop/ui/hopgui/ContentEditorTm4eSupport.java
@@ -52,13 +52,15 @@ final class ContentEditorTm4eSupport {
   private static final String SCOPE_JSON = "source.json";
   private static final String SCOPE_XML = "text.xml";
   private static final String SCOPE_SQL = "source.sql";
+  private static final String SCOPE_PYTHON = "source.python";
 
   /** Maps TM4E scope names to grammar resource filenames (classpath-relative 
to grammars/). */
   private static final Map<String, String> GRAMMAR_FILES =
       Map.of(
           SCOPE_JSON, "json.json",
           SCOPE_XML, "xml.json",
-          SCOPE_SQL, "sql.json");
+          SCOPE_SQL, "sql.json",
+          SCOPE_PYTHON, "python.json");
 
   // Same palette as before (light/dark) for consistency
   private static final RGB L_COMMENT = new RGB(128, 128, 128);
@@ -107,6 +109,9 @@ final class ContentEditorTm4eSupport {
         return SCOPE_XML;
       case "sql":
         return SCOPE_SQL;
+      case "python":
+      case "py":
+        return SCOPE_PYTHON;
       default:
         return null;
     }
diff --git 
a/rcp/src/main/java/org/apache/hop/ui/hopgui/RuleBasedSourceViewerConfiguration.java
 
b/rcp/src/main/java/org/apache/hop/ui/hopgui/RuleBasedSourceViewerConfiguration.java
index 91db2f17c4..fef246f722 100644
--- 
a/rcp/src/main/java/org/apache/hop/ui/hopgui/RuleBasedSourceViewerConfiguration.java
+++ 
b/rcp/src/main/java/org/apache/hop/ui/hopgui/RuleBasedSourceViewerConfiguration.java
@@ -22,7 +22,8 @@ import org.eclipse.swt.widgets.Display;
 
 /**
  * Builds a {@link SourceViewerConfiguration} for the content editor. Uses 
TM4E with TextMate
- * grammars for syntax highlighting of JSON, XML, and SQL; other languages get 
a plain config.
+ * grammars for syntax highlighting of JSON, XML, SQL, and Python; other 
languages get a plain
+ * config.
  */
 public final class RuleBasedSourceViewerConfiguration {
 
@@ -30,7 +31,7 @@ public final class RuleBasedSourceViewerConfiguration {
 
   /**
    * Creates a configuration for the given language. Uses TM4E when a grammar 
is available (json,
-   * xml, sql); otherwise returns a plain configuration with no syntax 
highlighting.
+   * xml, sql, python); otherwise returns a plain configuration with no syntax 
highlighting.
    *
    * @param languageId language id (e.g. "json", "xml", "sql"), or null for 
plain text
    * @return configuration, never null
diff --git 
a/rcp/src/main/resources/org/apache/hop/ui/hopgui/grammars/python.json 
b/rcp/src/main/resources/org/apache/hop/ui/hopgui/grammars/python.json
new file mode 100644
index 0000000000..91a2c8e756
--- /dev/null
+++ b/rcp/src/main/resources/org/apache/hop/ui/hopgui/grammars/python.json
@@ -0,0 +1,4213 @@
+{
+       "information_for_contributors": [
+               "This file has been converted from 
https://github.com/MagicStack/MagicPython/blob/master/grammars/MagicPython.tmLanguage";,
+               "If you want to provide a fix or improvement, please create a 
pull request against the original repository.",
+               "Once accepted there, we are happy to receive an update 
request."
+       ],
+       "version": 
"https://github.com/MagicStack/MagicPython/commit/7d0f2b22a5ad8fccbd7341bc7b7a715169283044";,
+       "name": "MagicPython",
+       "scopeName": "source.python",
+       "patterns": [
+               {
+                       "include": "#statement"
+               },
+               {
+                       "include": "#expression"
+               }
+       ],
+       "repository": {
+               "impossible": {
+                       "comment": "This is a special rule that should be used 
where no match is desired. It is not a good idea to match something like '1{0}' 
because in some cases that can result in infinite loops in token generation. So 
the rule instead matches and impossible expression to allow a match to fail and 
move to the next token.",
+                       "match": "$.^"
+               },
+               "statement": {
+                       "patterns": [
+                               {
+                                       "include": "#import"
+                               },
+                               {
+                                       "include": "#class-declaration"
+                               },
+                               {
+                                       "include": "#function-declaration"
+                               },
+                               {
+                                       "include": "#generator"
+                               },
+                               {
+                                       "include": "#statement-keyword"
+                               },
+                               {
+                                       "include": "#assignment-operator"
+                               },
+                               {
+                                       "include": "#decorator"
+                               },
+                               {
+                                       "include": "#docstring-statement"
+                               },
+                               {
+                                       "include": "#semicolon"
+                               }
+                       ]
+               },
+               "semicolon": {
+                       "patterns": [
+                               {
+                                       "name": 
"invalid.deprecated.semicolon.python",
+                                       "match": "\\;$"
+                               }
+                       ]
+               },
+               "comments": {
+                       "patterns": [
+                               {
+                                       "name": 
"comment.line.number-sign.python",
+                                       "contentName": 
"meta.typehint.comment.python",
+                                       "begin": "(?x)\n  (?:\n    \\# \\s* 
(type:)\n    \\s*+ (?# we want `\\s*+` which is possessive quantifier since\n   
          we do not actually want to backtrack when matching\n             
whitespace here)\n    (?! $ | \\#)\n  )\n",
+                                       "end": "(?:$|(?=\\#))",
+                                       "beginCaptures": {
+                                               "0": {
+                                                       "name": 
"meta.typehint.comment.python"
+                                               },
+                                               "1": {
+                                                       "name": 
"comment.typehint.directive.notation.python"
+                                               }
+                                       },
+                                       "patterns": [
+                                               {
+                                                       "name": 
"comment.typehint.ignore.notation.python",
+                                                       "match": "(?x)\n  \\G 
ignore\n  (?= \\s* (?: $ | \\#))\n"
+                                               },
+                                               {
+                                                       "name": 
"comment.typehint.type.notation.python",
+                                                       "match": "(?x)\n  
(?<!\\.)\\b(\n    bool | bytes | float | int | object | str\n    | List | Dict 
| Iterable | Sequence | Set\n    | FrozenSet | Callable | Union | Tuple\n    | 
Any | None\n  )\\b\n"
+                                               },
+                                               {
+                                                       "name": 
"comment.typehint.punctuation.notation.python",
+                                                       "match": 
"([\\[\\]\\(\\),\\.\\=\\*]|(->))"
+                                               },
+                                               {
+                                                       "name": 
"comment.typehint.variable.notation.python",
+                                                       "match": 
"([[:alpha:]_]\\w*)"
+                                               }
+                                       ]
+                               },
+                               {
+                                       "include": "#comments-base"
+                               }
+                       ]
+               },
+               "docstring-statement": {
+                       "begin": 
"^(?=\\s*[rR]?(\\'\\'\\'|\\\"\\\"\\\"|\\'|\\\"))",
+                       "comment": "the string either terminates correctly or 
by the beginning of a new line (this is for single line docstrings that aren't 
terminated) AND it's not followed by another docstring",
+                       "end": 
"((?<=\\1)|^)(?!\\s*[rR]?(\\'\\'\\'|\\\"\\\"\\\"|\\'|\\\"))",
+                       "patterns": [
+                               {
+                                       "include": "#docstring"
+                               }
+                       ]
+               },
+               "docstring": {
+                       "patterns": [
+                               {
+                                       "name": 
"string.quoted.docstring.multi.python",
+                                       "begin": "(\\'\\'\\'|\\\"\\\"\\\")",
+                                       "end": "(\\1)",
+                                       "beginCaptures": {
+                                               "1": {
+                                                       "name": 
"punctuation.definition.string.begin.python"
+                                               }
+                                       },
+                                       "endCaptures": {
+                                               "1": {
+                                                       "name": 
"punctuation.definition.string.end.python"
+                                               }
+                                       },
+                                       "patterns": [
+                                               {
+                                                       "include": 
"#docstring-prompt"
+                                               },
+                                               {
+                                                       "include": "#codetags"
+                                               },
+                                               {
+                                                       "include": 
"#docstring-guts-unicode"
+                                               }
+                                       ]
+                               },
+                               {
+                                       "name": 
"string.quoted.docstring.raw.multi.python",
+                                       "begin": 
"([rR])(\\'\\'\\'|\\\"\\\"\\\")",
+                                       "end": "(\\2)",
+                                       "beginCaptures": {
+                                               "1": {
+                                                       "name": 
"storage.type.string.python"
+                                               },
+                                               "2": {
+                                                       "name": 
"punctuation.definition.string.begin.python"
+                                               }
+                                       },
+                                       "endCaptures": {
+                                               "1": {
+                                                       "name": 
"punctuation.definition.string.end.python"
+                                               }
+                                       },
+                                       "patterns": [
+                                               {
+                                                       "include": 
"#string-consume-escape"
+                                               },
+                                               {
+                                                       "include": 
"#docstring-prompt"
+                                               },
+                                               {
+                                                       "include": "#codetags"
+                                               }
+                                       ]
+                               },
+                               {
+                                       "name": 
"string.quoted.docstring.single.python",
+                                       "begin": "(\\'|\\\")",
+                                       "end": "(\\1)|(\\n)",
+                                       "beginCaptures": {
+                                               "1": {
+                                                       "name": 
"punctuation.definition.string.begin.python"
+                                               }
+                                       },
+                                       "endCaptures": {
+                                               "1": {
+                                                       "name": 
"punctuation.definition.string.end.python"
+                                               },
+                                               "2": {
+                                                       "name": 
"invalid.illegal.newline.python"
+                                               }
+                                       },
+                                       "patterns": [
+                                               {
+                                                       "include": "#codetags"
+                                               },
+                                               {
+                                                       "include": 
"#docstring-guts-unicode"
+                                               }
+                                       ]
+                               },
+                               {
+                                       "name": 
"string.quoted.docstring.raw.single.python",
+                                       "begin": "([rR])(\\'|\\\")",
+                                       "end": "(\\2)|(\\n)",
+                                       "beginCaptures": {
+                                               "1": {
+                                                       "name": 
"storage.type.string.python"
+                                               },
+                                               "2": {
+                                                       "name": 
"punctuation.definition.string.begin.python"
+                                               }
+                                       },
+                                       "endCaptures": {
+                                               "1": {
+                                                       "name": 
"punctuation.definition.string.end.python"
+                                               },
+                                               "2": {
+                                                       "name": 
"invalid.illegal.newline.python"
+                                               }
+                                       },
+                                       "patterns": [
+                                               {
+                                                       "include": 
"#string-consume-escape"
+                                               },
+                                               {
+                                                       "include": "#codetags"
+                                               }
+                                       ]
+                               }
+                       ]
+               },
+               "docstring-guts-unicode": {
+                       "patterns": [
+                               {
+                                       "include": "#escape-sequence-unicode"
+                               },
+                               {
+                                       "include": "#escape-sequence"
+                               },
+                               {
+                                       "include": "#string-line-continuation"
+                               }
+                       ]
+               },
+               "docstring-prompt": {
+                       "match": "(?x)\n  (?:\n    (?:^|\\G) \\s* (?# '\\G' is 
necessary for ST)\n    ((?:>>>|\\.\\.\\.) \\s) (?=\\s*\\S)\n  )\n",
+                       "captures": {
+                               "1": {
+                                       "name": "keyword.control.flow.python"
+                               }
+                       }
+               },
+               "statement-keyword": {
+                       "patterns": [
+                               {
+                                       "name": "storage.type.function.python",
+                                       "match": "\\b((async\\s+)?\\s*def)\\b"
+                               },
+                               {
+                                       "name": "keyword.control.flow.python",
+                                       "comment": "if `as` is eventually 
followed by `:` or line continuation\nit's probably control flow like:\n    
with foo as bar, \\\n         Foo as Bar:\n      try:\n        do_stuff()\n     
 except Exception as e:\n        pass\n",
+                                       "match": "\\b(?<!\\.)as\\b(?=.*[:\\\\])"
+                               },
+                               {
+                                       "name": "keyword.control.import.python",
+                                       "comment": "other legal use of `as` is 
in an import",
+                                       "match": "\\b(?<!\\.)as\\b"
+                               },
+                               {
+                                       "name": "keyword.control.flow.python",
+                                       "match": "(?x)\n  \\b(?<!\\.)(\n    
async | continue | del | assert | break | finally | for\n    | from | elif | 
else | if | except | pass | raise\n    | return | try | while | with\n  )\\b\n"
+                               },
+                               {
+                                       "name": 
"storage.modifier.declaration.python",
+                                       "match": "(?x)\n  \\b(?<!\\.)(\n    
global | nonlocal\n  )\\b\n"
+                               },
+                               {
+                                       "name": "storage.type.class.python",
+                                       "match": "\\b(?<!\\.)(class)\\b"
+                               },
+                               {
+                                       "match": "(?x)\n  ^\\s*(\n    case | 
match\n  )(?=\\s*([-+\\w\\d(\\[{'\":#]|$))\\b\n",
+                                       "captures": {
+                                               "1": {
+                                                       "name": 
"keyword.control.flow.python"
+                                               }
+                                       }
+                               }
+                       ]
+               },
+               "expression-bare": {
+                       "comment": "valid Python expressions w/o comments and 
line continuation",
+                       "patterns": [
+                               {
+                                       "include": "#backticks"
+                               },
+                               {
+                                       "include": "#illegal-anno"
+                               },
+                               {
+                                       "include": "#literal"
+                               },
+                               {
+                                       "include": "#regexp"
+                               },
+                               {
+                                       "include": "#string"
+                               },
+                               {
+                                       "include": "#lambda"
+                               },
+                               {
+                                       "include": "#generator"
+                               },
+                               {
+                                       "include": "#illegal-operator"
+                               },
+                               {
+                                       "include": "#operator"
+                               },
+                               {
+                                       "include": "#curly-braces"
+                               },
+                               {
+                                       "include": "#item-access"
+                               },
+                               {
+                                       "include": "#list"
+                               },
+                               {
+                                       "include": "#odd-function-call"
+                               },
+                               {
+                                       "include": "#round-braces"
+                               },
+                               {
+                                       "include": "#function-call"
+                               },
+                               {
+                                       "include": "#builtin-functions"
+                               },
+                               {
+                                       "include": "#builtin-types"
+                               },
+                               {
+                                       "include": "#builtin-exceptions"
+                               },
+                               {
+                                       "include": "#magic-names"
+                               },
+                               {
+                                       "include": "#special-names"
+                               },
+                               {
+                                       "include": "#illegal-names"
+                               },
+                               {
+                                       "include": "#special-variables"
+                               },
+                               {
+                                       "include": "#ellipsis"
+                               },
+                               {
+                                       "include": "#punctuation"
+                               },
+                               {
+                                       "include": "#line-continuation"
+                               }
+                       ]
+               },
+               "expression-base": {
+                       "comment": "valid Python expressions with comments and 
line continuation",
+                       "patterns": [
+                               {
+                                       "include": "#comments"
+                               },
+                               {
+                                       "include": "#expression-bare"
+                               },
+                               {
+                                       "include": "#line-continuation"
+                               }
+                       ]
+               },
+               "expression": {
+                       "comment": "All valid Python expressions",
+                       "patterns": [
+                               {
+                                       "include": "#expression-base"
+                               },
+                               {
+                                       "include": "#member-access"
+                               },
+                               {
+                                       "comment": "Tokenize identifiers to 
help linters",
+                                       "match": "(?x) \\b ([[:alpha:]_]\\w*) 
\\b"
+                               }
+                       ]
+               },
+               "member-access": {
+                       "name": "meta.member.access.python",
+                       "begin": "(\\.)\\s*(?!\\.)",
+                       "end": "(?x)\n  # stop when you've just read 
non-whitespace followed by non-word\n  # i.e. when finished reading an 
identifier or function call\n  (?<=\\S)(?=\\W) |\n  # stop when seeing the 
start of something that's not a word,\n  # i.e. when seeing a non-identifier\n  
(^|(?<=\\s))(?=[^\\\\\\w\\s]) |\n  $\n",
+                       "beginCaptures": {
+                               "1": {
+                                       "name": 
"punctuation.separator.period.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": "#function-call"
+                               },
+                               {
+                                       "include": "#member-access-base"
+                               },
+                               {
+                                       "include": "#member-access-attribute"
+                               }
+                       ]
+               },
+               "member-access-base": {
+                       "patterns": [
+                               {
+                                       "include": "#magic-names"
+                               },
+                               {
+                                       "include": "#illegal-names"
+                               },
+                               {
+                                       "include": "#illegal-object-name"
+                               },
+                               {
+                                       "include": "#special-names"
+                               },
+                               {
+                                       "include": "#line-continuation"
+                               },
+                               {
+                                       "include": "#item-access"
+                               }
+                       ]
+               },
+               "member-access-attribute": {
+                       "comment": "Highlight attribute access in otherwise 
non-specialized cases.",
+                       "name": "meta.attribute.python",
+                       "match": "(?x)\n  \\b ([[:alpha:]_]\\w*) \\b\n"
+               },
+               "special-names": {
+                       "name": "constant.other.caps.python",
+                       "match": "(?x)\n  \\b\n    # we want to see \"enough\", 
meaning 2 or more upper-case\n    # letters in the beginning of the constant\n  
  #\n    # for more details refer to:\n    #   
https://github.com/MagicStack/MagicPython/issues/42\n    (\n      _* 
[[:upper:]] [_\\d]* [[:upper:]]\n    )\n    [[:upper:]\\d]* (_\\w*)?\n  \\b\n"
+               },
+               "curly-braces": {
+                       "begin": "\\{",
+                       "end": "\\}",
+                       "beginCaptures": {
+                               "0": {
+                                       "name": 
"punctuation.definition.dict.begin.python"
+                               }
+                       },
+                       "endCaptures": {
+                               "0": {
+                                       "name": 
"punctuation.definition.dict.end.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "name": 
"punctuation.separator.dict.python",
+                                       "match": ":"
+                               },
+                               {
+                                       "include": "#expression"
+                               }
+                       ]
+               },
+               "list": {
+                       "begin": "\\[",
+                       "end": "\\]",
+                       "beginCaptures": {
+                               "0": {
+                                       "name": 
"punctuation.definition.list.begin.python"
+                               }
+                       },
+                       "endCaptures": {
+                               "0": {
+                                       "name": 
"punctuation.definition.list.end.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": "#expression"
+                               }
+                       ]
+               },
+               "odd-function-call": {
+                       "comment": "A bit obscured function call where there 
may have been an\narbitrary number of other operations to get the 
function.\nE.g. \"arr[idx](args)\"\n",
+                       "begin": "(?x)\n  (?<= \\] | \\) ) \\s*\n  (?=\\()\n",
+                       "end": "(\\))",
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"punctuation.definition.arguments.end.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": "#function-arguments"
+                               }
+                       ]
+               },
+               "round-braces": {
+                       "begin": "\\(",
+                       "end": "\\)",
+                       "beginCaptures": {
+                               "0": {
+                                       "name": 
"punctuation.parenthesis.begin.python"
+                               }
+                       },
+                       "endCaptures": {
+                               "0": {
+                                       "name": 
"punctuation.parenthesis.end.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": "#expression"
+                               }
+                       ]
+               },
+               "line-continuation": {
+                       "patterns": [
+                               {
+                                       "match": "(\\\\)\\s*(\\S.*$\\n?)",
+                                       "captures": {
+                                               "1": {
+                                                       "name": 
"punctuation.separator.continuation.line.python"
+                                               },
+                                               "2": {
+                                                       "name": 
"invalid.illegal.line.continuation.python"
+                                               }
+                                       }
+                               },
+                               {
+                                       "begin": "(\\\\)\\s*$\\n?",
+                                       "end": "(?x)\n  (?=^\\s*$)\n  |\n  (?! 
(\\s* [rR]? (\\'\\'\\'|\\\"\\\"\\\"|\\'|\\\"))\n      |\n      (\\G $)  (?# 
'\\G' is necessary for ST)\n  )\n",
+                                       "beginCaptures": {
+                                               "1": {
+                                                       "name": 
"punctuation.separator.continuation.line.python"
+                                               }
+                                       },
+                                       "patterns": [
+                                               {
+                                                       "include": "#regexp"
+                                               },
+                                               {
+                                                       "include": "#string"
+                                               }
+                                       ]
+                               }
+                       ]
+               },
+               "assignment-operator": {
+                       "name": "keyword.operator.assignment.python",
+                       "match": "(?x)\n     <<= | >>= | //= | \\*\\*=\n    | 
\\+= | -= | /= | @=\n    | \\*= | %= | ~= | \\^= | &= | \\|=\n    | =(?!=)\n"
+               },
+               "operator": {
+                       "match": "(?x)\n    \\b(?<!\\.)\n      (?:\n        
(and | or | not | in | is)                         (?# 1)\n        |\n        
(for | if | else | await | (?:yield(?:\\s+from)?))  (?# 2)\n      )\n    
(?!\\s*:)\\b\n\n    | (<< | >> | & | \\| | \\^ | ~)                          
(?# 3)\n\n    | (\\*\\* | \\* | \\+ | - | % | // | / | @)                (?# 
4)\n\n    | (!= | == | >= | <= | < | >)                          (?# 5)\n\n    
| (:=)                                                [...]
+                       "captures": {
+                               "1": {
+                                       "name": 
"keyword.operator.logical.python"
+                               },
+                               "2": {
+                                       "name": "keyword.control.flow.python"
+                               },
+                               "3": {
+                                       "name": 
"keyword.operator.bitwise.python"
+                               },
+                               "4": {
+                                       "name": 
"keyword.operator.arithmetic.python"
+                               },
+                               "5": {
+                                       "name": 
"keyword.operator.comparison.python"
+                               },
+                               "6": {
+                                       "name": 
"keyword.operator.assignment.python"
+                               }
+                       }
+               },
+               "punctuation": {
+                       "patterns": [
+                               {
+                                       "name": 
"punctuation.separator.colon.python",
+                                       "match": ":"
+                               },
+                               {
+                                       "name": 
"punctuation.separator.element.python",
+                                       "match": ","
+                               }
+                       ]
+               },
+               "literal": {
+                       "patterns": [
+                               {
+                                       "name": "constant.language.python",
+                                       "match": 
"\\b(True|False|None|NotImplemented|Ellipsis)\\b"
+                               },
+                               {
+                                       "include": "#number"
+                               }
+                       ]
+               },
+               "number": {
+                       "name": "constant.numeric.python",
+                       "patterns": [
+                               {
+                                       "include": "#number-float"
+                               },
+                               {
+                                       "include": "#number-dec"
+                               },
+                               {
+                                       "include": "#number-hex"
+                               },
+                               {
+                                       "include": "#number-oct"
+                               },
+                               {
+                                       "include": "#number-bin"
+                               },
+                               {
+                                       "include": "#number-long"
+                               },
+                               {
+                                       "name": "invalid.illegal.name.python",
+                                       "match": "\\b[0-9]+\\w+"
+                               }
+                       ]
+               },
+               "number-float": {
+                       "name": "constant.numeric.float.python",
+                       "match": "(?x)\n  (?<! \\w)(?:\n    (?:\n      
\\.[0-9](?: _?[0-9] )*\n      |\n      [0-9](?: _?[0-9] )* \\. [0-9](?: _?[0-9] 
)*\n      |\n      [0-9](?: _?[0-9] )* \\.\n    ) (?: [eE][+-]?[0-9](?: _?[0-9] 
)* )?\n    |\n    [0-9](?: _?[0-9] )* (?: [eE][+-]?[0-9](?: _?[0-9] )* )\n  
)([jJ])?\\b\n",
+                       "captures": {
+                               "1": {
+                                       "name": 
"storage.type.imaginary.number.python"
+                               }
+                       }
+               },
+               "number-dec": {
+                       "name": "constant.numeric.dec.python",
+                       "match": "(?x)\n  (?<![\\w\\.])(?:\n      [1-9](?: 
_?[0-9] )*\n      |\n      0+\n      |\n      [0-9](?: _?[0-9] )* ([jJ])\n      
|\n      0 ([0-9]+)(?![eE\\.])\n  )\\b\n",
+                       "captures": {
+                               "1": {
+                                       "name": 
"storage.type.imaginary.number.python"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.dec.python"
+                               }
+                       }
+               },
+               "number-hex": {
+                       "name": "constant.numeric.hex.python",
+                       "match": "(?x)\n  (?<![\\w\\.])\n    (0[xX]) 
(_?[0-9a-fA-F])+\n  \\b\n",
+                       "captures": {
+                               "1": {
+                                       "name": "storage.type.number.python"
+                               }
+                       }
+               },
+               "number-oct": {
+                       "name": "constant.numeric.oct.python",
+                       "match": "(?x)\n  (?<![\\w\\.])\n    (0[oO]) 
(_?[0-7])+\n  \\b\n",
+                       "captures": {
+                               "1": {
+                                       "name": "storage.type.number.python"
+                               }
+                       }
+               },
+               "number-bin": {
+                       "name": "constant.numeric.bin.python",
+                       "match": "(?x)\n  (?<![\\w\\.])\n    (0[bB]) 
(_?[01])+\n  \\b\n",
+                       "captures": {
+                               "1": {
+                                       "name": "storage.type.number.python"
+                               }
+                       }
+               },
+               "number-long": {
+                       "name": "constant.numeric.bin.python",
+                       "comment": "this is to support python2 syntax for long 
ints",
+                       "match": "(?x)\n  (?<![\\w\\.])\n    ([1-9][0-9]* | 0) 
([lL])\n  \\b\n",
+                       "captures": {
+                               "2": {
+                                       "name": "storage.type.number.python"
+                               }
+                       }
+               },
+               "regexp": {
+                       "patterns": [
+                               {
+                                       "include": "#regexp-single-three-line"
+                               },
+                               {
+                                       "include": "#regexp-double-three-line"
+                               },
+                               {
+                                       "include": "#regexp-single-one-line"
+                               },
+                               {
+                                       "include": "#regexp-double-one-line"
+                               }
+                       ]
+               },
+               "string": {
+                       "patterns": [
+                               {
+                                       "include": "#string-quoted-multi-line"
+                               },
+                               {
+                                       "include": "#string-quoted-single-line"
+                               },
+                               {
+                                       "include": 
"#string-bin-quoted-multi-line"
+                               },
+                               {
+                                       "include": 
"#string-bin-quoted-single-line"
+                               },
+                               {
+                                       "include": 
"#string-raw-quoted-multi-line"
+                               },
+                               {
+                                       "include": 
"#string-raw-quoted-single-line"
+                               },
+                               {
+                                       "include": 
"#string-raw-bin-quoted-multi-line"
+                               },
+                               {
+                                       "include": 
"#string-raw-bin-quoted-single-line"
+                               },
+                               {
+                                       "include": 
"#fstring-fnorm-quoted-multi-line"
+                               },
+                               {
+                                       "include": 
"#fstring-fnorm-quoted-single-line"
+                               },
+                               {
+                                       "include": 
"#fstring-normf-quoted-multi-line"
+                               },
+                               {
+                                       "include": 
"#fstring-normf-quoted-single-line"
+                               },
+                               {
+                                       "include": 
"#fstring-raw-quoted-multi-line"
+                               },
+                               {
+                                       "include": 
"#fstring-raw-quoted-single-line"
+                               }
+                       ]
+               },
+               "string-unicode-guts": {
+                       "patterns": [
+                               {
+                                       "include": "#escape-sequence-unicode"
+                               },
+                               {
+                                       "include": "#string-entity"
+                               },
+                               {
+                                       "include": "#string-brace-formatting"
+                               }
+                       ]
+               },
+               "string-consume-escape": {
+                       "match": "\\\\['\"\\n\\\\]"
+               },
+               "string-raw-guts": {
+                       "patterns": [
+                               {
+                                       "include": "#string-consume-escape"
+                               },
+                               {
+                                       "include": "#string-formatting"
+                               },
+                               {
+                                       "include": "#string-brace-formatting"
+                               }
+                       ]
+               },
+               "string-raw-bin-guts": {
+                       "patterns": [
+                               {
+                                       "include": "#string-consume-escape"
+                               },
+                               {
+                                       "include": "#string-formatting"
+                               }
+                       ]
+               },
+               "string-entity": {
+                       "patterns": [
+                               {
+                                       "include": "#escape-sequence"
+                               },
+                               {
+                                       "include": "#string-line-continuation"
+                               },
+                               {
+                                       "include": "#string-formatting"
+                               }
+                       ]
+               },
+               "fstring-guts": {
+                       "patterns": [
+                               {
+                                       "include": "#escape-sequence-unicode"
+                               },
+                               {
+                                       "include": "#escape-sequence"
+                               },
+                               {
+                                       "include": "#string-line-continuation"
+                               },
+                               {
+                                       "include": "#fstring-formatting"
+                               }
+                       ]
+               },
+               "fstring-raw-guts": {
+                       "patterns": [
+                               {
+                                       "include": "#string-consume-escape"
+                               },
+                               {
+                                       "include": "#fstring-formatting"
+                               }
+                       ]
+               },
+               "fstring-illegal-single-brace": {
+                       "comment": "it is illegal to have a multiline brace 
inside a single-line string",
+                       "begin": "(\\{)(?=[^\\n}]*$\\n?)",
+                       "end": "(\\})|(?=\\n)",
+                       "beginCaptures": {
+                               "1": {
+                                       "name": 
"constant.character.format.placeholder.other.python"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"constant.character.format.placeholder.other.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": "#fstring-terminator-single"
+                               },
+                               {
+                                       "include": "#f-expression"
+                               }
+                       ]
+               },
+               "fstring-illegal-multi-brace": {
+                       "patterns": [
+                               {
+                                       "include": "#impossible"
+                               }
+                       ]
+               },
+               "f-expression": {
+                       "comment": "All valid Python expressions, except 
comments and line continuation",
+                       "patterns": [
+                               {
+                                       "include": "#expression-bare"
+                               },
+                               {
+                                       "include": "#member-access"
+                               },
+                               {
+                                       "comment": "Tokenize identifiers to 
help linters",
+                                       "match": "(?x) \\b ([[:alpha:]_]\\w*) 
\\b"
+                               }
+                       ]
+               },
+               "escape-sequence-unicode": {
+                       "patterns": [
+                               {
+                                       "name": 
"constant.character.escape.python",
+                                       "match": "(?x)\n  \\\\ (\n        
u[0-9A-Fa-f]{4}\n        | U[0-9A-Fa-f]{8}\n        | N\\{[\\w\\s]+?\\}\n     
)\n"
+                               }
+                       ]
+               },
+               "escape-sequence": {
+                       "name": "constant.character.escape.python",
+                       "match": "(?x)\n  \\\\ (\n        x[0-9A-Fa-f]{2}\n     
   | [0-7]{1,3}\n        | [\\\\\"'abfnrtv]\n     )\n"
+               },
+               "string-line-continuation": {
+                       "name": "constant.language.python",
+                       "match": "\\\\$"
+               },
+               "string-formatting": {
+                       "name": "meta.format.percent.python",
+                       "match": "(?x)\n  (\n    % (\\([\\w\\s]*\\))?\n      
[-+#0 ]*\n      (\\d+|\\*)? (\\.(\\d+|\\*))?\n      ([hlL])?\n      
[diouxXeEfFgGcrsab%]\n  )\n",
+                       "captures": {
+                               "1": {
+                                       "name": 
"constant.character.format.placeholder.other.python"
+                               }
+                       }
+               },
+               "string-brace-formatting": {
+                       "patterns": [
+                               {
+                                       "name": "meta.format.brace.python",
+                                       "match": "(?x)\n  (\n    {{ | }}\n    | 
(?:\n      {\n        \\w* (\\.[[:alpha:]_]\\w* | \\[[^\\]'\"]+\\])*\n        
(![rsa])?\n        ( : \\w? [<>=^]? [-+ ]? \\#?\n          \\d* ,? (\\.\\d+)? 
[bcdeEfFgGnosxX%]? )?\n      })\n  )\n",
+                                       "captures": {
+                                               "1": {
+                                                       "name": 
"constant.character.format.placeholder.other.python"
+                                               },
+                                               "3": {
+                                                       "name": 
"storage.type.format.python"
+                                               },
+                                               "4": {
+                                                       "name": 
"storage.type.format.python"
+                                               }
+                                       }
+                               },
+                               {
+                                       "name": "meta.format.brace.python",
+                                       "match": "(?x)\n  (\n    {\n      \\w* 
(\\.[[:alpha:]_]\\w* | \\[[^\\]'\"]+\\])*\n      (![rsa])?\n      (:)\n        
[^'\"{}\\n]* (?:\n          \\{ [^'\"}\\n]*? \\} [^'\"{}\\n]*\n        )*\n    
}\n  )\n",
+                                       "captures": {
+                                               "1": {
+                                                       "name": 
"constant.character.format.placeholder.other.python"
+                                               },
+                                               "3": {
+                                                       "name": 
"storage.type.format.python"
+                                               },
+                                               "4": {
+                                                       "name": 
"storage.type.format.python"
+                                               }
+                                       }
+                               }
+                       ]
+               },
+               "fstring-formatting": {
+                       "patterns": [
+                               {
+                                       "include": "#fstring-formatting-braces"
+                               },
+                               {
+                                       "include": 
"#fstring-formatting-singe-brace"
+                               }
+                       ]
+               },
+               "fstring-formatting-singe-brace": {
+                       "name": "invalid.illegal.brace.python",
+                       "match": "(}(?!}))"
+               },
+               "import": {
+                       "comment": "Import statements used to correctly mark 
`from`, `import`, and `as`\n",
+                       "patterns": [
+                               {
+                                       "begin": 
"\\b(?<!\\.)(from)\\b(?=.+import)",
+                                       "end": "$|(?=import)",
+                                       "beginCaptures": {
+                                               "1": {
+                                                       "name": 
"keyword.control.import.python"
+                                               }
+                                       },
+                                       "patterns": [
+                                               {
+                                                       "name": 
"punctuation.separator.period.python",
+                                                       "match": "\\.+"
+                                               },
+                                               {
+                                                       "include": "#expression"
+                                               }
+                                       ]
+                               },
+                               {
+                                       "begin": "\\b(?<!\\.)(import)\\b",
+                                       "end": "$",
+                                       "beginCaptures": {
+                                               "1": {
+                                                       "name": 
"keyword.control.import.python"
+                                               }
+                                       },
+                                       "patterns": [
+                                               {
+                                                       "name": 
"keyword.control.import.python",
+                                                       "match": 
"\\b(?<!\\.)as\\b"
+                                               },
+                                               {
+                                                       "include": "#expression"
+                                               }
+                                       ]
+                               }
+                       ]
+               },
+               "class-declaration": {
+                       "patterns": [
+                               {
+                                       "name": "meta.class.python",
+                                       "begin": "(?x)\n  \\s*(class)\\s+\n    
(?=\n      [[:alpha:]_]\\w* \\s* (:|\\()\n    )\n",
+                                       "end": "(:)",
+                                       "beginCaptures": {
+                                               "1": {
+                                                       "name": 
"storage.type.class.python"
+                                               }
+                                       },
+                                       "endCaptures": {
+                                               "1": {
+                                                       "name": 
"punctuation.section.class.begin.python"
+                                               }
+                                       },
+                                       "patterns": [
+                                               {
+                                                       "include": "#class-name"
+                                               },
+                                               {
+                                                       "include": 
"#class-inheritance"
+                                               }
+                                       ]
+                               }
+                       ]
+               },
+               "class-name": {
+                       "patterns": [
+                               {
+                                       "include": "#illegal-object-name"
+                               },
+                               {
+                                       "include": "#builtin-possible-callables"
+                               },
+                               {
+                                       "name": "entity.name.type.class.python",
+                                       "match": "(?x)\n  \\b 
([[:alpha:]_]\\w*) \\b\n"
+                               }
+                       ]
+               },
+               "class-inheritance": {
+                       "name": "meta.class.inheritance.python",
+                       "begin": "(\\()",
+                       "end": "(\\))",
+                       "beginCaptures": {
+                               "1": {
+                                       "name": 
"punctuation.definition.inheritance.begin.python"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"punctuation.definition.inheritance.end.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "name": 
"keyword.operator.unpacking.arguments.python",
+                                       "match": "(\\*\\*|\\*)"
+                               },
+                               {
+                                       "name": 
"punctuation.separator.inheritance.python",
+                                       "match": ","
+                               },
+                               {
+                                       "name": 
"keyword.operator.assignment.python",
+                                       "match": "=(?!=)"
+                               },
+                               {
+                                       "name": "support.type.metaclass.python",
+                                       "match": "\\bmetaclass\\b"
+                               },
+                               {
+                                       "include": "#illegal-names"
+                               },
+                               {
+                                       "include": "#class-kwarg"
+                               },
+                               {
+                                       "include": "#call-wrapper-inheritance"
+                               },
+                               {
+                                       "include": "#expression-base"
+                               },
+                               {
+                                       "include": "#member-access-class"
+                               },
+                               {
+                                       "include": "#inheritance-identifier"
+                               }
+                       ]
+               },
+               "class-kwarg": {
+                       "match": "(?x)\n  \\b ([[:alpha:]_]\\w*) 
\\s*(=)(?!=)\n",
+                       "captures": {
+                               "1": {
+                                       "name": 
"entity.other.inherited-class.python variable.parameter.class.python"
+                               },
+                               "2": {
+                                       "name": 
"keyword.operator.assignment.python"
+                               }
+                       }
+               },
+               "inheritance-identifier": {
+                       "match": "(?x)\n  \\b ([[:alpha:]_]\\w*) \\b\n",
+                       "captures": {
+                               "1": {
+                                       "name": 
"entity.other.inherited-class.python"
+                               }
+                       }
+               },
+               "member-access-class": {
+                       "name": "meta.member.access.python",
+                       "begin": "(\\.)\\s*(?!\\.)",
+                       "end": "(?<=\\S)(?=\\W)|$",
+                       "beginCaptures": {
+                               "1": {
+                                       "name": 
"punctuation.separator.period.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": "#call-wrapper-inheritance"
+                               },
+                               {
+                                       "include": "#member-access-base"
+                               },
+                               {
+                                       "include": "#inheritance-identifier"
+                               }
+                       ]
+               },
+               "lambda": {
+                       "patterns": [
+                               {
+                                       "match": 
"((?<=\\.)lambda|lambda(?=\\s*[\\.=]))",
+                                       "captures": {
+                                               "1": {
+                                                       "name": 
"keyword.control.flow.python"
+                                               }
+                                       }
+                               },
+                               {
+                                       "match": "\\b(lambda)\\s*?(?=[,\\n]|$)",
+                                       "captures": {
+                                               "1": {
+                                                       "name": 
"storage.type.function.lambda.python"
+                                               }
+                                       }
+                               },
+                               {
+                                       "name": "meta.lambda-function.python",
+                                       "begin": "(?x)\n  \\b (lambda) \\b\n",
+                                       "end": "(:)|(\\n)",
+                                       "beginCaptures": {
+                                               "1": {
+                                                       "name": 
"storage.type.function.lambda.python"
+                                               }
+                                       },
+                                       "endCaptures": {
+                                               "1": {
+                                                       "name": 
"punctuation.section.function.lambda.begin.python"
+                                               }
+                                       },
+                                       "contentName": 
"meta.function.lambda.parameters.python",
+                                       "patterns": [
+                                               {
+                                                       "name": 
"keyword.operator.positional.parameter.python",
+                                                       "match": "/"
+                                               },
+                                               {
+                                                       "name": 
"keyword.operator.unpacking.parameter.python",
+                                                       "match": "(\\*\\*|\\*)"
+                                               },
+                                               {
+                                                       "include": 
"#lambda-nested-incomplete"
+                                               },
+                                               {
+                                                       "include": 
"#illegal-names"
+                                               },
+                                               {
+                                                       "match": 
"([[:alpha:]_]\\w*)\\s*(?:(,)|(?=:|$))",
+                                                       "captures": {
+                                                               "1": {
+                                                                       "name": 
"variable.parameter.function.language.python"
+                                                               },
+                                                               "2": {
+                                                                       "name": 
"punctuation.separator.parameters.python"
+                                                               }
+                                                       }
+                                               },
+                                               {
+                                                       "include": "#comments"
+                                               },
+                                               {
+                                                       "include": "#backticks"
+                                               },
+                                               {
+                                                       "include": 
"#illegal-anno"
+                                               },
+                                               {
+                                                       "include": 
"#lambda-parameter-with-default"
+                                               },
+                                               {
+                                                       "include": 
"#line-continuation"
+                                               },
+                                               {
+                                                       "include": 
"#illegal-operator"
+                                               }
+                                       ]
+                               }
+                       ]
+               },
+               "lambda-incomplete": {
+                       "name": "storage.type.function.lambda.python",
+                       "match": "\\blambda(?=\\s*[,)])"
+               },
+               "lambda-nested-incomplete": {
+                       "name": "storage.type.function.lambda.python",
+                       "match": "\\blambda(?=\\s*[:,)])"
+               },
+               "lambda-parameter-with-default": {
+                       "begin": "(?x)\n  \\b\n  ([[:alpha:]_]\\w*) \\s* (=)\n",
+                       "end": "(,)|(?=:|$)",
+                       "beginCaptures": {
+                               "1": {
+                                       "name": 
"variable.parameter.function.language.python"
+                               },
+                               "2": {
+                                       "name": "keyword.operator.python"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"punctuation.separator.parameters.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": "#expression"
+                               }
+                       ]
+               },
+               "generator": {
+                       "comment": "Match \"for ... in\" construct used in 
generators and for loops to\ncorrectly identify the \"in\" as a control flow 
keyword.\n",
+                       "begin": "\\bfor\\b",
+                       "beginCaptures": {
+                               "0": {
+                                       "name": "keyword.control.flow.python"
+                               }
+                       },
+                       "end": "\\bin\\b",
+                       "endCaptures": {
+                               "0": {
+                                       "name": "keyword.control.flow.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": "#expression"
+                               }
+                       ]
+               },
+               "function-declaration": {
+                       "name": "meta.function.python",
+                       "begin": "(?x)\n  \\s*\n  (?:\\b(async) \\s+)? 
\\b(def)\\s+\n    (?=\n      [[:alpha:]_][[:word:]]* \\s* \\(\n    )\n",
+                       "end": "(:|(?=[#'\"\\n]))",
+                       "beginCaptures": {
+                               "1": {
+                                       "name": 
"storage.type.function.async.python"
+                               },
+                               "2": {
+                                       "name": "storage.type.function.python"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"punctuation.section.function.begin.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": "#function-def-name"
+                               },
+                               {
+                                       "include": "#parameters"
+                               },
+                               {
+                                       "include": "#line-continuation"
+                               },
+                               {
+                                       "include": "#return-annotation"
+                               }
+                       ]
+               },
+               "function-def-name": {
+                       "patterns": [
+                               {
+                                       "include": "#illegal-object-name"
+                               },
+                               {
+                                       "include": "#builtin-possible-callables"
+                               },
+                               {
+                                       "name": "entity.name.function.python",
+                                       "match": "(?x)\n  \\b 
([[:alpha:]_]\\w*) \\b\n"
+                               }
+                       ]
+               },
+               "parameters": {
+                       "name": "meta.function.parameters.python",
+                       "begin": "(\\()",
+                       "end": "(\\))",
+                       "beginCaptures": {
+                               "1": {
+                                       "name": 
"punctuation.definition.parameters.begin.python"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"punctuation.definition.parameters.end.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "name": 
"keyword.operator.positional.parameter.python",
+                                       "match": "/"
+                               },
+                               {
+                                       "name": 
"keyword.operator.unpacking.parameter.python",
+                                       "match": "(\\*\\*|\\*)"
+                               },
+                               {
+                                       "include": "#lambda-incomplete"
+                               },
+                               {
+                                       "include": "#illegal-names"
+                               },
+                               {
+                                       "include": "#illegal-object-name"
+                               },
+                               {
+                                       "include": "#parameter-special"
+                               },
+                               {
+                                       "match": "(?x)\n  ([[:alpha:]_]\\w*)\n  
  \\s* (?: (,) | (?=[)#\\n=]))\n",
+                                       "captures": {
+                                               "1": {
+                                                       "name": 
"variable.parameter.function.language.python"
+                                               },
+                                               "2": {
+                                                       "name": 
"punctuation.separator.parameters.python"
+                                               }
+                                       }
+                               },
+                               {
+                                       "include": "#comments"
+                               },
+                               {
+                                       "include": "#loose-default"
+                               },
+                               {
+                                       "include": "#annotated-parameter"
+                               }
+                       ]
+               },
+               "parameter-special": {
+                       "match": "(?x)\n  \\b ((self)|(cls)) \\b 
\\s*(?:(,)|(?=\\)))\n",
+                       "captures": {
+                               "1": {
+                                       "name": 
"variable.parameter.function.language.python"
+                               },
+                               "2": {
+                                       "name": 
"variable.parameter.function.language.special.self.python"
+                               },
+                               "3": {
+                                       "name": 
"variable.parameter.function.language.special.cls.python"
+                               },
+                               "4": {
+                                       "name": 
"punctuation.separator.parameters.python"
+                               }
+                       }
+               },
+               "loose-default": {
+                       "begin": "(=)",
+                       "end": "(,)|(?=\\))",
+                       "beginCaptures": {
+                               "1": {
+                                       "name": "keyword.operator.python"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"punctuation.separator.parameters.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": "#expression"
+                               }
+                       ]
+               },
+               "annotated-parameter": {
+                       "begin": "(?x)\n  \\b\n  ([[:alpha:]_]\\w*) \\s* (:)\n",
+                       "end": "(,)|(?=\\))",
+                       "beginCaptures": {
+                               "1": {
+                                       "name": 
"variable.parameter.function.language.python"
+                               },
+                               "2": {
+                                       "name": 
"punctuation.separator.annotation.python"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"punctuation.separator.parameters.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": "#expression"
+                               },
+                               {
+                                       "name": 
"keyword.operator.assignment.python",
+                                       "match": "=(?!=)"
+                               }
+                       ]
+               },
+               "return-annotation": {
+                       "begin": "(->)",
+                       "end": "(?=:)",
+                       "beginCaptures": {
+                               "1": {
+                                       "name": 
"punctuation.separator.annotation.result.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": "#expression"
+                               }
+                       ]
+               },
+               "item-access": {
+                       "patterns": [
+                               {
+                                       "name": "meta.item-access.python",
+                                       "begin": "(?x)\n  \\b(?=\n    
[[:alpha:]_]\\w* \\s* \\[\n  )\n",
+                                       "end": "(\\])",
+                                       "endCaptures": {
+                                               "1": {
+                                                       "name": 
"punctuation.definition.arguments.end.python"
+                                               }
+                                       },
+                                       "patterns": [
+                                               {
+                                                       "include": "#item-name"
+                                               },
+                                               {
+                                                       "include": "#item-index"
+                                               },
+                                               {
+                                                       "include": "#expression"
+                                               }
+                                       ]
+                               }
+                       ]
+               },
+               "item-name": {
+                       "patterns": [
+                               {
+                                       "include": "#special-variables"
+                               },
+                               {
+                                       "include": "#builtin-functions"
+                               },
+                               {
+                                       "include": "#special-names"
+                               },
+                               {
+                                       "name": "meta.indexed-name.python",
+                                       "match": "(?x)\n  \\b 
([[:alpha:]_]\\w*) \\b\n"
+                               }
+                       ]
+               },
+               "item-index": {
+                       "begin": "(\\[)",
+                       "end": "(?=\\])",
+                       "beginCaptures": {
+                               "1": {
+                                       "name": 
"punctuation.definition.arguments.begin.python"
+                               }
+                       },
+                       "contentName": "meta.item-access.arguments.python",
+                       "patterns": [
+                               {
+                                       "name": 
"punctuation.separator.slice.python",
+                                       "match": ":"
+                               },
+                               {
+                                       "include": "#expression"
+                               }
+                       ]
+               },
+               "decorator": {
+                       "name": "meta.function.decorator.python",
+                       "begin": "(?x)\n  ^\\s*\n  ((@)) \\s* 
(?=[[:alpha:]_]\\w*)\n",
+                       "end": "(?x)\n  ( \\) )\n    # trailing whitespace and 
comments are legal\n    (?: (.*?) (?=\\s*(?:\\#|$)) )\n  | (?=\\n|\\#)\n",
+                       "beginCaptures": {
+                               "1": {
+                                       "name": 
"entity.name.function.decorator.python"
+                               },
+                               "2": {
+                                       "name": 
"punctuation.definition.decorator.python"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"punctuation.definition.arguments.end.python"
+                               },
+                               "2": {
+                                       "name": 
"invalid.illegal.decorator.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": "#decorator-name"
+                               },
+                               {
+                                       "include": "#function-arguments"
+                               }
+                       ]
+               },
+               "decorator-name": {
+                       "patterns": [
+                               {
+                                       "include": "#builtin-callables"
+                               },
+                               {
+                                       "include": "#illegal-object-name"
+                               },
+                               {
+                                       "name": 
"entity.name.function.decorator.python",
+                                       "match": "(?x)\n  ([[:alpha:]_]\\w*) | 
(\\.)\n",
+                                       "captures": {
+                                               "2": {
+                                                       "name": 
"punctuation.separator.period.python"
+                                               }
+                                       }
+                               },
+                               {
+                                       "include": "#line-continuation"
+                               },
+                               {
+                                       "name": 
"invalid.illegal.decorator.python",
+                                       "match": "(?x)\n  \\s* 
([^([:alpha:]\\s_\\.#\\\\] .*?) (?=\\#|$)\n",
+                                       "captures": {
+                                               "1": {
+                                                       "name": 
"invalid.illegal.decorator.python"
+                                               }
+                                       }
+                               }
+                       ]
+               },
+               "call-wrapper-inheritance": {
+                       "comment": "same as a function call, but in inheritance 
context",
+                       "name": "meta.function-call.python",
+                       "begin": "(?x)\n  \\b(?=\n    ([[:alpha:]_]\\w*) \\s* 
(\\()\n  )\n",
+                       "end": "(\\))",
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"punctuation.definition.arguments.end.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": "#inheritance-name"
+                               },
+                               {
+                                       "include": "#function-arguments"
+                               }
+                       ]
+               },
+               "inheritance-name": {
+                       "patterns": [
+                               {
+                                       "include": "#lambda-incomplete"
+                               },
+                               {
+                                       "include": "#builtin-possible-callables"
+                               },
+                               {
+                                       "include": "#inheritance-identifier"
+                               }
+                       ]
+               },
+               "function-call": {
+                       "name": "meta.function-call.python",
+                       "comment": "Regular function call of the type 
\"name(args)\"",
+                       "begin": "(?x)\n  \\b(?=\n    ([[:alpha:]_]\\w*) \\s* 
(\\()\n  )\n",
+                       "end": "(\\))",
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"punctuation.definition.arguments.end.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": "#special-variables"
+                               },
+                               {
+                                       "include": "#function-name"
+                               },
+                               {
+                                       "include": "#function-arguments"
+                               }
+                       ]
+               },
+               "function-name": {
+                       "patterns": [
+                               {
+                                       "include": "#builtin-possible-callables"
+                               },
+                               {
+                                       "comment": "Some color schemas support 
meta.function-call.generic scope",
+                                       "name": 
"meta.function-call.generic.python",
+                                       "match": "(?x)\n  \\b 
([[:alpha:]_]\\w*) \\b\n"
+                               }
+                       ]
+               },
+               "function-arguments": {
+                       "begin": "(\\()",
+                       "end": "(?=\\))(?!\\)\\s*\\()",
+                       "beginCaptures": {
+                               "1": {
+                                       "name": 
"punctuation.definition.arguments.begin.python"
+                               }
+                       },
+                       "contentName": "meta.function-call.arguments.python",
+                       "patterns": [
+                               {
+                                       "name": 
"punctuation.separator.arguments.python",
+                                       "match": "(,)"
+                               },
+                               {
+                                       "match": "(?x)\n  (?:(?<=[,(])|^) \\s* 
(\\*{1,2})\n",
+                                       "captures": {
+                                               "1": {
+                                                       "name": 
"keyword.operator.unpacking.arguments.python"
+                                               }
+                                       }
+                               },
+                               {
+                                       "include": "#lambda-incomplete"
+                               },
+                               {
+                                       "include": "#illegal-names"
+                               },
+                               {
+                                       "match": 
"\\b([[:alpha:]_]\\w*)\\s*(=)(?!=)",
+                                       "captures": {
+                                               "1": {
+                                                       "name": 
"variable.parameter.function-call.python"
+                                               },
+                                               "2": {
+                                                       "name": 
"keyword.operator.assignment.python"
+                                               }
+                                       }
+                               },
+                               {
+                                       "name": 
"keyword.operator.assignment.python",
+                                       "match": "=(?!=)"
+                               },
+                               {
+                                       "include": "#expression"
+                               },
+                               {
+                                       "match": "\\s*(\\))\\s*(\\()",
+                                       "captures": {
+                                               "1": {
+                                                       "name": 
"punctuation.definition.arguments.end.python"
+                                               },
+                                               "2": {
+                                                       "name": 
"punctuation.definition.arguments.begin.python"
+                                               }
+                                       }
+                               }
+                       ]
+               },
+               "builtin-callables": {
+                       "patterns": [
+                               {
+                                       "include": "#illegal-names"
+                               },
+                               {
+                                       "include": "#illegal-object-name"
+                               },
+                               {
+                                       "include": "#builtin-exceptions"
+                               },
+                               {
+                                       "include": "#builtin-functions"
+                               },
+                               {
+                                       "include": "#builtin-types"
+                               }
+                       ]
+               },
+               "builtin-possible-callables": {
+                       "patterns": [
+                               {
+                                       "include": "#builtin-callables"
+                               },
+                               {
+                                       "include": "#magic-names"
+                               }
+                       ]
+               },
+               "builtin-exceptions": {
+                       "name": "support.type.exception.python",
+                       "match": "(?x) (?<!\\.) \\b(\n  (\n    Arithmetic | 
Assertion | Attribute | Buffer | BlockingIO\n    | BrokenPipe | ChildProcess\n  
  | (Connection (Aborted | Refused | Reset)?)\n    | EOF | Environment | 
FileExists | FileNotFound\n    | FloatingPoint | IO | Import | Indentation | 
Index | Interrupted\n    | IsADirectory | NotADirectory | Permission | 
ProcessLookup\n    | Timeout\n    | Key | Lookup | Memory | Name | 
NotImplemented | OS | Overflow\n    | Reference | Runtime | Recursion [...]
+               },
+               "builtin-functions": {
+                       "patterns": [
+                               {
+                                       "name": 
"support.function.builtin.python",
+                                       "match": "(?x)\n  (?<!\\.) \\b(\n    
__import__ | abs | aiter | all | any | anext | ascii | bin\n    | breakpoint | 
callable | chr | compile | copyright | credits\n    | delattr | dir | divmod | 
enumerate | eval | exec | exit\n    | filter | format | getattr | globals | 
hasattr | hash | help\n    | hex | id | input | isinstance | issubclass | iter 
| len\n    | license | locals | map | max | memoryview | min | next\n    | oct 
| open | ord | pow | print | quit | range | reload | repr\ [...]
+                               },
+                               {
+                                       "name": 
"variable.legacy.builtin.python",
+                                       "match": "(?x)\n  (?<!\\.) \\b(\n    
file | reduce | intern | raw_input | unicode | cmp | basestring\n    | execfile 
| long | xrange\n  )\\b\n"
+                               }
+                       ]
+               },
+               "builtin-types": {
+                       "name": "support.type.python",
+                       "match": "(?x)\n  (?<!\\.) \\b(\n    bool | bytearray | 
bytes | classmethod | complex | dict\n    | float | frozenset | int | list | 
object | property\n    | set | slice | staticmethod | str | tuple | type\n\n    
(?# Although 'super' is not a type, it's related to types,\n        and is 
special enough to be highlighted differently from\n        other built-ins)\n   
 | super\n  )\\b\n"
+               },
+               "magic-function-names": {
+                       "comment": "these methods have magic interpretation by 
python and are generally called\nindirectly through syntactic constructs\n",
+                       "match": "(?x)\n  \\b(\n    __(?:\n      abs | add | 
aenter | aexit | aiter | and | anext\n      | await | bool | call | ceil | 
class_getitem\n      | cmp | coerce | complex | contains | copy\n      | 
deepcopy | del | delattr | delete | delitem\n      | delslice | dir | div | 
divmod | enter | eq\n      | exit | float | floor | floordiv | format | ge\n    
  | get | getattr | getattribute | getinitargs\n      | getitem | getnewargs | 
getslice | getstate | gt\n      | hash | hex | iadd | [...]
+                       "captures": {
+                               "1": {
+                                       "name": "support.function.magic.python"
+                               }
+                       }
+               },
+               "magic-variable-names": {
+                       "comment": "magic variables which a class/module may 
have.",
+                       "match": "(?x)\n  \\b(\n    __(?:\n      all | 
annotations | bases | builtins | class\n      | closure | code | debug | 
defaults | dict | doc | file | func\n      | globals | kwdefaults | match_args 
| members | metaclass | methods\n      | module | mro | mro_entries | name | 
qualname | post_init | self\n      | signature | slots | subclasses | version | 
weakref | wrapped\n      | classcell | spec | path | package | future | 
traceback\n    )__\n  )\\b\n",
+                       "captures": {
+                               "1": {
+                                       "name": "support.variable.magic.python"
+                               }
+                       }
+               },
+               "magic-names": {
+                       "patterns": [
+                               {
+                                       "include": "#magic-function-names"
+                               },
+                               {
+                                       "include": "#magic-variable-names"
+                               }
+                       ]
+               },
+               "illegal-names": {
+                       "match": "(?x)\n  \\b(?:\n    (\n      and | assert | 
async | await | break | class | continue | def\n      | del | elif | else | 
except | finally | for | from | global\n      | if | in | is | (?<=\\.)lambda | 
lambda(?=\\s*[\\.=])\n      | nonlocal | not | or | pass | raise | return | try 
| while | with\n      | yield\n    ) | (\n      as | import\n    )\n  )\\b\n",
+                       "captures": {
+                               "1": {
+                                       "name": "keyword.control.flow.python"
+                               },
+                               "2": {
+                                       "name": "keyword.control.import.python"
+                               }
+                       }
+               },
+               "special-variables": {
+                       "match": "(?x)\n  \\b (?<!\\.) (?:\n    (self) | 
(cls)\n  )\\b\n",
+                       "captures": {
+                               "1": {
+                                       "name": 
"variable.language.special.self.python"
+                               },
+                               "2": {
+                                       "name": 
"variable.language.special.cls.python"
+                               }
+                       }
+               },
+               "ellipsis": {
+                       "name": "constant.other.ellipsis.python",
+                       "match": "\\.\\.\\."
+               },
+               "backticks": {
+                       "name": "invalid.deprecated.backtick.python",
+                       "begin": "\\`",
+                       "end": "(?:\\`|(?<!\\\\)(\\n))",
+                       "patterns": [
+                               {
+                                       "include": "#expression"
+                               }
+                       ]
+               },
+               "illegal-operator": {
+                       "patterns": [
+                               {
+                                       "name": 
"invalid.illegal.operator.python",
+                                       "match": "&&|\\|\\||--|\\+\\+"
+                               },
+                               {
+                                       "name": 
"invalid.illegal.operator.python",
+                                       "match": "[?$]"
+                               },
+                               {
+                                       "name": 
"invalid.illegal.operator.python",
+                                       "comment": "We don't want `!` to flash 
when we're typing `!=`",
+                                       "match": "!\\b"
+                               }
+                       ]
+               },
+               "illegal-object-name": {
+                       "comment": "It's illegal to name class or function 
\"True\"",
+                       "name": "keyword.illegal.name.python",
+                       "match": "\\b(True|False|None)\\b"
+               },
+               "illegal-anno": {
+                       "name": "invalid.illegal.annotation.python",
+                       "match": "->"
+               },
+               "regexp-base-expression": {
+                       "patterns": [
+                               {
+                                       "include": "#regexp-quantifier"
+                               },
+                               {
+                                       "include": "#regexp-base-common"
+                               }
+                       ]
+               },
+               "fregexp-base-expression": {
+                       "patterns": [
+                               {
+                                       "include": "#fregexp-quantifier"
+                               },
+                               {
+                                       "include": "#fstring-formatting-braces"
+                               },
+                               {
+                                       "match": "\\{.*?\\}"
+                               },
+                               {
+                                       "include": "#regexp-base-common"
+                               }
+                       ]
+               },
+               "fstring-formatting-braces": {
+                       "patterns": [
+                               {
+                                       "comment": "empty braces are illegal",
+                                       "match": "({)(\\s*?)(})",
+                                       "captures": {
+                                               "1": {
+                                                       "name": 
"constant.character.format.placeholder.other.python"
+                                               },
+                                               "2": {
+                                                       "name": 
"invalid.illegal.brace.python"
+                                               },
+                                               "3": {
+                                                       "name": 
"constant.character.format.placeholder.other.python"
+                                               }
+                                       }
+                               },
+                               {
+                                       "name": 
"constant.character.escape.python",
+                                       "match": "({{|}})"
+                               }
+                       ]
+               },
+               "regexp-base-common": {
+                       "patterns": [
+                               {
+                                       "name": 
"support.other.match.any.regexp",
+                                       "match": "\\."
+                               },
+                               {
+                                       "name": 
"support.other.match.begin.regexp",
+                                       "match": "\\^"
+                               },
+                               {
+                                       "name": 
"support.other.match.end.regexp",
+                                       "match": "\\$"
+                               },
+                               {
+                                       "name": 
"keyword.operator.quantifier.regexp",
+                                       "match": "[+*?]\\??"
+                               },
+                               {
+                                       "name": 
"keyword.operator.disjunction.regexp",
+                                       "match": "\\|"
+                               },
+                               {
+                                       "include": "#regexp-escape-sequence"
+                               }
+                       ]
+               },
+               "regexp-quantifier": {
+                       "name": "keyword.operator.quantifier.regexp",
+                       "match": "(?x)\n  \\{(\n    \\d+ | \\d+,(\\d+)? | 
,\\d+\n  )\\}\n"
+               },
+               "fregexp-quantifier": {
+                       "name": "keyword.operator.quantifier.regexp",
+                       "match": "(?x)\n  \\{\\{(\n    \\d+ | \\d+,(\\d+)? | 
,\\d+\n  )\\}\\}\n"
+               },
+               "regexp-backreference-number": {
+                       "name": "meta.backreference.regexp",
+                       "match": "(\\\\[1-9]\\d?)",
+                       "captures": {
+                               "1": {
+                                       "name": 
"entity.name.tag.backreference.regexp"
+                               }
+                       }
+               },
+               "regexp-backreference": {
+                       "name": "meta.backreference.named.regexp",
+                       "match": "(?x)\n  (\\()  (\\?P= 
\\w+(?:\\s+[[:alnum:]]+)?)  (\\))\n",
+                       "captures": {
+                               "1": {
+                                       "name": 
"support.other.parenthesis.regexp 
punctuation.parenthesis.backreference.named.begin.regexp"
+                               },
+                               "2": {
+                                       "name": 
"entity.name.tag.named.backreference.regexp"
+                               },
+                               "3": {
+                                       "name": 
"support.other.parenthesis.regexp 
punctuation.parenthesis.backreference.named.end.regexp"
+                               }
+                       }
+               },
+               "regexp-flags": {
+                       "name": "storage.modifier.flag.regexp",
+                       "match": "\\(\\?[aiLmsux]+\\)"
+               },
+               "regexp-escape-special": {
+                       "name": "support.other.escape.special.regexp",
+                       "match": "\\\\([AbBdDsSwWZ])"
+               },
+               "regexp-escape-character": {
+                       "name": "constant.character.escape.regexp",
+                       "match": "(?x)\n  \\\\ (\n        x[0-9A-Fa-f]{2}\n     
   | 0[0-7]{1,2}\n        | [0-7]{3}\n     )\n"
+               },
+               "regexp-escape-unicode": {
+                       "name": "constant.character.unicode.regexp",
+                       "match": "(?x)\n  \\\\ (\n        u[0-9A-Fa-f]{4}\n     
   | U[0-9A-Fa-f]{8}\n     )\n"
+               },
+               "regexp-escape-catchall": {
+                       "name": "constant.character.escape.regexp",
+                       "match": "\\\\(.|\\n)"
+               },
+               "regexp-escape-sequence": {
+                       "patterns": [
+                               {
+                                       "include": "#regexp-escape-special"
+                               },
+                               {
+                                       "include": "#regexp-escape-character"
+                               },
+                               {
+                                       "include": "#regexp-escape-unicode"
+                               },
+                               {
+                                       "include": 
"#regexp-backreference-number"
+                               },
+                               {
+                                       "include": "#regexp-escape-catchall"
+                               }
+                       ]
+               },
+               "regexp-charecter-set-escapes": {
+                       "patterns": [
+                               {
+                                       "name": 
"constant.character.escape.regexp",
+                                       "match": "\\\\[abfnrtv\\\\]"
+                               },
+                               {
+                                       "include": "#regexp-escape-special"
+                               },
+                               {
+                                       "name": 
"constant.character.escape.regexp",
+                                       "match": "\\\\([0-7]{1,3})"
+                               },
+                               {
+                                       "include": "#regexp-escape-character"
+                               },
+                               {
+                                       "include": "#regexp-escape-unicode"
+                               },
+                               {
+                                       "include": "#regexp-escape-catchall"
+                               }
+                       ]
+               },
+               "codetags": {
+                       "match": "(?:\\b(NOTE|XXX|HACK|FIXME|BUG|TODO)\\b)",
+                       "captures": {
+                               "1": {
+                                       "name": 
"keyword.codetag.notation.python"
+                               }
+                       }
+               },
+               "comments-base": {
+                       "name": "comment.line.number-sign.python",
+                       "begin": "(\\#)",
+                       "beginCaptures": {
+                               "1": {
+                                       "name": 
"punctuation.definition.comment.python"
+                               }
+                       },
+                       "end": "($)",
+                       "patterns": [
+                               {
+                                       "include": "#codetags"
+                               }
+                       ]
+               },
+               "comments-string-single-three": {
+                       "name": "comment.line.number-sign.python",
+                       "begin": "(\\#)",
+                       "beginCaptures": {
+                               "1": {
+                                       "name": 
"punctuation.definition.comment.python"
+                               }
+                       },
+                       "end": "($|(?='''))",
+                       "patterns": [
+                               {
+                                       "include": "#codetags"
+                               }
+                       ]
+               },
+               "comments-string-double-three": {
+                       "name": "comment.line.number-sign.python",
+                       "begin": "(\\#)",
+                       "beginCaptures": {
+                               "1": {
+                                       "name": 
"punctuation.definition.comment.python"
+                               }
+                       },
+                       "end": "($|(?=\"\"\"))",
+                       "patterns": [
+                               {
+                                       "include": "#codetags"
+                               }
+                       ]
+               },
+               "single-one-regexp-expression": {
+                       "patterns": [
+                               {
+                                       "include": "#regexp-base-expression"
+                               },
+                               {
+                                       "include": 
"#single-one-regexp-character-set"
+                               },
+                               {
+                                       "include": "#single-one-regexp-comments"
+                               },
+                               {
+                                       "include": "#regexp-flags"
+                               },
+                               {
+                                       "include": 
"#single-one-regexp-named-group"
+                               },
+                               {
+                                       "include": "#regexp-backreference"
+                               },
+                               {
+                                       "include": 
"#single-one-regexp-lookahead"
+                               },
+                               {
+                                       "include": 
"#single-one-regexp-lookahead-negative"
+                               },
+                               {
+                                       "include": 
"#single-one-regexp-lookbehind"
+                               },
+                               {
+                                       "include": 
"#single-one-regexp-lookbehind-negative"
+                               },
+                               {
+                                       "include": 
"#single-one-regexp-conditional"
+                               },
+                               {
+                                       "include": 
"#single-one-regexp-parentheses-non-capturing"
+                               },
+                               {
+                                       "include": 
"#single-one-regexp-parentheses"
+                               }
+                       ]
+               },
+               "single-one-regexp-character-set": {
+                       "patterns": [
+                               {
+                                       "match": "(?x)\n  \\[ \\^? \\] (?! 
.*?\\])\n"
+                               },
+                               {
+                                       "name": "meta.character.set.regexp",
+                                       "begin": "(\\[)(\\^)?(\\])?",
+                                       "end": 
"(\\]|(?=\\'))|((?=(?<!\\\\)\\n))",
+                                       "beginCaptures": {
+                                               "1": {
+                                                       "name": 
"punctuation.character.set.begin.regexp constant.other.set.regexp"
+                                               },
+                                               "2": {
+                                                       "name": 
"keyword.operator.negation.regexp"
+                                               },
+                                               "3": {
+                                                       "name": 
"constant.character.set.regexp"
+                                               }
+                                       },
+                                       "endCaptures": {
+                                               "1": {
+                                                       "name": 
"punctuation.character.set.end.regexp constant.other.set.regexp"
+                                               },
+                                               "2": {
+                                                       "name": 
"invalid.illegal.newline.python"
+                                               }
+                                       },
+                                       "patterns": [
+                                               {
+                                                       "include": 
"#regexp-charecter-set-escapes"
+                                               },
+                                               {
+                                                       "name": 
"constant.character.set.regexp",
+                                                       "match": "[^\\n]"
+                                               }
+                                       ]
+                               }
+                       ]
+               },
+               "single-one-regexp-named-group": {
+                       "name": "meta.named.regexp",
+                       "begin": "(?x)\n  (\\()  (\\?P 
<\\w+(?:\\s+[[:alnum:]]+)?>)\n",
+                       "end": "(\\)|(?=\\'))|((?=(?<!\\\\)\\n))",
+                       "beginCaptures": {
+                               "1": {
+                                       "name": 
"support.other.parenthesis.regexp punctuation.parenthesis.named.begin.regexp"
+                               },
+                               "2": {
+                                       "name": 
"entity.name.tag.named.group.regexp"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"support.other.parenthesis.regexp punctuation.parenthesis.named.end.regexp"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": 
"#single-one-regexp-expression"
+                               }
+                       ]
+               },
+               "single-one-regexp-comments": {
+                       "name": "comment.regexp",
+                       "begin": "\\(\\?#",
+                       "end": "(\\)|(?=\\'))|((?=(?<!\\\\)\\n))",
+                       "beginCaptures": {
+                               "0": {
+                                       "name": 
"punctuation.comment.begin.regexp"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": "punctuation.comment.end.regexp"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": "#codetags"
+                               }
+                       ]
+               },
+               "single-one-regexp-lookahead": {
+                       "begin": "(\\()\\?=",
+                       "end": "(\\)|(?=\\'))|((?=(?<!\\\\)\\n))",
+                       "beginCaptures": {
+                               "0": {
+                                       "name": 
"keyword.operator.lookahead.regexp"
+                               },
+                               "1": {
+                                       "name": 
"punctuation.parenthesis.lookahead.begin.regexp"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"keyword.operator.lookahead.regexp punctuation.parenthesis.lookahead.end.regexp"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": 
"#single-one-regexp-expression"
+                               }
+                       ]
+               },
+               "single-one-regexp-lookahead-negative": {
+                       "begin": "(\\()\\?!",
+                       "end": "(\\)|(?=\\'))|((?=(?<!\\\\)\\n))",
+                       "beginCaptures": {
+                               "0": {
+                                       "name": 
"keyword.operator.lookahead.negative.regexp"
+                               },
+                               "1": {
+                                       "name": 
"punctuation.parenthesis.lookahead.begin.regexp"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"keyword.operator.lookahead.negative.regexp 
punctuation.parenthesis.lookahead.end.regexp"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": 
"#single-one-regexp-expression"
+                               }
+                       ]
+               },
+               "single-one-regexp-lookbehind": {
+                       "begin": "(\\()\\?<=",
+                       "end": "(\\)|(?=\\'))|((?=(?<!\\\\)\\n))",
+                       "beginCaptures": {
+                               "0": {
+                                       "name": 
"keyword.operator.lookbehind.regexp"
+                               },
+                               "1": {
+                                       "name": 
"punctuation.parenthesis.lookbehind.begin.regexp"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"keyword.operator.lookbehind.regexp 
punctuation.parenthesis.lookbehind.end.regexp"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": 
"#single-one-regexp-expression"
+                               }
+                       ]
+               },
+               "single-one-regexp-lookbehind-negative": {
+                       "begin": "(\\()\\?<!",
+                       "end": "(\\)|(?=\\'))|((?=(?<!\\\\)\\n))",
+                       "beginCaptures": {
+                               "0": {
+                                       "name": 
"keyword.operator.lookbehind.negative.regexp"
+                               },
+                               "1": {
+                                       "name": 
"punctuation.parenthesis.lookbehind.begin.regexp"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"keyword.operator.lookbehind.negative.regexp 
punctuation.parenthesis.lookbehind.end.regexp"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": 
"#single-one-regexp-expression"
+                               }
+                       ]
+               },
+               "single-one-regexp-conditional": {
+                       "begin": 
"(\\()\\?\\((\\w+(?:\\s+[[:alnum:]]+)?|\\d+)\\)",
+                       "end": "(\\)|(?=\\'))|((?=(?<!\\\\)\\n))",
+                       "beginCaptures": {
+                               "0": {
+                                       "name": 
"keyword.operator.conditional.regexp"
+                               },
+                               "1": {
+                                       "name": 
"punctuation.parenthesis.conditional.begin.regexp"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"keyword.operator.conditional.negative.regexp 
punctuation.parenthesis.conditional.end.regexp"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": 
"#single-one-regexp-expression"
+                               }
+                       ]
+               },
+               "single-one-regexp-parentheses-non-capturing": {
+                       "begin": "\\(\\?:",
+                       "end": "(\\)|(?=\\'))|((?=(?<!\\\\)\\n))",
+                       "beginCaptures": {
+                               "0": {
+                                       "name": 
"support.other.parenthesis.regexp 
punctuation.parenthesis.non-capturing.begin.regexp"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"support.other.parenthesis.regexp 
punctuation.parenthesis.non-capturing.end.regexp"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": 
"#single-one-regexp-expression"
+                               }
+                       ]
+               },
+               "single-one-regexp-parentheses": {
+                       "begin": "\\(",
+                       "end": "(\\)|(?=\\'))|((?=(?<!\\\\)\\n))",
+                       "beginCaptures": {
+                               "0": {
+                                       "name": 
"support.other.parenthesis.regexp punctuation.parenthesis.begin.regexp"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"support.other.parenthesis.regexp punctuation.parenthesis.end.regexp"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": 
"#single-one-regexp-expression"
+                               }
+                       ]
+               },
+               "single-three-regexp-expression": {
+                       "patterns": [
+                               {
+                                       "include": "#regexp-base-expression"
+                               },
+                               {
+                                       "include": 
"#single-three-regexp-character-set"
+                               },
+                               {
+                                       "include": 
"#single-three-regexp-comments"
+                               },
+                               {
+                                       "include": "#regexp-flags"
+                               },
+                               {
+                                       "include": 
"#single-three-regexp-named-group"
+                               },
+                               {
+                                       "include": "#regexp-backreference"
+                               },
+                               {
+                                       "include": 
"#single-three-regexp-lookahead"
+                               },
+                               {
+                                       "include": 
"#single-three-regexp-lookahead-negative"
+                               },
+                               {
+                                       "include": 
"#single-three-regexp-lookbehind"
+                               },
+                               {
+                                       "include": 
"#single-three-regexp-lookbehind-negative"
+                               },
+                               {
+                                       "include": 
"#single-three-regexp-conditional"
+                               },
+                               {
+                                       "include": 
"#single-three-regexp-parentheses-non-capturing"
+                               },
+                               {
+                                       "include": 
"#single-three-regexp-parentheses"
+                               },
+                               {
+                                       "include": 
"#comments-string-single-three"
+                               }
+                       ]
+               },
+               "single-three-regexp-character-set": {
+                       "patterns": [
+                               {
+                                       "match": "(?x)\n  \\[ \\^? \\] (?! 
.*?\\])\n"
+                               },
+                               {
+                                       "name": "meta.character.set.regexp",
+                                       "begin": "(\\[)(\\^)?(\\])?",
+                                       "end": "(\\]|(?=\\'\\'\\'))",
+                                       "beginCaptures": {
+                                               "1": {
+                                                       "name": 
"punctuation.character.set.begin.regexp constant.other.set.regexp"
+                                               },
+                                               "2": {
+                                                       "name": 
"keyword.operator.negation.regexp"
+                                               },
+                                               "3": {
+                                                       "name": 
"constant.character.set.regexp"
+                                               }
+                                       },
+                                       "endCaptures": {
+                                               "1": {
+                                                       "name": 
"punctuation.character.set.end.regexp constant.other.set.regexp"
+                                               },
+                                               "2": {
+                                                       "name": 
"invalid.illegal.newline.python"
+                                               }
+                                       },
+                                       "patterns": [
+                                               {
+                                                       "include": 
"#regexp-charecter-set-escapes"
+                                               },
+                                               {
+                                                       "name": 
"constant.character.set.regexp",
+                                                       "match": "[^\\n]"
+                                               }
+                                       ]
+                               }
+                       ]
+               },
+               "single-three-regexp-named-group": {
+                       "name": "meta.named.regexp",
+                       "begin": "(?x)\n  (\\()  (\\?P 
<\\w+(?:\\s+[[:alnum:]]+)?>)\n",
+                       "end": "(\\)|(?=\\'\\'\\'))",
+                       "beginCaptures": {
+                               "1": {
+                                       "name": 
"support.other.parenthesis.regexp punctuation.parenthesis.named.begin.regexp"
+                               },
+                               "2": {
+                                       "name": 
"entity.name.tag.named.group.regexp"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"support.other.parenthesis.regexp punctuation.parenthesis.named.end.regexp"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": 
"#single-three-regexp-expression"
+                               },
+                               {
+                                       "include": 
"#comments-string-single-three"
+                               }
+                       ]
+               },
+               "single-three-regexp-comments": {
+                       "name": "comment.regexp",
+                       "begin": "\\(\\?#",
+                       "end": "(\\)|(?=\\'\\'\\'))",
+                       "beginCaptures": {
+                               "0": {
+                                       "name": 
"punctuation.comment.begin.regexp"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": "punctuation.comment.end.regexp"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": "#codetags"
+                               }
+                       ]
+               },
+               "single-three-regexp-lookahead": {
+                       "begin": "(\\()\\?=",
+                       "end": "(\\)|(?=\\'\\'\\'))",
+                       "beginCaptures": {
+                               "0": {
+                                       "name": 
"keyword.operator.lookahead.regexp"
+                               },
+                               "1": {
+                                       "name": 
"punctuation.parenthesis.lookahead.begin.regexp"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"keyword.operator.lookahead.regexp punctuation.parenthesis.lookahead.end.regexp"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": 
"#single-three-regexp-expression"
+                               },
+                               {
+                                       "include": 
"#comments-string-single-three"
+                               }
+                       ]
+               },
+               "single-three-regexp-lookahead-negative": {
+                       "begin": "(\\()\\?!",
+                       "end": "(\\)|(?=\\'\\'\\'))",
+                       "beginCaptures": {
+                               "0": {
+                                       "name": 
"keyword.operator.lookahead.negative.regexp"
+                               },
+                               "1": {
+                                       "name": 
"punctuation.parenthesis.lookahead.begin.regexp"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"keyword.operator.lookahead.negative.regexp 
punctuation.parenthesis.lookahead.end.regexp"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": 
"#single-three-regexp-expression"
+                               },
+                               {
+                                       "include": 
"#comments-string-single-three"
+                               }
+                       ]
+               },
+               "single-three-regexp-lookbehind": {
+                       "begin": "(\\()\\?<=",
+                       "end": "(\\)|(?=\\'\\'\\'))",
+                       "beginCaptures": {
+                               "0": {
+                                       "name": 
"keyword.operator.lookbehind.regexp"
+                               },
+                               "1": {
+                                       "name": 
"punctuation.parenthesis.lookbehind.begin.regexp"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"keyword.operator.lookbehind.regexp 
punctuation.parenthesis.lookbehind.end.regexp"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": 
"#single-three-regexp-expression"
+                               },
+                               {
+                                       "include": 
"#comments-string-single-three"
+                               }
+                       ]
+               },
+               "single-three-regexp-lookbehind-negative": {
+                       "begin": "(\\()\\?<!",
+                       "end": "(\\)|(?=\\'\\'\\'))",
+                       "beginCaptures": {
+                               "0": {
+                                       "name": 
"keyword.operator.lookbehind.negative.regexp"
+                               },
+                               "1": {
+                                       "name": 
"punctuation.parenthesis.lookbehind.begin.regexp"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"keyword.operator.lookbehind.negative.regexp 
punctuation.parenthesis.lookbehind.end.regexp"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": 
"#single-three-regexp-expression"
+                               },
+                               {
+                                       "include": 
"#comments-string-single-three"
+                               }
+                       ]
+               },
+               "single-three-regexp-conditional": {
+                       "begin": 
"(\\()\\?\\((\\w+(?:\\s+[[:alnum:]]+)?|\\d+)\\)",
+                       "end": "(\\)|(?=\\'\\'\\'))",
+                       "beginCaptures": {
+                               "0": {
+                                       "name": 
"keyword.operator.conditional.regexp"
+                               },
+                               "1": {
+                                       "name": 
"punctuation.parenthesis.conditional.begin.regexp"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"keyword.operator.conditional.negative.regexp 
punctuation.parenthesis.conditional.end.regexp"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": 
"#single-three-regexp-expression"
+                               },
+                               {
+                                       "include": 
"#comments-string-single-three"
+                               }
+                       ]
+               },
+               "single-three-regexp-parentheses-non-capturing": {
+                       "begin": "\\(\\?:",
+                       "end": "(\\)|(?=\\'\\'\\'))",
+                       "beginCaptures": {
+                               "0": {
+                                       "name": 
"support.other.parenthesis.regexp 
punctuation.parenthesis.non-capturing.begin.regexp"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"support.other.parenthesis.regexp 
punctuation.parenthesis.non-capturing.end.regexp"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": 
"#single-three-regexp-expression"
+                               },
+                               {
+                                       "include": 
"#comments-string-single-three"
+                               }
+                       ]
+               },
+               "single-three-regexp-parentheses": {
+                       "begin": "\\(",
+                       "end": "(\\)|(?=\\'\\'\\'))",
+                       "beginCaptures": {
+                               "0": {
+                                       "name": 
"support.other.parenthesis.regexp punctuation.parenthesis.begin.regexp"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"support.other.parenthesis.regexp punctuation.parenthesis.end.regexp"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": 
"#single-three-regexp-expression"
+                               },
+                               {
+                                       "include": 
"#comments-string-single-three"
+                               }
+                       ]
+               },
+               "double-one-regexp-expression": {
+                       "patterns": [
+                               {
+                                       "include": "#regexp-base-expression"
+                               },
+                               {
+                                       "include": 
"#double-one-regexp-character-set"
+                               },
+                               {
+                                       "include": "#double-one-regexp-comments"
+                               },
+                               {
+                                       "include": "#regexp-flags"
+                               },
+                               {
+                                       "include": 
"#double-one-regexp-named-group"
+                               },
+                               {
+                                       "include": "#regexp-backreference"
+                               },
+                               {
+                                       "include": 
"#double-one-regexp-lookahead"
+                               },
+                               {
+                                       "include": 
"#double-one-regexp-lookahead-negative"
+                               },
+                               {
+                                       "include": 
"#double-one-regexp-lookbehind"
+                               },
+                               {
+                                       "include": 
"#double-one-regexp-lookbehind-negative"
+                               },
+                               {
+                                       "include": 
"#double-one-regexp-conditional"
+                               },
+                               {
+                                       "include": 
"#double-one-regexp-parentheses-non-capturing"
+                               },
+                               {
+                                       "include": 
"#double-one-regexp-parentheses"
+                               }
+                       ]
+               },
+               "double-one-regexp-character-set": {
+                       "patterns": [
+                               {
+                                       "match": "(?x)\n  \\[ \\^? \\] (?! 
.*?\\])\n"
+                               },
+                               {
+                                       "name": "meta.character.set.regexp",
+                                       "begin": "(\\[)(\\^)?(\\])?",
+                                       "end": 
"(\\]|(?=\"))|((?=(?<!\\\\)\\n))",
+                                       "beginCaptures": {
+                                               "1": {
+                                                       "name": 
"punctuation.character.set.begin.regexp constant.other.set.regexp"
+                                               },
+                                               "2": {
+                                                       "name": 
"keyword.operator.negation.regexp"
+                                               },
+                                               "3": {
+                                                       "name": 
"constant.character.set.regexp"
+                                               }
+                                       },
+                                       "endCaptures": {
+                                               "1": {
+                                                       "name": 
"punctuation.character.set.end.regexp constant.other.set.regexp"
+                                               },
+                                               "2": {
+                                                       "name": 
"invalid.illegal.newline.python"
+                                               }
+                                       },
+                                       "patterns": [
+                                               {
+                                                       "include": 
"#regexp-charecter-set-escapes"
+                                               },
+                                               {
+                                                       "name": 
"constant.character.set.regexp",
+                                                       "match": "[^\\n]"
+                                               }
+                                       ]
+                               }
+                       ]
+               },
+               "double-one-regexp-named-group": {
+                       "name": "meta.named.regexp",
+                       "begin": "(?x)\n  (\\()  (\\?P 
<\\w+(?:\\s+[[:alnum:]]+)?>)\n",
+                       "end": "(\\)|(?=\"))|((?=(?<!\\\\)\\n))",
+                       "beginCaptures": {
+                               "1": {
+                                       "name": 
"support.other.parenthesis.regexp punctuation.parenthesis.named.begin.regexp"
+                               },
+                               "2": {
+                                       "name": 
"entity.name.tag.named.group.regexp"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"support.other.parenthesis.regexp punctuation.parenthesis.named.end.regexp"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": 
"#double-one-regexp-expression"
+                               }
+                       ]
+               },
+               "double-one-regexp-comments": {
+                       "name": "comment.regexp",
+                       "begin": "\\(\\?#",
+                       "end": "(\\)|(?=\"))|((?=(?<!\\\\)\\n))",
+                       "beginCaptures": {
+                               "0": {
+                                       "name": 
"punctuation.comment.begin.regexp"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": "punctuation.comment.end.regexp"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": "#codetags"
+                               }
+                       ]
+               },
+               "double-one-regexp-lookahead": {
+                       "begin": "(\\()\\?=",
+                       "end": "(\\)|(?=\"))|((?=(?<!\\\\)\\n))",
+                       "beginCaptures": {
+                               "0": {
+                                       "name": 
"keyword.operator.lookahead.regexp"
+                               },
+                               "1": {
+                                       "name": 
"punctuation.parenthesis.lookahead.begin.regexp"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"keyword.operator.lookahead.regexp punctuation.parenthesis.lookahead.end.regexp"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": 
"#double-one-regexp-expression"
+                               }
+                       ]
+               },
+               "double-one-regexp-lookahead-negative": {
+                       "begin": "(\\()\\?!",
+                       "end": "(\\)|(?=\"))|((?=(?<!\\\\)\\n))",
+                       "beginCaptures": {
+                               "0": {
+                                       "name": 
"keyword.operator.lookahead.negative.regexp"
+                               },
+                               "1": {
+                                       "name": 
"punctuation.parenthesis.lookahead.begin.regexp"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"keyword.operator.lookahead.negative.regexp 
punctuation.parenthesis.lookahead.end.regexp"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": 
"#double-one-regexp-expression"
+                               }
+                       ]
+               },
+               "double-one-regexp-lookbehind": {
+                       "begin": "(\\()\\?<=",
+                       "end": "(\\)|(?=\"))|((?=(?<!\\\\)\\n))",
+                       "beginCaptures": {
+                               "0": {
+                                       "name": 
"keyword.operator.lookbehind.regexp"
+                               },
+                               "1": {
+                                       "name": 
"punctuation.parenthesis.lookbehind.begin.regexp"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"keyword.operator.lookbehind.regexp 
punctuation.parenthesis.lookbehind.end.regexp"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": 
"#double-one-regexp-expression"
+                               }
+                       ]
+               },
+               "double-one-regexp-lookbehind-negative": {
+                       "begin": "(\\()\\?<!",
+                       "end": "(\\)|(?=\"))|((?=(?<!\\\\)\\n))",
+                       "beginCaptures": {
+                               "0": {
+                                       "name": 
"keyword.operator.lookbehind.negative.regexp"
+                               },
+                               "1": {
+                                       "name": 
"punctuation.parenthesis.lookbehind.begin.regexp"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"keyword.operator.lookbehind.negative.regexp 
punctuation.parenthesis.lookbehind.end.regexp"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": 
"#double-one-regexp-expression"
+                               }
+                       ]
+               },
+               "double-one-regexp-conditional": {
+                       "begin": 
"(\\()\\?\\((\\w+(?:\\s+[[:alnum:]]+)?|\\d+)\\)",
+                       "end": "(\\)|(?=\"))|((?=(?<!\\\\)\\n))",
+                       "beginCaptures": {
+                               "0": {
+                                       "name": 
"keyword.operator.conditional.regexp"
+                               },
+                               "1": {
+                                       "name": 
"punctuation.parenthesis.conditional.begin.regexp"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"keyword.operator.conditional.negative.regexp 
punctuation.parenthesis.conditional.end.regexp"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": 
"#double-one-regexp-expression"
+                               }
+                       ]
+               },
+               "double-one-regexp-parentheses-non-capturing": {
+                       "begin": "\\(\\?:",
+                       "end": "(\\)|(?=\"))|((?=(?<!\\\\)\\n))",
+                       "beginCaptures": {
+                               "0": {
+                                       "name": 
"support.other.parenthesis.regexp 
punctuation.parenthesis.non-capturing.begin.regexp"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"support.other.parenthesis.regexp 
punctuation.parenthesis.non-capturing.end.regexp"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": 
"#double-one-regexp-expression"
+                               }
+                       ]
+               },
+               "double-one-regexp-parentheses": {
+                       "begin": "\\(",
+                       "end": "(\\)|(?=\"))|((?=(?<!\\\\)\\n))",
+                       "beginCaptures": {
+                               "0": {
+                                       "name": 
"support.other.parenthesis.regexp punctuation.parenthesis.begin.regexp"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"support.other.parenthesis.regexp punctuation.parenthesis.end.regexp"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": 
"#double-one-regexp-expression"
+                               }
+                       ]
+               },
+               "double-three-regexp-expression": {
+                       "patterns": [
+                               {
+                                       "include": "#regexp-base-expression"
+                               },
+                               {
+                                       "include": 
"#double-three-regexp-character-set"
+                               },
+                               {
+                                       "include": 
"#double-three-regexp-comments"
+                               },
+                               {
+                                       "include": "#regexp-flags"
+                               },
+                               {
+                                       "include": 
"#double-three-regexp-named-group"
+                               },
+                               {
+                                       "include": "#regexp-backreference"
+                               },
+                               {
+                                       "include": 
"#double-three-regexp-lookahead"
+                               },
+                               {
+                                       "include": 
"#double-three-regexp-lookahead-negative"
+                               },
+                               {
+                                       "include": 
"#double-three-regexp-lookbehind"
+                               },
+                               {
+                                       "include": 
"#double-three-regexp-lookbehind-negative"
+                               },
+                               {
+                                       "include": 
"#double-three-regexp-conditional"
+                               },
+                               {
+                                       "include": 
"#double-three-regexp-parentheses-non-capturing"
+                               },
+                               {
+                                       "include": 
"#double-three-regexp-parentheses"
+                               },
+                               {
+                                       "include": 
"#comments-string-double-three"
+                               }
+                       ]
+               },
+               "double-three-regexp-character-set": {
+                       "patterns": [
+                               {
+                                       "match": "(?x)\n  \\[ \\^? \\] (?! 
.*?\\])\n"
+                               },
+                               {
+                                       "name": "meta.character.set.regexp",
+                                       "begin": "(\\[)(\\^)?(\\])?",
+                                       "end": "(\\]|(?=\"\"\"))",
+                                       "beginCaptures": {
+                                               "1": {
+                                                       "name": 
"punctuation.character.set.begin.regexp constant.other.set.regexp"
+                                               },
+                                               "2": {
+                                                       "name": 
"keyword.operator.negation.regexp"
+                                               },
+                                               "3": {
+                                                       "name": 
"constant.character.set.regexp"
+                                               }
+                                       },
+                                       "endCaptures": {
+                                               "1": {
+                                                       "name": 
"punctuation.character.set.end.regexp constant.other.set.regexp"
+                                               },
+                                               "2": {
+                                                       "name": 
"invalid.illegal.newline.python"
+                                               }
+                                       },
+                                       "patterns": [
+                                               {
+                                                       "include": 
"#regexp-charecter-set-escapes"
+                                               },
+                                               {
+                                                       "name": 
"constant.character.set.regexp",
+                                                       "match": "[^\\n]"
+                                               }
+                                       ]
+                               }
+                       ]
+               },
+               "double-three-regexp-named-group": {
+                       "name": "meta.named.regexp",
+                       "begin": "(?x)\n  (\\()  (\\?P 
<\\w+(?:\\s+[[:alnum:]]+)?>)\n",
+                       "end": "(\\)|(?=\"\"\"))",
+                       "beginCaptures": {
+                               "1": {
+                                       "name": 
"support.other.parenthesis.regexp punctuation.parenthesis.named.begin.regexp"
+                               },
+                               "2": {
+                                       "name": 
"entity.name.tag.named.group.regexp"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"support.other.parenthesis.regexp punctuation.parenthesis.named.end.regexp"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": 
"#double-three-regexp-expression"
+                               },
+                               {
+                                       "include": 
"#comments-string-double-three"
+                               }
+                       ]
+               },
+               "double-three-regexp-comments": {
+                       "name": "comment.regexp",
+                       "begin": "\\(\\?#",
+                       "end": "(\\)|(?=\"\"\"))",
+                       "beginCaptures": {
+                               "0": {
+                                       "name": 
"punctuation.comment.begin.regexp"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": "punctuation.comment.end.regexp"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": "#codetags"
+                               }
+                       ]
+               },
+               "double-three-regexp-lookahead": {
+                       "begin": "(\\()\\?=",
+                       "end": "(\\)|(?=\"\"\"))",
+                       "beginCaptures": {
+                               "0": {
+                                       "name": 
"keyword.operator.lookahead.regexp"
+                               },
+                               "1": {
+                                       "name": 
"punctuation.parenthesis.lookahead.begin.regexp"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"keyword.operator.lookahead.regexp punctuation.parenthesis.lookahead.end.regexp"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": 
"#double-three-regexp-expression"
+                               },
+                               {
+                                       "include": 
"#comments-string-double-three"
+                               }
+                       ]
+               },
+               "double-three-regexp-lookahead-negative": {
+                       "begin": "(\\()\\?!",
+                       "end": "(\\)|(?=\"\"\"))",
+                       "beginCaptures": {
+                               "0": {
+                                       "name": 
"keyword.operator.lookahead.negative.regexp"
+                               },
+                               "1": {
+                                       "name": 
"punctuation.parenthesis.lookahead.begin.regexp"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"keyword.operator.lookahead.negative.regexp 
punctuation.parenthesis.lookahead.end.regexp"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": 
"#double-three-regexp-expression"
+                               },
+                               {
+                                       "include": 
"#comments-string-double-three"
+                               }
+                       ]
+               },
+               "double-three-regexp-lookbehind": {
+                       "begin": "(\\()\\?<=",
+                       "end": "(\\)|(?=\"\"\"))",
+                       "beginCaptures": {
+                               "0": {
+                                       "name": 
"keyword.operator.lookbehind.regexp"
+                               },
+                               "1": {
+                                       "name": 
"punctuation.parenthesis.lookbehind.begin.regexp"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"keyword.operator.lookbehind.regexp 
punctuation.parenthesis.lookbehind.end.regexp"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": 
"#double-three-regexp-expression"
+                               },
+                               {
+                                       "include": 
"#comments-string-double-three"
+                               }
+                       ]
+               },
+               "double-three-regexp-lookbehind-negative": {
+                       "begin": "(\\()\\?<!",
+                       "end": "(\\)|(?=\"\"\"))",
+                       "beginCaptures": {
+                               "0": {
+                                       "name": 
"keyword.operator.lookbehind.negative.regexp"
+                               },
+                               "1": {
+                                       "name": 
"punctuation.parenthesis.lookbehind.begin.regexp"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"keyword.operator.lookbehind.negative.regexp 
punctuation.parenthesis.lookbehind.end.regexp"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": 
"#double-three-regexp-expression"
+                               },
+                               {
+                                       "include": 
"#comments-string-double-three"
+                               }
+                       ]
+               },
+               "double-three-regexp-conditional": {
+                       "begin": 
"(\\()\\?\\((\\w+(?:\\s+[[:alnum:]]+)?|\\d+)\\)",
+                       "end": "(\\)|(?=\"\"\"))",
+                       "beginCaptures": {
+                               "0": {
+                                       "name": 
"keyword.operator.conditional.regexp"
+                               },
+                               "1": {
+                                       "name": 
"punctuation.parenthesis.conditional.begin.regexp"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"keyword.operator.conditional.negative.regexp 
punctuation.parenthesis.conditional.end.regexp"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": 
"#double-three-regexp-expression"
+                               },
+                               {
+                                       "include": 
"#comments-string-double-three"
+                               }
+                       ]
+               },
+               "double-three-regexp-parentheses-non-capturing": {
+                       "begin": "\\(\\?:",
+                       "end": "(\\)|(?=\"\"\"))",
+                       "beginCaptures": {
+                               "0": {
+                                       "name": 
"support.other.parenthesis.regexp 
punctuation.parenthesis.non-capturing.begin.regexp"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"support.other.parenthesis.regexp 
punctuation.parenthesis.non-capturing.end.regexp"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": 
"#double-three-regexp-expression"
+                               },
+                               {
+                                       "include": 
"#comments-string-double-three"
+                               }
+                       ]
+               },
+               "double-three-regexp-parentheses": {
+                       "begin": "\\(",
+                       "end": "(\\)|(?=\"\"\"))",
+                       "beginCaptures": {
+                               "0": {
+                                       "name": 
"support.other.parenthesis.regexp punctuation.parenthesis.begin.regexp"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"support.other.parenthesis.regexp punctuation.parenthesis.end.regexp"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": 
"#double-three-regexp-expression"
+                               },
+                               {
+                                       "include": 
"#comments-string-double-three"
+                               }
+                       ]
+               },
+               "regexp-single-one-line": {
+                       "name": "string.regexp.quoted.single.python",
+                       "begin": "\\b(([uU]r)|([bB]r)|(r[bB]?))(\\')",
+                       "end": "(\\')|(?<!\\\\)(\\n)",
+                       "beginCaptures": {
+                               "2": {
+                                       "name": 
"invalid.deprecated.prefix.python"
+                               },
+                               "3": {
+                                       "name": "storage.type.string.python"
+                               },
+                               "4": {
+                                       "name": "storage.type.string.python"
+                               },
+                               "5": {
+                                       "name": 
"punctuation.definition.string.begin.python"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"punctuation.definition.string.end.python"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": 
"#single-one-regexp-expression"
+                               }
+                       ]
+               },
+               "regexp-single-three-line": {
+                       "name": "string.regexp.quoted.multi.python",
+                       "begin": "\\b(([uU]r)|([bB]r)|(r[bB]?))(\\'\\'\\')",
+                       "end": "(\\'\\'\\')",
+                       "beginCaptures": {
+                               "2": {
+                                       "name": 
"invalid.deprecated.prefix.python"
+                               },
+                               "3": {
+                                       "name": "storage.type.string.python"
+                               },
+                               "4": {
+                                       "name": "storage.type.string.python"
+                               },
+                               "5": {
+                                       "name": 
"punctuation.definition.string.begin.python"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"punctuation.definition.string.end.python"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": 
"#single-three-regexp-expression"
+                               }
+                       ]
+               },
+               "regexp-double-one-line": {
+                       "name": "string.regexp.quoted.single.python",
+                       "begin": "\\b(([uU]r)|([bB]r)|(r[bB]?))(\")",
+                       "end": "(\")|(?<!\\\\)(\\n)",
+                       "beginCaptures": {
+                               "2": {
+                                       "name": 
"invalid.deprecated.prefix.python"
+                               },
+                               "3": {
+                                       "name": "storage.type.string.python"
+                               },
+                               "4": {
+                                       "name": "storage.type.string.python"
+                               },
+                               "5": {
+                                       "name": 
"punctuation.definition.string.begin.python"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"punctuation.definition.string.end.python"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": 
"#double-one-regexp-expression"
+                               }
+                       ]
+               },
+               "regexp-double-three-line": {
+                       "name": "string.regexp.quoted.multi.python",
+                       "begin": "\\b(([uU]r)|([bB]r)|(r[bB]?))(\"\"\")",
+                       "end": "(\"\"\")",
+                       "beginCaptures": {
+                               "2": {
+                                       "name": 
"invalid.deprecated.prefix.python"
+                               },
+                               "3": {
+                                       "name": "storage.type.string.python"
+                               },
+                               "4": {
+                                       "name": "storage.type.string.python"
+                               },
+                               "5": {
+                                       "name": 
"punctuation.definition.string.begin.python"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"punctuation.definition.string.end.python"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": 
"#double-three-regexp-expression"
+                               }
+                       ]
+               },
+               "string-raw-quoted-single-line": {
+                       "name": "string.quoted.raw.single.python",
+                       "begin": "\\b(([uU]R)|(R))((['\"]))",
+                       "end": "(\\4)|((?<!\\\\)\\n)",
+                       "beginCaptures": {
+                               "2": {
+                                       "name": 
"invalid.deprecated.prefix.python"
+                               },
+                               "3": {
+                                       "name": "storage.type.string.python"
+                               },
+                               "4": {
+                                       "name": 
"punctuation.definition.string.begin.python"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"punctuation.definition.string.end.python"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": 
"#string-single-bad-brace1-formatting-raw"
+                               },
+                               {
+                                       "include": 
"#string-single-bad-brace2-formatting-raw"
+                               },
+                               {
+                                       "include": "#string-raw-guts"
+                               }
+                       ]
+               },
+               "string-bin-quoted-single-line": {
+                       "name": "string.quoted.binary.single.python",
+                       "begin": "(\\b[bB])((['\"]))",
+                       "end": "(\\2)|((?<!\\\\)\\n)",
+                       "beginCaptures": {
+                               "1": {
+                                       "name": "storage.type.string.python"
+                               },
+                               "2": {
+                                       "name": 
"punctuation.definition.string.begin.python"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"punctuation.definition.string.end.python"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": "#string-entity"
+                               }
+                       ]
+               },
+               "string-raw-bin-quoted-single-line": {
+                       "name": "string.quoted.raw.binary.single.python",
+                       "begin": "(\\b(?:R[bB]|[bB]R))((['\"]))",
+                       "end": "(\\2)|((?<!\\\\)\\n)",
+                       "beginCaptures": {
+                               "1": {
+                                       "name": "storage.type.string.python"
+                               },
+                               "2": {
+                                       "name": 
"punctuation.definition.string.begin.python"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"punctuation.definition.string.end.python"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": "#string-raw-bin-guts"
+                               }
+                       ]
+               },
+               "string-quoted-single-line": {
+                       "name": "string.quoted.single.python",
+                       "begin": "(?:\\b([rR])(?=[uU]))?([uU])?((['\"]))",
+                       "end": "(\\3)|((?<!\\\\)\\n)",
+                       "beginCaptures": {
+                               "1": {
+                                       "name": "invalid.illegal.prefix.python"
+                               },
+                               "2": {
+                                       "name": "storage.type.string.python"
+                               },
+                               "3": {
+                                       "name": 
"punctuation.definition.string.begin.python"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"punctuation.definition.string.end.python"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": 
"#string-single-bad-brace1-formatting-unicode"
+                               },
+                               {
+                                       "include": 
"#string-single-bad-brace2-formatting-unicode"
+                               },
+                               {
+                                       "include": "#string-unicode-guts"
+                               }
+                       ]
+               },
+               "string-single-bad-brace1-formatting-unicode": {
+                       "comment": "template using {% ... %}",
+                       "begin": "(?x)\n    (?= \\{%\n          ( .*? 
(?!(['\"])|((?<!\\\\)\\n)) )\n        %\\}\n    )\n",
+                       "end": "(?=(['\"])|((?<!\\\\)\\n))",
+                       "patterns": [
+                               {
+                                       "include": "#escape-sequence-unicode"
+                               },
+                               {
+                                       "include": "#escape-sequence"
+                               },
+                               {
+                                       "include": "#string-line-continuation"
+                               }
+                       ]
+               },
+               "string-single-bad-brace1-formatting-raw": {
+                       "comment": "template using {% ... %}",
+                       "begin": "(?x)\n    (?= \\{%\n          ( .*? 
(?!(['\"])|((?<!\\\\)\\n)) )\n        %\\}\n    )\n",
+                       "end": "(?=(['\"])|((?<!\\\\)\\n))",
+                       "patterns": [
+                               {
+                                       "include": "#string-consume-escape"
+                               }
+                       ]
+               },
+               "string-single-bad-brace2-formatting-unicode": {
+                       "comment": "odd format or format-like syntax",
+                       "begin": "(?x)\n    (?!\\{\\{)\n    (?= \\{ (\n         
     \\w*? (?!(['\"])|((?<!\\\\)\\n)) [^!:\\.\\[}\\w]\n           )\n        
.*?(?!(['\"])|((?<!\\\\)\\n))\n        \\}\n    )\n",
+                       "end": "(?=(['\"])|((?<!\\\\)\\n))",
+                       "patterns": [
+                               {
+                                       "include": "#escape-sequence-unicode"
+                               },
+                               {
+                                       "include": "#string-entity"
+                               }
+                       ]
+               },
+               "string-single-bad-brace2-formatting-raw": {
+                       "comment": "odd format or format-like syntax",
+                       "begin": "(?x)\n    (?!\\{\\{)\n    (?= \\{ (\n         
     \\w*? (?!(['\"])|((?<!\\\\)\\n)) [^!:\\.\\[}\\w]\n           )\n        
.*?(?!(['\"])|((?<!\\\\)\\n))\n        \\}\n    )\n",
+                       "end": "(?=(['\"])|((?<!\\\\)\\n))",
+                       "patterns": [
+                               {
+                                       "include": "#string-consume-escape"
+                               },
+                               {
+                                       "include": "#string-formatting"
+                               }
+                       ]
+               },
+               "string-raw-quoted-multi-line": {
+                       "name": "string.quoted.raw.multi.python",
+                       "begin": "\\b(([uU]R)|(R))('''|\"\"\")",
+                       "end": "(\\4)",
+                       "beginCaptures": {
+                               "2": {
+                                       "name": 
"invalid.deprecated.prefix.python"
+                               },
+                               "3": {
+                                       "name": "storage.type.string.python"
+                               },
+                               "4": {
+                                       "name": 
"punctuation.definition.string.begin.python"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"punctuation.definition.string.end.python"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": 
"#string-multi-bad-brace1-formatting-raw"
+                               },
+                               {
+                                       "include": 
"#string-multi-bad-brace2-formatting-raw"
+                               },
+                               {
+                                       "include": "#string-raw-guts"
+                               }
+                       ]
+               },
+               "string-bin-quoted-multi-line": {
+                       "name": "string.quoted.binary.multi.python",
+                       "begin": "(\\b[bB])('''|\"\"\")",
+                       "end": "(\\2)",
+                       "beginCaptures": {
+                               "1": {
+                                       "name": "storage.type.string.python"
+                               },
+                               "2": {
+                                       "name": 
"punctuation.definition.string.begin.python"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"punctuation.definition.string.end.python"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": "#string-entity"
+                               }
+                       ]
+               },
+               "string-raw-bin-quoted-multi-line": {
+                       "name": "string.quoted.raw.binary.multi.python",
+                       "begin": "(\\b(?:R[bB]|[bB]R))('''|\"\"\")",
+                       "end": "(\\2)",
+                       "beginCaptures": {
+                               "1": {
+                                       "name": "storage.type.string.python"
+                               },
+                               "2": {
+                                       "name": 
"punctuation.definition.string.begin.python"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"punctuation.definition.string.end.python"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": "#string-raw-bin-guts"
+                               }
+                       ]
+               },
+               "string-quoted-multi-line": {
+                       "name": "string.quoted.multi.python",
+                       "begin": "(?:\\b([rR])(?=[uU]))?([uU])?('''|\"\"\")",
+                       "end": "(\\3)",
+                       "beginCaptures": {
+                               "1": {
+                                       "name": "invalid.illegal.prefix.python"
+                               },
+                               "2": {
+                                       "name": "storage.type.string.python"
+                               },
+                               "3": {
+                                       "name": 
"punctuation.definition.string.begin.python"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"punctuation.definition.string.end.python"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": 
"#string-multi-bad-brace1-formatting-unicode"
+                               },
+                               {
+                                       "include": 
"#string-multi-bad-brace2-formatting-unicode"
+                               },
+                               {
+                                       "include": "#string-unicode-guts"
+                               }
+                       ]
+               },
+               "string-multi-bad-brace1-formatting-unicode": {
+                       "comment": "template using {% ... %}",
+                       "begin": "(?x)\n    (?= \\{%\n          ( .*? 
(?!'''|\"\"\") )\n        %\\}\n    )\n",
+                       "end": "(?='''|\"\"\")",
+                       "patterns": [
+                               {
+                                       "include": "#escape-sequence-unicode"
+                               },
+                               {
+                                       "include": "#escape-sequence"
+                               },
+                               {
+                                       "include": "#string-line-continuation"
+                               }
+                       ]
+               },
+               "string-multi-bad-brace1-formatting-raw": {
+                       "comment": "template using {% ... %}",
+                       "begin": "(?x)\n    (?= \\{%\n          ( .*? 
(?!'''|\"\"\") )\n        %\\}\n    )\n",
+                       "end": "(?='''|\"\"\")",
+                       "patterns": [
+                               {
+                                       "include": "#string-consume-escape"
+                               }
+                       ]
+               },
+               "string-multi-bad-brace2-formatting-unicode": {
+                       "comment": "odd format or format-like syntax",
+                       "begin": "(?x)\n    (?!\\{\\{)\n    (?= \\{ (\n         
     \\w*? (?!'''|\"\"\") [^!:\\.\\[}\\w]\n           )\n        
.*?(?!'''|\"\"\")\n        \\}\n    )\n",
+                       "end": "(?='''|\"\"\")",
+                       "patterns": [
+                               {
+                                       "include": "#escape-sequence-unicode"
+                               },
+                               {
+                                       "include": "#string-entity"
+                               }
+                       ]
+               },
+               "string-multi-bad-brace2-formatting-raw": {
+                       "comment": "odd format or format-like syntax",
+                       "begin": "(?x)\n    (?!\\{\\{)\n    (?= \\{ (\n         
     \\w*? (?!'''|\"\"\") [^!:\\.\\[}\\w]\n           )\n        
.*?(?!'''|\"\"\")\n        \\}\n    )\n",
+                       "end": "(?='''|\"\"\")",
+                       "patterns": [
+                               {
+                                       "include": "#string-consume-escape"
+                               },
+                               {
+                                       "include": "#string-formatting"
+                               }
+                       ]
+               },
+               "fstring-fnorm-quoted-single-line": {
+                       "name": "meta.fstring.python",
+                       "begin": "(\\b[fF])([bBuU])?((['\"]))",
+                       "end": "(\\3)|((?<!\\\\)\\n)",
+                       "beginCaptures": {
+                               "1": {
+                                       "name": "string.interpolated.python 
string.quoted.single.python storage.type.string.python"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.prefix.python"
+                               },
+                               "3": {
+                                       "name": 
"punctuation.definition.string.begin.python string.interpolated.python 
string.quoted.single.python"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"punctuation.definition.string.end.python string.interpolated.python 
string.quoted.single.python"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": "#fstring-guts"
+                               },
+                               {
+                                       "include": 
"#fstring-illegal-single-brace"
+                               },
+                               {
+                                       "include": "#fstring-single-brace"
+                               },
+                               {
+                                       "include": "#fstring-single-core"
+                               }
+                       ]
+               },
+               "fstring-normf-quoted-single-line": {
+                       "name": "meta.fstring.python",
+                       "begin": "(\\b[bBuU])([fF])((['\"]))",
+                       "end": "(\\3)|((?<!\\\\)\\n)",
+                       "beginCaptures": {
+                               "1": {
+                                       "name": "invalid.illegal.prefix.python"
+                               },
+                               "2": {
+                                       "name": "string.interpolated.python 
string.quoted.single.python storage.type.string.python"
+                               },
+                               "3": {
+                                       "name": 
"punctuation.definition.string.begin.python string.quoted.single.python"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"punctuation.definition.string.end.python string.interpolated.python 
string.quoted.single.python"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": "#fstring-guts"
+                               },
+                               {
+                                       "include": 
"#fstring-illegal-single-brace"
+                               },
+                               {
+                                       "include": "#fstring-single-brace"
+                               },
+                               {
+                                       "include": "#fstring-single-core"
+                               }
+                       ]
+               },
+               "fstring-raw-quoted-single-line": {
+                       "name": "meta.fstring.python",
+                       "begin": "(\\b(?:[rR][fF]|[fF][rR]))((['\"]))",
+                       "end": "(\\2)|((?<!\\\\)\\n)",
+                       "beginCaptures": {
+                               "1": {
+                                       "name": "string.interpolated.python 
string.quoted.raw.single.python storage.type.string.python"
+                               },
+                               "2": {
+                                       "name": 
"punctuation.definition.string.begin.python string.quoted.raw.single.python"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"punctuation.definition.string.end.python string.interpolated.python 
string.quoted.raw.single.python"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": "#fstring-raw-guts"
+                               },
+                               {
+                                       "include": 
"#fstring-illegal-single-brace"
+                               },
+                               {
+                                       "include": "#fstring-single-brace"
+                               },
+                               {
+                                       "include": "#fstring-raw-single-core"
+                               }
+                       ]
+               },
+               "fstring-single-core": {
+                       "name": "string.interpolated.python 
string.quoted.single.python",
+                       "match": "(?x)\n  (.+?)\n    (\n      (?# .* and .*? in 
multi-line match need special handling of\n        newlines otherwise 
SublimeText and Atom will match slightly\n        differently.\n\n        The 
guard for newlines has to be separate from the\n        lookahead because of 
special $ matching rule.)\n      ($\\n?)\n      |\n      
(?=[\\\\\\}\\{]|(['\"])|((?<!\\\\)\\n))\n    )\n  (?# due to how multiline 
regexps are matched we need a special case\n    for matching a newline chara 
[...]
+               },
+               "fstring-raw-single-core": {
+                       "name": "string.interpolated.python 
string.quoted.raw.single.python",
+                       "match": "(?x)\n  (.+?)\n    (\n      (?# .* and .*? in 
multi-line match need special handling of\n        newlines otherwise 
SublimeText and Atom will match slightly\n        differently.\n\n        The 
guard for newlines has to be separate from the\n        lookahead because of 
special $ matching rule.)\n      ($\\n?)\n      |\n      
(?=[\\\\\\}\\{]|(['\"])|((?<!\\\\)\\n))\n    )\n  (?# due to how multiline 
regexps are matched we need a special case\n    for matching a newline chara 
[...]
+               },
+               "fstring-single-brace": {
+                       "comment": "value interpolation using { ... }",
+                       "begin": "(\\{)",
+                       "end": "(?x)\n  (\\})|(?=\\n)\n",
+                       "beginCaptures": {
+                               "1": {
+                                       "name": 
"constant.character.format.placeholder.other.python"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"constant.character.format.placeholder.other.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": "#fstring-terminator-single"
+                               },
+                               {
+                                       "include": "#f-expression"
+                               }
+                       ]
+               },
+               "fstring-terminator-single": {
+                       "patterns": [
+                               {
+                                       "name": "storage.type.format.python",
+                                       "match": "(=(![rsa])?)(?=})"
+                               },
+                               {
+                                       "name": "storage.type.format.python",
+                                       "match": "(=?![rsa])(?=})"
+                               },
+                               {
+                                       "match": "(?x)\n  ( (?: =?) (?: 
![rsa])? )\n    ( : \\w? [<>=^]? [-+ ]? \\#?\n      \\d* ,? (\\.\\d+)? 
[bcdeEfFgGnosxX%]? )(?=})\n",
+                                       "captures": {
+                                               "1": {
+                                                       "name": 
"storage.type.format.python"
+                                               },
+                                               "2": {
+                                                       "name": 
"storage.type.format.python"
+                                               }
+                                       }
+                               },
+                               {
+                                       "include": 
"#fstring-terminator-single-tail"
+                               }
+                       ]
+               },
+               "fstring-terminator-single-tail": {
+                       "begin": "((?:=?)(?:![rsa])?)(:)(?=.*?{)",
+                       "end": "(?=})|(?=\\n)",
+                       "beginCaptures": {
+                               "1": {
+                                       "name": "storage.type.format.python"
+                               },
+                               "2": {
+                                       "name": "storage.type.format.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": 
"#fstring-illegal-single-brace"
+                               },
+                               {
+                                       "include": "#fstring-single-brace"
+                               },
+                               {
+                                       "name": "storage.type.format.python",
+                                       "match": "([bcdeEfFgGnosxX%])(?=})"
+                               },
+                               {
+                                       "name": "storage.type.format.python",
+                                       "match": "(\\.\\d+)"
+                               },
+                               {
+                                       "name": "storage.type.format.python",
+                                       "match": "(,)"
+                               },
+                               {
+                                       "name": "storage.type.format.python",
+                                       "match": "(\\d+)"
+                               },
+                               {
+                                       "name": "storage.type.format.python",
+                                       "match": "(\\#)"
+                               },
+                               {
+                                       "name": "storage.type.format.python",
+                                       "match": "([-+ ])"
+                               },
+                               {
+                                       "name": "storage.type.format.python",
+                                       "match": "([<>=^])"
+                               },
+                               {
+                                       "name": "storage.type.format.python",
+                                       "match": "(\\w)"
+                               }
+                       ]
+               },
+               "fstring-fnorm-quoted-multi-line": {
+                       "name": "meta.fstring.python",
+                       "begin": "(\\b[fF])([bBuU])?('''|\"\"\")",
+                       "end": "(\\3)",
+                       "beginCaptures": {
+                               "1": {
+                                       "name": "string.interpolated.python 
string.quoted.multi.python storage.type.string.python"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.prefix.python"
+                               },
+                               "3": {
+                                       "name": 
"punctuation.definition.string.begin.python string.interpolated.python 
string.quoted.multi.python"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"punctuation.definition.string.end.python string.interpolated.python 
string.quoted.multi.python"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": "#fstring-guts"
+                               },
+                               {
+                                       "include": 
"#fstring-illegal-multi-brace"
+                               },
+                               {
+                                       "include": "#fstring-multi-brace"
+                               },
+                               {
+                                       "include": "#fstring-multi-core"
+                               }
+                       ]
+               },
+               "fstring-normf-quoted-multi-line": {
+                       "name": "meta.fstring.python",
+                       "begin": "(\\b[bBuU])([fF])('''|\"\"\")",
+                       "end": "(\\3)",
+                       "beginCaptures": {
+                               "1": {
+                                       "name": "invalid.illegal.prefix.python"
+                               },
+                               "2": {
+                                       "name": "string.interpolated.python 
string.quoted.multi.python storage.type.string.python"
+                               },
+                               "3": {
+                                       "name": 
"punctuation.definition.string.begin.python string.quoted.multi.python"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"punctuation.definition.string.end.python string.interpolated.python 
string.quoted.multi.python"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": "#fstring-guts"
+                               },
+                               {
+                                       "include": 
"#fstring-illegal-multi-brace"
+                               },
+                               {
+                                       "include": "#fstring-multi-brace"
+                               },
+                               {
+                                       "include": "#fstring-multi-core"
+                               }
+                       ]
+               },
+               "fstring-raw-quoted-multi-line": {
+                       "name": "meta.fstring.python",
+                       "begin": "(\\b(?:[rR][fF]|[fF][rR]))('''|\"\"\")",
+                       "end": "(\\2)",
+                       "beginCaptures": {
+                               "1": {
+                                       "name": "string.interpolated.python 
string.quoted.raw.multi.python storage.type.string.python"
+                               },
+                               "2": {
+                                       "name": 
"punctuation.definition.string.begin.python string.quoted.raw.multi.python"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"punctuation.definition.string.end.python string.interpolated.python 
string.quoted.raw.multi.python"
+                               },
+                               "2": {
+                                       "name": "invalid.illegal.newline.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": "#fstring-raw-guts"
+                               },
+                               {
+                                       "include": 
"#fstring-illegal-multi-brace"
+                               },
+                               {
+                                       "include": "#fstring-multi-brace"
+                               },
+                               {
+                                       "include": "#fstring-raw-multi-core"
+                               }
+                       ]
+               },
+               "fstring-multi-core": {
+                       "name": "string.interpolated.python 
string.quoted.multi.python",
+                       "match": "(?x)\n  (.+?)\n    (\n      (?# .* and .*? in 
multi-line match need special handling of\n        newlines otherwise 
SublimeText and Atom will match slightly\n        differently.\n\n        The 
guard for newlines has to be separate from the\n        lookahead because of 
special $ matching rule.)\n      ($\\n?)\n      |\n      
(?=[\\\\\\}\\{]|'''|\"\"\")\n    )\n  (?# due to how multiline regexps are 
matched we need a special case\n    for matching a newline character)\n  | 
\\n\n"
+               },
+               "fstring-raw-multi-core": {
+                       "name": "string.interpolated.python 
string.quoted.raw.multi.python",
+                       "match": "(?x)\n  (.+?)\n    (\n      (?# .* and .*? in 
multi-line match need special handling of\n        newlines otherwise 
SublimeText and Atom will match slightly\n        differently.\n\n        The 
guard for newlines has to be separate from the\n        lookahead because of 
special $ matching rule.)\n      ($\\n?)\n      |\n      
(?=[\\\\\\}\\{]|'''|\"\"\")\n    )\n  (?# due to how multiline regexps are 
matched we need a special case\n    for matching a newline character)\n  | 
\\n\n"
+               },
+               "fstring-multi-brace": {
+                       "comment": "value interpolation using { ... }",
+                       "begin": "(\\{)",
+                       "end": "(?x)\n  (\\})\n",
+                       "beginCaptures": {
+                               "1": {
+                                       "name": 
"constant.character.format.placeholder.other.python"
+                               }
+                       },
+                       "endCaptures": {
+                               "1": {
+                                       "name": 
"constant.character.format.placeholder.other.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": "#fstring-terminator-multi"
+                               },
+                               {
+                                       "include": "#f-expression"
+                               }
+                       ]
+               },
+               "fstring-terminator-multi": {
+                       "patterns": [
+                               {
+                                       "name": "storage.type.format.python",
+                                       "match": "(=(![rsa])?)(?=})"
+                               },
+                               {
+                                       "name": "storage.type.format.python",
+                                       "match": "(=?![rsa])(?=})"
+                               },
+                               {
+                                       "match": "(?x)\n  ( (?: =?) (?: 
![rsa])? )\n    ( : \\w? [<>=^]? [-+ ]? \\#?\n      \\d* ,? (\\.\\d+)? 
[bcdeEfFgGnosxX%]? )(?=})\n",
+                                       "captures": {
+                                               "1": {
+                                                       "name": 
"storage.type.format.python"
+                                               },
+                                               "2": {
+                                                       "name": 
"storage.type.format.python"
+                                               }
+                                       }
+                               },
+                               {
+                                       "include": 
"#fstring-terminator-multi-tail"
+                               }
+                       ]
+               },
+               "fstring-terminator-multi-tail": {
+                       "begin": "((?:=?)(?:![rsa])?)(:)(?=.*?{)",
+                       "end": "(?=})",
+                       "beginCaptures": {
+                               "1": {
+                                       "name": "storage.type.format.python"
+                               },
+                               "2": {
+                                       "name": "storage.type.format.python"
+                               }
+                       },
+                       "patterns": [
+                               {
+                                       "include": 
"#fstring-illegal-multi-brace"
+                               },
+                               {
+                                       "include": "#fstring-multi-brace"
+                               },
+                               {
+                                       "name": "storage.type.format.python",
+                                       "match": "([bcdeEfFgGnosxX%])(?=})"
+                               },
+                               {
+                                       "name": "storage.type.format.python",
+                                       "match": "(\\.\\d+)"
+                               },
+                               {
+                                       "name": "storage.type.format.python",
+                                       "match": "(,)"
+                               },
+                               {
+                                       "name": "storage.type.format.python",
+                                       "match": "(\\d+)"
+                               },
+                               {
+                                       "name": "storage.type.format.python",
+                                       "match": "(\\#)"
+                               },
+                               {
+                                       "name": "storage.type.format.python",
+                                       "match": "([-+ ])"
+                               },
+                               {
+                                       "name": "storage.type.format.python",
+                                       "match": "([<>=^])"
+                               },
+                               {
+                                       "name": "storage.type.format.python",
+                                       "match": "(\\w)"
+                               }
+                       ]
+               }
+       }
+}
\ No newline at end of file
diff --git 
a/rcp/src/test/java/org/apache/hop/ui/hopgui/ContentEditorTm4eSupportTest.java 
b/rcp/src/test/java/org/apache/hop/ui/hopgui/ContentEditorTm4eSupportTest.java
new file mode 100644
index 0000000000..63cfc77a72
--- /dev/null
+++ 
b/rcp/src/test/java/org/apache/hop/ui/hopgui/ContentEditorTm4eSupportTest.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hop.ui.hopgui;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.io.InputStream;
+import org.junit.jupiter.api.Test;
+
+class ContentEditorTm4eSupportTest {
+
+  @Test
+  void scopeForLanguage_python_returnsSourcePython() {
+    assertEquals("source.python", 
ContentEditorTm4eSupport.scopeForLanguage("python"));
+  }
+
+  @Test
+  void scopeForLanguage_py_returnsSourcePython() {
+    assertEquals("source.python", 
ContentEditorTm4eSupport.scopeForLanguage("py"));
+  }
+
+  @Test
+  void pythonGrammarResourceIsOnClasspath() throws Exception {
+    try (InputStream in =
+        
ContentEditorTm4eSupport.class.getResourceAsStream("grammars/python.json")) {
+      assertNotNull(in, "grammars/python.json should be on the classpath");
+      assertTrue(in.read() >= 0, "python.json should not be empty");
+    }
+  }
+}


Reply via email to