I can define a custom build command output by defining $*COMSTR in my environment:
env['CXXCOMSTR'] = compile_source_message
However, this overrides the message shown for the build command. I want to augment the message instead, e.g. by prefixing it with the target. My goal is to have a message like this:
% scons
Compiling foo.o
cc -o foo.o -c foo.c
I tried the following:
env['CXXCOMSTR'] = compile_source_message + '\n' + env['CXXCOMSTR']
However, this doesn't work because CXXCOMSTR is not in env yet, I get a KeyError: 'CXXCOMSTR'.
How can I augment/prefix the default $*COMSTR?
As far as I know, there is currently no environment variable like "$ACTIONCMD" containing the full command string for the running build step. So what you're trying to do:
env['CXXCOMSTR'] = "Compiling $TARGET:\n$ACTIONCMD"
isn't possible. It would require changing the SCons core sources, so it's not impossible in the long run. ;)
However, when creating a new Action object you can also specify a callable instead of a simple command string via the strfunction argument. Within this function you could then compile the printed string to your liking. Search the MAN page for the keyword strfunction to get an impression, and then decide for yourself whether you want to take this route or not. Please also consider subscribing to our user mailing list scons-users#scons.org for questions like this.
The problem you're having is due to the following behavior:
If the *COMSTR evaulates to a null string, then the CommandAction object which undelies the Action for this will default to using the *COM string to generate the output.
try:
print env.Dump('CXXCOMSTR')
except KeyError as e:
print env.Dump('CXXCOM')
Would output the value you're looking for. And for your specific usage:
try:
env['CXXCOMSTR'] = compile_source_message + '\n' + env['CXXCOMSTR']
except: KeyError as e:
env['CXXCOMSTR'] = compile_source_message + '\n' + env['CXXCOM']
Of course if some logic in your build were to later on alter the value of CXXCOM then that change would not affect your new setting.
If you wanted to ensure that changes to CXXCOM would propogate to your new value of CXXCOMSTR then the following should work:
if env.get('CXXCOMSTR',False):
env['CXXCOMSTR'] = compile_source_message + '\n' + env['CXXCOMSTR']
else:
env['CXXCOMSTR'] = "%s \n $CXXCOM"%compile_source_message
Note that having the $CXXCOM(*) in your new CXXCOMSTR allows SCons to substitute and fully expand the output for each target.
Related
I am trying to execute the command abs.__ doc__ inside the exec() function but for some reason it does not work.
function = input("Please enter the name of a function: ")
proper_string = str(function) + "." + "__doc__"
exec(proper_string)
Essentially, I am going through a series of exercises and one of them asks to provide a short description of the entered function using the __ doc__ attribute. I am trying with abs.__ doc__ but my command line comes empty. When I run python in the command line and type in abs.__ doc__ without anything else it works, but for some reason when I try to input it as a string into the exec() command I can't get any output. Any help would be greatly appreciated. (I have deliberately added spaces in this description concerning the attribute I am trying to use because I get bold type without any of the underscores showing.)
As a note, I do not think I have imported any libraries that could interfere, but these are the libraries that I have imported so far:
import sys
import datetime
from math import pi
My Python version is Python 3.10.4. My operating system is Windows 10.
abs.__doc__ is a string. You should use eval instead of exec to get the string.
Example:
function = input("Please enter the name of a function: ")
proper_string = str(function) + "." + "__doc__"
doc = eval(proper_string)
You can access it using globals():
def func():
"""Func"""
pass
mine = input("Please enter the name of a function: ")
print(globals()[mine].__doc__)
globals() return a dictionary that keeps track of all the module-level definitions. globals()[mine] is just trying to lookup for the name stored in mine; which is a function object if you assign mine to "func".
As for abs and int -- since these are builtins -- you can look it up directly using getattr(abs, "__doc__") or a more explicit: getattr(__builtins__, "abs").__doc__.
There are different ways to lookup for a python object corresponding to a given string; it's better not to use exec and eval unless really needed.
I am trying to download an audio dataset, I have all the audio's link stored in a csv. I read the csv and get all the links now I have to download the audio's one by one. Here's the code.
if not os.path.exists(audio_path_orig):
line = f"wget {episode_url}"
print('command:',line)
process = subprocess.Popen([(line)],shell=True)
process.wait()
for a sample, the line variable contains
wget https://stutterrockstar.files.wordpress.com/2012/08/male-episode-14-with-grant.mp3
Note that the url works and you can check for yourself, but when I try to download it using python it gives me the below error.
error: The filename, directory name, or volume label syntax is incorrect
Look at the documentation for Popen:
args should be a sequence of program arguments or else a single string or path-like object. By default, the program to execute is the first item in args if args is a sequence.
And:
Unless otherwise stated, it is recommended to pass args as a sequence.
Also:
The recommended approach to invoking subprocesses is to use the run() function for all use cases it can handle.
So use:
if not os.path.exists(audio_path_orig):
args = ["wget", f"{episode_url}"]
print('command:', " ".join(args))
result = subprocess.run(
args, capture_output=True, text=True
)
if result.returncode != 0:
print(f"wget returned error {result.returncode}")
print("Standard output:")
print(result.stdout)
print("Error output:")
print(result.stderr)
I am building a config in Jmeter where I specializing a system windows path to load CSV and write into CSV files. The path contains "" symbol.
There are some samplers with JSR223 PreProcessors and JSR223 Samplers. Language used is Groovy.
I know that I should screen symbols such this, but I am a bit lost at the moment because I do not understand why different options work sometimes and do not other times.
Initial path is "C:\user\jmeter\csv"
How I define this in jMeter JSR223:
def systemPath = "C:\\user\\jmeter\\csv\\"
Sometimes it works, but after I've changed some lines of code it won't!
Next time I've tried:
def systemPath = "C:\\\user\\\jmeter\\\csv\\\"
It worked for me for a while but after some code alterations after this line it won't work again.
I also 've read an article https://www.baeldung.com/groovy-strings and tried everything, but still I get this error every time:
javax.script.ScriptException: org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
Script343.groovy: 2: Unexpected input: '"' # line 2, column 16.
def systemPath = "C:\user\jmeter\csv\";
I want to store this system path reliably without errors and understand why I get this error.
I don't see any problems with this line:
def systemPath = "C:\\user\\jmeter\\csv\\"
this one is not good:
def systemPath = "C:\\\user\\\jmeter\\\csv\\\"
Your "work sometimes and do not other times" statement doesn't add any value unless you show jmeter.log preferably with debug level of verbosity for "working" and "not working" cases.
For the time being consider the following hints:
You can use forward slashes instead of escaping, i.e.
def systemPath = "C:/user/jmeter/csv/"
Or you can use File.separator property to get OS-specific "slash" value like:
def systemPath = "C:" + File.separator + "user" + File.separator + "jmeter" + File.separator + "csv" + File.separator
If you think that " character is a problem (it needs to be escaped as well by the way) you can declare Groovy strings using ' characters like:
def systemPath = 'C:\\user\\jmeter\\csv\\'
I have a tkinter GUI with an entry box I want to allow only numbers. Can someone explain to me what each command / line of code in validation does. I don't understand the vcmd variable and all the '%i' '%s' stuff. Thanks :)
UPDATE:
I have a different application to use this vcmd command with and dont understand it entirely. Here is my validation code:
def validate(self, action, index, value_if_allowed, prior_value, text, validation_type, trigger_type, widget_name):
if not int(action):
return True
elif text in '0123456789.-+':
try:
float(value_if_allowed)
return True
except ValueError:
return False
else:
return False
I dont get why in this code i need all of these:
action, index, value_if_allowed, prior_value, text, validation_type, trigger_type, widget_name
Why do i need all of these specific to my validation code for it to function correctly and what use are they?
The documentation you provided made sense but some of those '%s', '%i' stuff seemed unnecessary for my specific code yet it only works with all of them included like so:
vcmd = (self.master.register(self.validate), '%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W')
I also want to know what self.master.register does please, i still cant figure that one out.
If you do not need any of the special arguments, you don't need to call register. For example, the following code will correctly call do_validation without any arguments:
import tkinter as tk
def do_validation():
value = entry.get()
if value == "" or value.isnumeric():
return True
return False
root = tk.Tk()
entry = tk.Entry(root, validate='key', validatecommand=do_validation)
entry.pack(fill="x", padx=20, pady=20)
root.mainloop()
However, in the above case the validation will always be one character behind. This is because validation happens before the character is inserted into the entry widget (ie: the first time it is called, entry.get() will return an empty string). The whole point of validation is to prevent illegal characters, so it makes sense to call the command before the character is inserted rather than after.
This is why the special arguments are useful -- they provide sufficient context in order to decide whether the character or characters are legal before they are inserted into the widget.
How register is useful
Tkinter is a wrapper around a Tcl interpreter, because tk (the core technology behind tkinter) is implemented in Tcl. Tcl is a programming language just like python.
In a Tcl program, you would use the validation features like this:
proc do_validation(new_value) {
return $new_value == "" || [string is integer $new_value]
}
entry .entry -validate key --validatecommand [list do_validation %P]
When Tcl detects a change, it performs substitution on the arguments, and then calls the defined procedure with the substituted arguments. For example, if you type "A", %P is converted to "A" and the function is called with "A" as the only argument.
In the case of Tkinter, there is no direct corollary for defining the function with arguments to be substituted at runtime.
Unfortunately, the validation feature wasn't implemented very well in the tkinter wrapper, so to properly use the validation we have to use a small workaround in order to get these special arguments passed to our function.
What register does is to create a new Tcl command that calls your python command. It also creates a new python command that is a reference to this new Tcl command. You can use this reference exactly like any other python command.
A simple example
In the simplest case, all you need is what the string would look like if the edit was to be allowed. You can then decide whether the edit is something that will result in valid input, or if it will result in invalid input. If the edit won't result in valid input, you can reject the edit before it actually happens.
The special argument that represents the value if the edit is allowed is %P 1. We can modify the function we are registering to accept this argument, and we can add this argument when we do the registering:
def do_validation(new_value):
return new_value == "" or new_value.isnumeric()
...
vcmd = (root.register(do_validation), '%P')
entry = tk.Entry(..., validatecommand=vcmd)
With that, when the underlying Tcl code detects a change it will call the new Tcl command which was created, passing in one argument corresponding to the special %P substitution.
1All of the mechanics of the validation are described thoroughly in the tcl documentation here: http://tcl.tk/man/tcl8.5/TkCmd/entry.htm#M7
I have this test code:
def p = [:]
p.foo = [:]
p.foo.bar = 120
p.foo.bar - 3
(p.foo.bar) + 3
why on the last statement i get a compilation error : "unable to resolve class p.foo.bar "?
Thanks for the help
Groovy version 1.8.1
OK, I think I figured it out. I ran the AST browser against your sample script (using the GroovyConsole). It would only show an output at the Conversion phase. At this phase you can see how the script is converted. The key is that the last line is converted into this:
...
((1) as p.foo.bar)
This means that, apparently, it's trying to cast or convert the 1 into a class named p.foo.bar.
You can dig a little deeper and see that the parser is parsing the statement like this:
(p.foo.bar)(+1)
Which is the same as
(p.foo.bar)1
Therefore, the parser/compiler is seeing the + as a unary + operator. And that is why you are getting the error. (The way around it it to remove the parentheses, or swap the order of the arguments!)