search and replace block in python - python

I have a config(text) file with the following content :
hello {
if name == "foo" {
//do something
else {
// something else
}
# contents
}
world {
if name == "bar" {
//do something
else {
// do something else
}
# comments
}
I want to search in this file all the if else blocks with "foo". What is the best way in python ?

The comments warning you away from overly complex languages for configuration aren't wrong. But if this is something you must do, the next step is to build a parser that can read your grammar, and give you the token tree. Perhaps something lie pyparsing would be useful?

Related

Running a python script in C# after publishing C# project [duplicate]

I have been working on a problem for a while now which I cannot seem to resolve so I need some help! The problem is that I am writing a program in C# but I require a function from a Python file I created. This in itself is no problem:
...Usual Stuff
using IronPython.Hosting;
using IronPython.Runtime;
using Microsoft.Scripting;
using Microsoft.Scripting.Hosting;
namespace Program
{
public partial class Form1 : Form
{
Microsoft.Scripting.Hosting.ScriptEngine py;
Microsoft.Scripting.Hosting.ScriptScope s;
public Form1()
{
InitializeComponent();
py = Python.CreateEngine(); // allow us to run ironpython programs
s = py.CreateScope(); // you need this to get the variables
}
private void doPython()
{
//Step 1:
//Creating a new script runtime
var ironPythonRuntime = Python.CreateRuntime();
//Step 2:
//Load the Iron Python file/script into the memory
//Should be resolve at runtime
dynamic loadIPython = ironPythonRuntime.;
//Step 3:
//Invoke the method and print the result
double n = loadIPython.add(100, 200);
numericUpDown1.Value = (decimal)n;
}
}
}
However, this requires for the file 'first.py' to be wherever the program is once compiled. So if I wanted to share my program I would have to send both the executable and the python files which is very inconvenient. One way I thought to resolve this is by adding the 'first.py' file to the resources and running from there... but I don't know how to do this or even if it is possible.
Naturally the above code will not work for this as .UseFile method takes string arguments not byte[]. Does anyone know how I may progress?
Lets start with the simplest thing that could possibly work, you've got some code that looks a little like the following:
// ...
py = Python.CreateEngine(); // allow us to run ironpython programs
s = py.CreateScope(); // you need this to get the variables
var ironPythonRuntime = Python.CreateRuntime();
var x = py.CreateScriptSourceFromFile("SomeCode.py");
x.Execute(s);
var myFoo = s.GetVariable("myFoo");
var n = (double)myFoo.add(100, 200);
// ...
and we'd like to replace the line var x = py.CreateScriptSourceFromFile(... with something else; If we could get the embedded resource as a string, we could use ScriptingEngine.CreateScriptSourceFromString().
Cribbing this fine answer, we can get something that looks a bit like this:
string pySrc;
var resourceName = "ConsoleApplication1.SomeCode.py";
using (var stream = System.Reflection.Assembly.GetExecutingAssembly()
.GetManifestResourceStream(resourceName))
using (var reader = new System.IO.StreamReader(stream))
{
pySrc = reader.ReadToEnd();
}
var x = py.CreateScriptSourceFromString(pySrc);

How can I make QScintilla auto-indent like SublimeText?

Consider the below mcve:
import sys
import textwrap
from PyQt5.Qsci import QsciScintilla
from PyQt5.Qt import *
if __name__ == '__main__':
app = QApplication(sys.argv)
view = QsciScintilla()
view.SendScintilla(view.SCI_SETMULTIPLESELECTION, True)
view.SendScintilla(view.SCI_SETMULTIPASTE, 1)
view.SendScintilla(view.SCI_SETADDITIONALSELECTIONTYPING, True)
view.setAutoIndent(True)
view.setTabWidth(4)
view.setIndentationGuides(True)
view.setIndentationsUseTabs(False)
view.setBackspaceUnindents(True)
view.setText(textwrap.dedent("""\
def foo(a,b):
print('hello')
"""))
view.show()
app.exec_()
The behaviour of the auto-indent of the above snippet is really bad when comparing it with editors such as SublimeText or CodeMirror. First let's see how nice will behave the autoindent feature in SublimeText with single or multiple selections.
And now let's see how the auto-indent works in with the above snippet:
In comparison to SublimeText the way QScintilla works when auto-indentation is enabled with both single/multi selections is corky and really bad/unusable.
The first step to make the widget more like SublimeText/Codemirror would be disconnecting the current slot that makes autoindentation to behave badly, we can achieve that by doing:
print(view.receivers(view.SCN_CHARADDED))
view.SCN_CHARADDED.disconnect()
print(view.receivers(view.SCN_CHARADDED))
At this point you'd be ready to connect SCN_CHARADDED with your custom slot doing all the magic :)
QUESTION: How would you modify the above snippet so all selections will be preserved and the auto-indentation will behave exactly like SublimeText, Codemirror or any serious text editor out there?
REFERENCES:
https://www.riverbankcomputing.com/static/Docs/QScintilla/classQsciScintillaBase.html#signals
QScintilla source code, below you can see what the private slot we've disconnected by using disconnect would look like:
qsciscintilla.h
class QSCINTILLA_EXPORT QsciScintilla : public QsciScintillaBase
{
Q_OBJECT
public:
...
private slots:
void handleCharAdded(int charadded);
...
private:
void autoIndentation(char ch, long pos);
qsciscintilla.cpp
connect(this,SIGNAL(SCN_CHARADDED(int)),
SLOT(handleCharAdded(int)));
...
// Handle the addition of a character.
void QsciScintilla::handleCharAdded(int ch)
{
// Ignore if there is a selection.
long pos = SendScintilla(SCI_GETSELECTIONSTART);
if (pos != SendScintilla(SCI_GETSELECTIONEND) || pos == 0)
return;
// If auto-completion is already active then see if this character is a
// start character. If it is then create a new list which will be a subset
// of the current one. The case where it isn't a start character seems to
// be handled correctly elsewhere.
if (isListActive() && isStartChar(ch))
{
cancelList();
startAutoCompletion(acSource, false, use_single == AcusAlways);
return;
}
// Handle call tips.
if (call_tips_style != CallTipsNone && !lex.isNull() && strchr("(),", ch) != NULL)
callTip();
// Handle auto-indentation.
if (autoInd)
{
if (lex.isNull() || (lex->autoIndentStyle() & AiMaintain))
maintainIndentation(ch, pos);
else
autoIndentation(ch, pos);
}
// See if we might want to start auto-completion.
if (!isCallTipActive() && acSource != AcsNone)
{
if (isStartChar(ch))
startAutoCompletion(acSource, false, use_single == AcusAlways);
else if (acThresh >= 1 && isWordCharacter(ch))
startAutoCompletion(acSource, true, use_single == AcusAlways);
}
}
IMPORTANT: I've decided to post the relevant c++ bits so you'll got more background about how the indentation is achieved internally to give more clues about a possible replacement... The goal of this thread is to try to find a pure python solution though. I'd like to avoid modifying the QScintilla source code (if possible) so maintenance/upgrading will remain as simple as possible and QScintilla dep can still be seen as a black box.
It looks like you have to code your own version, the documentation mentions the most important point's about it already in the chapter Installation:
As supplied QScintilla will be built as a shared library/DLL and installed in the same directories as the Qt libraries and include files.
If you wish to build a static version of the library then pass CONFIG+=staticlib on the qmake command line.
If you want to make more significant changes to the configuration then edit the file qscintilla.pro in the Qt4Qt5 directory.
If you do make changes, specifically to the names of the installation directories or the name of the library, then you may also need to update the Qt4Qt5/features/qscintilla2.prf file.*
Further steps are explained there too.
There is no integrated way to make auto-indentation work in QScintilla (especially as it is in SublimeText). This behaviour is a language-specific and user-specific. Native Scintilla documentation includes examples of how to trigger auto-indentation. Sorry but it's written in C#. I haven't found it written in Python.
Here's a code (I know that a QScintilla is a Port to Qt, this Scintilla-oriented code should work with QScintilla too, or at the worst you can adapt it for C++):
private void Scintilla_InsertCheck(object sender, InsertCheckEventArgs e) {
if ((e.Text.EndsWith("" + Constants.vbCr) || e.Text.EndsWith("" + Constants.vbLf))) {
int startPos = Scintilla.Lines(Scintilla.LineFromPosition(Scintilla.CurrentPosition)).Position;
int endPos = e.Position;
string curLineText = Scintilla.GetTextRange(startPos, (endPos - startPos));
// Text until the caret so that the whitespace is always
// equal in every line.
Match indent = Regex.Match(curLineText, "^[ \\t]*");
e.Text = (e.Text + indent.Value);
if (Regex.IsMatch(curLineText, "{\\s*$")) {
e.Text = (e.Text + Constants.vbTab);
}
}
}
private void Scintilla_CharAdded(object sender, CharAddedEventArgs e) {
//The '}' char.
if (e.Char == 125) {
int curLine = Scintilla.LineFromPosition(Scintilla.CurrentPosition);
if (Scintilla.Lines(curLine).Text.Trim() == "}") {
//Check whether the bracket is the only thing on the line.
//For cases like "if() { }".
SetIndent(Scintilla, curLine, GetIndent(Scintilla, curLine) - 4);
}
}
}
//Codes for the handling the Indention of the lines.
//They are manually added here until they get officially
//added to the Scintilla control.
#region "CodeIndent Handlers"
const int SCI_SETLINEINDENTATION = 2126;
const int SCI_GETLINEINDENTATION = 2127;
private void SetIndent(ScintillaNET.Scintilla scin, int line, int indent) {
scin.DirectMessage(SCI_SETLINEINDENTATION, new IntPtr(line), new IntPtr(indent));
}
private int GetIndent(ScintillaNET.Scintilla scin, int line) {
return (scin.DirectMessage(SCI_GETLINEINDENTATION, new IntPtr(line), null).ToInt32);
}
#endregion
Hope this helps.

How to execute Python code generated by Blockly right in the browser?

I was following the example Blockly Code Generators and was able to generate Python codes. But when I run the Python code, I get an error. It seems the error is 'eval(code)' below, what should I do if I want to execute the Python code right inside the browser? Thanks for any help!
Blockly.JavaScript.addReservedWords('code');
var code = Blockly.JavaScript.workspaceToCode(workspace);
try {
eval(code);
} catch (e) {
alert(e);
}
here is the snapshot Unfortunately i dont have enough points to post the image here
Can you try this with a simple code , like - print('Hello World!')
According to the image , the issue could be with indentation , and indentation is very important in python, othewise it can cause syntax errors .
You should have also changed the code to -
Blockly.Python.addReservedWords('code');
var code = Blockly.JavaScript.workspaceToCode(workspace);
try {
eval(code);
} catch (e) {
alert(e);
}
Try to eval with a Python interp written is JS, like http://brython.info/.
as you using eval function of javascript you are actually saying to print the page as print() means to print the page in javascript.
The solution to this is there in the Blockly itself as to rn the code they call this function.
function() {
Blockly.JavaScript.INFINITE_LOOP_TRAP = 'checkTimeout();\n';
var timeouts = 0;
var checkTimeout = function() {
if (timeouts++ > 1000000) {
throw MSG['timeout'];
}
};
var code = Blockly.JavaScript.workspaceToCode(Code.workspace);
Blockly.JavaScript.INFINITE_LOOP_TRAP = null;
try {
eval(code);
} catch (e) {
alert(MSG['badCode'].replace('%1', e));
}
The above code is from code.js in demos/code/code.js line 553.

Autocomplete for Python in Codemirror?

I am trying to set up an autocomplete feature for Codemirror for the Python language. Unfortunately, it seems that Codemirror only includes the files necessary for Javascript key term completion.
Has anyone built Python hint file for CodeMirror similar to the JavaScript Version?
(Edit for future reference: link to similar question on CodeMirror Google Group)
I'm the original author of the Python parser for Codemirror (1 and 2). You are correct that the Python parser does not offer enough information for autocomplete. I tried to build it into the parser when Codemirror 2 came around but it proved too difficult for my JS skills at the time.
I have far more skills now but far less time. Perhaps someday I'll get back to it. Or if someone wants to take it up, I would be glad to help.
Add python-hint.js, show-hint.js, show-hint.css. Then
var editor = CodeMirror.fromTextArea(your editor instance codes here;
editor.on('inputRead', function onChange(editor, input) {
if (input.text[0] === ';' || input.text[0] === ' ' || input.text[0] === ":") {
return;
}
editor.showHint({
hint: CodeMirror.pythonHint
});
});
< script >
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
mode: {
name: "python",
version: 3,
singleLineStringErrors: false
},
lineNumbers: true,
indentUnit: 4,
extraKeys: {
"Ctrl-Space": "autocomplete"
},
matchBrackets: true
});
CodeMirror.commands.autocomplete = function (cm) {
CodeMirror.simpleHint(cm, CodeMirror.pythonHint);
}
</script>
I start the python autocomplete with a js based on pig-hint from codemirror 3.
You can get the python-hint.js from here.
to work, you need in your html:
include simple-hint,js and python-hint.js, simple-hint.css plus codemirror.js
add this script:
<script>
CodeMirror.commands.autocomplete = function(cm) {
CodeMirror.simpleHint(cm, CodeMirror.pythonHint);
}
</script>
python-hint.js is a basic js I have created today and not reviewed in depth.
You can initialize this way also, adding extraKeys parameter to CodeMirror initialization:
CodeMirror(function(elt) {
myTextArea.parentNode.replaceChild(elt, myTextArea);
}, {
mode: "python",
lineNumbers: true,
autofocus: true,
extraKeys: {"Ctrl-Space": "autocomplete"}
});

Regex to capture the codes between specific function

I have been experimenting with python re, trying to capture specific variables between specific functions. To illustrate let me give an example of file contents of a php file :-
public function executeSomething ()
{
$this->title = 'Edit something';
$this->action = 'Edit';
$this->headerTitle = 'Edit something';
return true;
}
public function executeSomethingEdit ()
{
if (strlen ($this->somethingElse) > 0)
{
$this->titleText = "Update";
$title = 'Edit something';
}
else
{
$this->titleText = "Create";
$title = 'Create something';
}
$this->title = $title;
$this->headerTitle = $title;
$this->formTitle = 'Something details'
return true;
}
What the python script needs to do now is iterate through this file in search for functions that starts with 'public function execute' and get the content within the braces i.e { }. I have already came up with python code to achieve this i.e :-
r = re.compile(r"public function execute(.*?)\(\).*?{(.*?)}", re.DOTALL)
The problem occurs when I have a validation within the function i.e if else statement such as the one in the function executeSomethingEdit. The script doesn't takes into account whatever codes below the if statements closing braces '}'. Therefore I need to further enhance the python code to include the function declaration below i.e something like this :-
r = re.compile(r"public function execute(.*?)\(\).*?{(.*?)}.*?public function", re.DOTALL)
At the moment this code is not working/producing the result that I wanted. I need to used python's re specifically because i need to further analyse the content of {(.*?)}. I'm very new to python so I hope someone could direct me in the right direction or at least tell me what I'm doing wrong. Thanks in advance.
If the input PHP has no bugs and has consistent indentation, you could check for a non-space character before the closing brace.
r = re.compile(r'public function execute(.*?)\(\).*?{(.*?)[^ ]}', re.DOTALL)

Categories

Resources