I am using Behave to automate the testing of a config file, as part of this test I need to populate various fields in the config file with invalid and blank fields. Where I am entering values I can do this using a Scenario Outline entering the values in the Examples. However when I try entering a blank field using this method Behave does not like the fact there is no value.
Is there an easy way to pass a blank value from the Examples file, or will I need to test these conditions using a separate behave test
feature
Scenario Outline:Misconfigured Identity Listener
Given an already stopped Identity Listener
And parameter <parameter> is configured to value <config_value>
When the Identity Listener is started
Then the identity listener process is not present on the system
And the log contains a <message> showing that the parameter is not configured
Examples: Protocols
|parameter |message |config_value|
|cache_ip_address | cache_ip_address | |
|cache_ip_address | cache_ip_address | 123.123.12 |
the step where I define the config value
#given('parameter {parameter} is configured to value {config_value}')
def step_impl(context, parameter, config_value):
context.parameter = parameter
context.config_value = config_value
context.identity_listener.update_config(parameter, config_value)
changing the config file using sed -i (I am interacting with a linux box in this test)
def update_config(self, param, config_value):
command = 'sudo sh -c "sed -i'
command = command + " '/" + param + "/c\\" + param + "= "+ config_value + " \\' {0}\""
command = command.format(self.config_file)
self.il_ssh.runcmd(command)
Thanks to answer from #Verv i got this working solution below
passed an empty value in for fields where I don't want a value passed
|parameter |message |config_value|
|cache_ip_address | cache_ip_address | empty |
Added an if else statement into my update config step
def update_config(self, param, config_value):
if config_value == "empty":
il_config = ""
else:
il_config = config_value
command = 'sudo sh -c "sed -i'
command = command + " '/" + param + "/c\\" + param + "= " + il_config + " \\' {0}\""
command = command.format(self.config_file)
self.il_ssh.runcmd(command)
You could put something like empty in the field, and tweak your method so that whenever the field's value is empty, you treat it as an actual empty string (i.e. "")
Related
How would I call a global variable from my python script inside of the tell application? Here's a sample of where that might go. Say I wanted to change all "front window" from outside of the applescript from a global python variable. How might that happen?
import subprocess
def get_window_title():
cmd = """
tell application "System Events"
set frontApp to name of first application process whose frontmost is true
end tell
tell application frontApp
if the (count of windows) is not 0 then
set window_name to name of front window
end if
end tell
return window_name
"""
result = subprocess.run(['osascript', '-e', cmd], capture_output=True)
return result.stdout
print(get_window_title())
Here's a way better example:
The phone number is defined on line 7 with input on line 74. It's called on line 91 from inside the applescript. I'd like to do the same for the message from inside the applescript on line 98, like the phone number was able to, and not from line 113 (msg). I'd like to define msg from outside of the applescript and call it just like the phone number.
import subprocess, sys
from os import system, name
from time import sleep
msg = ""
Phone_num = ""
repeat = ""
def Ascii():
clear()
print("+++++++++++++++++++++++++++++++++++++++.")
print("++++++++++++++77 77I++++++++++++++")
print("++++++++++77 77+++++++++++")
print("========77 77=========")
print("=======7 7========")
print("======7 7=======")
print("=====7 7======")
print("===== ======")
print("===== ======")
print("===== ======")
print(
"=====7 7====== _ __ __ "
)
print(
"~~~~~~7 7~~~~~~~ (_) \/ | "
)
print(
"~~~~~~~7 7~~~~~~~~ _| \ / | ___ ___ ___ __ _ __ _ ___ "
)
print(
"~~~~~~~~77 77~~~~~~~~~ | | |\/| |/ _ \/ __/ __|/ _` |/ _` |/ _ \ "
)
print(
"~~~~~~~~~~77 77~~~~~~~~~~~ | | | | | __/\__ \__ \ (_| | (_| | __/"
)
print(
"~~~~~~~~~~~~ 77 777I~~~~~~~~~~~~~~ |_|_| |_|\___||___/___/\__,_|\__, |\___|"
)
print(
"~~~~~~~~~~~ 7I~~~~~~~~~~~~~~~~~~~~~~~~~~ __/ | "
)
print(
"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~. |___/ "
)
print("\nWith Python!")
sleep(3)
def intro():
clear()
print("Welcome to iMessage for Python.\n")
print(
"This Adapts From The AppleScript and Uses Elements From Python to Send Automated Messages to Others.\n"
)
print('This Uses US Based Numbers "(+1)" Only.\n')
print(
"🚨[WARNING] By Agreeing to Use this Software, Any Liability Due to Misuse Will NOT be Placed On the Author. 🚨"
)
sleep(5)
def clear():
_ = system("clear")
def questions():
clear()
global msg, Phone_num, repeat
print('NO Dashes "-", Spaces "_", or parentheses"()" or the script WILL Fail.')
print("Input Ex:XXXXXXXXX\n")
Phone_num = str(input("Enter Here:"))
clear()
print("What is Your Message?\n")
msg = input("Enter Here:")
clear()
print("How Many Times do You Want to Send this Message?\n")
repeat = input("Enter Here:")
clear()
def apple():
applescript = (
"""
tell application "Messages"
set targetBuddy to "+1 """
+ Phone_num
+ """"
set targetService to id of 1st service whose service type = iMessage
set i to 1
set p to "Sent"
repeat {0}
set textMessage to "{1}"
set theBuddy to buddy targetBuddy of service id targetService
send textMessage to theBuddy
delay 1
log ("Repeated " & i &" Time(s).")
set i to i + 1
end repeat
end tell
""".format(
repeat, msg
)
)
args = [
item
for x in [("-e", l.strip()) for l in applescript.split("\n") if l.strip() != ""]
for item in x
]
proc = subprocess.Popen(["osascript"] + args, stdout=subprocess.PIPE)
progname = proc.stdout.read().strip()
You are using two different ways to programmatically build the script string. One way uses concatenation, the other uses a string function. Using one or the other would probably be less confusing.
The format function uses passed arguments to replace placeholders in the string. With index formatting, the arguments can be used in any order and multiple times (or not at all), so this method gives you a little more flexibility when building this kind of script. For example:
msg = "This is a test."
Phone_num = "8761234"
repeat = "5"
applescript = (
"""
tell application "Messages"
set targetBuddy to "+1 {0}"
set targetService to id of 1st service whose service type = iMessage
set i to 1
set p to "Sent"
repeat {1}
set textMessage to "{2}"
set theBuddy to buddy targetBuddy of service id targetService
send textMessage to theBuddy
delay 1
log ("Repeated " & i &" Time(s).")
set i to i + 1
end repeat
end tell
""".format(Phone_num, repeat, msg)) # replace placeholders with variable values
print(applescript)
If you want to pass arguments into AppleScript, here is the correct way to do it:
#!/usr/bin/env python3
import subprocess
scpt = """
on run {arg1, arg2}
return arg1 + arg2
end run
"""
arg1 = 37
arg2 = 5
proc = subprocess.Popen(['osascript', '-', str(arg1), str(arg2)],
stdin=subprocess.PIPE, stdout=subprocess.PIPE, encoding='utf8')
out, err = proc.communicate(scpt)
print(out) # 42
Since you’re on Python, you also have the options of py-applescript, which is supported, or appscript, which is not. If you need to pass complex arguments to AppleScript, the py-applescript library automatically converts between common AS and Python types. Appscript avoids AppleScript entirely, but you’re on your own with that.
I need to replace some string by others. I'm using function pathlib to do that it's working fine but I have a problem when there is two same string in my file and I need to change just one
My file (wireless.temp) is like this example
config 'conf'
option disabled '0'
option hidden '1'
option ssid 'confSSID'
option encryption 'psk2'
option key 'qwerty'
config 'client'
option disabled '0'
option hidden '0'
option ssid 'clientSSID'
option encryption 'psk2'
option key 'qwerty'
For example, I need to change string like 'disabled', 'hidden', 'ssid', 'key', in config station and/or config device. Right now I'm using this code
f1=open('wireless.temp', 'r').read()
f2=open('wireless.temp','w')
#checkbox from QT interface
if self.chkWifiEnable.isChecked():
newWifiEnable = "0"
else:
newWifiEnable = "1"
start = f1.find("config 'client'")
print start
end = f1.find("config", start + 1)
print end
if end < 0:
end = len(f1)
station = f1[start:end]
print station
print f1.find("disabled")
print f1.find("'")
actualValue = f1[(station.find("disabled")+10):station.find("'")]
print actualValue
station = station.replace("disabled '" + actualValue, "disabled '" + newWifiEnable)
print station
m = f1[:start] + station + f1[end:]
f2.write(m)
I have a problem with this code, first when I execute my output is
config 'conf'
option device 'radio0'
option ifname 'conf'
option network 'conf'
option mode 'ap'
option disabled '0'
option hidden '1'
option isolate '1'
option ssid 'Conf-2640'
option encryption 'psk2'
option key '12345678'
config 'client'
option device 'radio0'
option ifname 'ra0'
option network 'lan'
option mode 'ap'
option disabled '00' <---- problem
option hidden '0'
option ssid 'FW-2640'
option encryption 'psk2'
option key '12345678'
option disabled line in config 'client' section, my program add another 0 all time also I want to lighten my code because I need to do that for many others string.
Does anyone have an idea?
Thanks
The Path and pathlib2 is a red-herring. You are using that to find and read a file into a string. The issue is replacing text in a narrow section of the whole text. Specifically, between 'config device' and the next 'config ...' item
You can use .find() to find the beginning of the correct config section, and again to find the start of the next config section. Ensure you treat -1, for not found, as the end of the section. The text within that range can be modified, and then combine the resulting modification with the unmodified parts that came before and after it.
wirelessF = """
config device
.....
option key 'qwerty'
.....
config station
.....
option key 'qwerty'
.....
config otherthing
.....
option key 'qwerty'
.....
"""
actualWifiPass = 'qwerty'
newWifiPass = 's3cr3t'
start = wirelessF.find("config station")
end = wirelessF.find("config ", start+1)
if end < 0:
end = len(wirelessF)
station = wirelessF[start:end]
station = station.replace("key '"+actualWifiPass, "key '"+newWifiPass)
wirelessF = wirelessF[:start] + station + wirelessF[end:]
print(wirelessF)
Outputs:
config device
.....
option key 'qwerty'
.....
config station
.....
option key 's3cr3t'
.....
config otherthing
.....
option key 'qwerty'
.....
how to parametrize a function for pytest such that parameter are taken from a text file and function name changes on each iteration for pytest-html report
text file format : Function_name | assert_value | Query for assertion from postgresql.
requirement : to create a pytest based framework
so far with my logic(it doesn't work):
with open("F_Query.txt","r") as ins1:
for F_Query in ins1:
#Name of function to be executed to be extracted from the file differentiated with delimeter " | "(leading and trailing space required)
F_name=F_Query.split(" | ")[0]
assert_val=F_Query.split(" | ")[1]
Query=F_Query.split(" | ")[2]
Loc_file=(Query.split(" ")[-5:])[0]
def f(text):
def r(y):
return y
r.__name__ = text
return r
c1.execute(Query)
assert(c1.rowcount() == assert_val), "Please check output file for records"
p = f(F_name)
can anyone explain how to get the function name changed with every iteration while parameters are being passed in pytest fun
latest changes (still doesn't work):
with open("F_Query.txt","r") as ins1:
for F_Query in ins1:
#Name of function to be executed to be extracted from the file differentiated with delimeter " | "(leading and trailing space required)
#F_name=F_Query.split(" | ")[0]
assert_val=int(F_Query.split(" | ")[1])
Query=F_Query.split(" | ")[2]
Query=Query.strip("\n")
#Loc_file=(Query.split(" ")[-5:])[0]
dictionary1[Query]=assert_val
#pytest.mark.parametrize('argumentname',dictionary1)
def test_values(argumentname):
c1.execute(dictionary1.keys(argumentname))
assert(c1.rowcount==dictionary1.values(argumentname))
I call the python code from a Powershell script in order to loop over some arguments. Calling the python script from a Powershell is straight forward and works without a hitch:
PS C:\Windows\system32> C:\Users\Administrator\AppData\Local\Programs\Python\Python35-32\python.exe C:\Users\Administrator\AppData\Local\Programs\youtube-upload-master\bin\youtube-upload C:\Users\Administrator\Documents\timelapse\videos\timelapse_10.0.0.51-2016-06-21.mp4 --client-secrets=C:\Users\Administrator\Documents\timelapse\credentials\.yt-ul-ioa-secr.json --credentials-file=C:\Users\Administrator\Documents\timelapse\credentials\.yt-ul-ioa-cred.json --title="Timelapse 21.06.2016" --playlist "Timelapses June 2016"
Then within a script I am changing the parameters inserting variables into the argument strings, and finally calling the whole thing with Invoke-Command:
# yt-ul.ps1
param(
#[switch]$all_cams = $false,
[int]$days = -1,
[string]$cam = "ioa"
)
$cam_ip_hash = #{
"ioa" = "10.0.0.51";
"pam" = "10.0.0.52";
"biz" = "10.0.0.56";
"prz" = "10.160.58.25";
"igu" = "10.160.38.35"}
$cam_ip = $cam_ip_hash[$cam]
$date = (Get-Date).AddDays($days).ToString("yyyy-MM-dd")
$py = "C:\Users\Administrator\AppData\Local\Programs\Python\Python35-32\python.exe"
$yt_ul = "C:\Users\Administrator\AppData\Local\Programs\youtube-upload-master\bin\youtube-upload"
$title_date = (Get-Date).AddDays($days).ToString("dd.MM.yyyy")
$us = New-Object System.Globalization.CultureInfo("en-US")
$playlist_date = (Get-Date).AddDays($days).ToString("Y", $us)
$vid = "C:\Users\Administrator\Documents\timelapse\videos\timelapse_$cam_ip-$date.mp4"
$secr = "--client-secrets=C:\Users\Administrator\Documents\timelapse\credentials\.yt-ul-igu-secr.json"
$cred = "--credentials-file=C:\Users\Administrator\Documents\timelapse\credentials\.yt-ul-igu-cred.json"
$title = "--title=`"Timelapse $title_date`""
$playlist_date = "--playlist `"Timelapses $playlist_date`""
$arg_list = "$yt_ul $vid $secr $cred $title $playlist_date"
Invoke-Command "$py $arg_list"
But actually calling the script fails as follows:
PS C:\Users\Administrator\Documents\scripts> .\yt-ul.ps1
Invoke-Command : Parameter set cannot be resolved using the specified named parameters.
At C:\Users\Administrator\Documents\scripts\yt-ul.ps1:34 char:1
+ Invoke-Command "$py $arg_list"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Invoke-Command], ParameterBindingException
+ FullyQualifiedErrorId : AmbiguousParameterSet,Microsoft.PowerShell.Commands.InvokeCommandCommand
I assume I am doing something really stupid with the single and double quotes, but I am not sure.
Thanks to JosefZ this works:
& $py $yt_ul $vid $secr $cred --title "Timelapse $title_date" --playlist "Timelapses $playlist_date"
I have the following vimscript .vim/ftplugin dir:
" change to header file from c file or vice versa
function! CppAlter()
python << endpy
import vim
import os
bufferNames = [os.path.basename(b.name) for b in vim.buffers]
currentBufName = vim.eval("expand('%:p:t')")
currentBufStem, currentBufExt = os.path.splitext(currentBufName)
if currentBufExt == ".cpp" or currentBufExt == ".c" or currentBufExt == ".cc":
altBufName1 = currentBufStem + ".h"
altBufName2 = currentBufStem + ".hpp"
if altBufName1 in bufferNames:
vim.command("b " + altBufName1)
elif altBufName2 in bufferNames:
vim.command("b " + altBufName2)
else:
raise ValueError("No header file corresponding to this c file")
elif currentBufExt == ".h" or currentBufExt == ".hpp":
altBufName1 = currentBufStem + ".cpp"
altBufName2 = currentBufStem + ".c"
altBufName3 = currentBufStem + ".cc"
if altBufName1 in bufferNames:
vim.command("b " + altBufName1)
elif altBufName2 in bufferNames:
vim.command("b " + altBufName2)
elif altBufName3 in bufferNames:
vim.command("b " + altBufName3)
else:
raise ValueError("No c file corresponding to this header file")
else:
raise ValueError("This is not a c type file")
endpy
endfunction
nnoremap <leader>vc :call CppAlter()<cr>
inoremap <leader>vc <esc>:call CppAlter()<cr>
When I open vim I get an error:
" vim.error: Vim(function):E127: Cannot redefine function CppAlter: It is in use
But if I save it in /tmp and explicitly :so /tmp/x.vim, there is no error msg.
Wondering what is wrong here.
Inside your function, you're loading another buffer (e.g. vim.command("b " + altBufName1)). When that buffer has the same filetype, the current ftplugin script is sourced again as part of the filetype plugin handling, but the original function hasn't returned yet, so you get the E127.
Solution
I recommend putting the function itself into an autoload script, e.g. in ~/.vim/autoload/ft/cppalter.vim:
function! ft#cppalter#CppAlter()
...
Your ftplugin script becomes much smaller and efficient, as the function is only sourced once:
nnoremap <leader>vc :call ft#cppalter#CppAlter()<cr>
...
(You should probably use :nnoremap <buffer> here to limit the mapping's scope.)
Alternative
If you don't want to break this up, move the function definition(s) to the bottom and add a guard, like:
nnoremap <leader>vc :...
if exists('*CppAlter')
finish
endif
function! CppAlter()
...
I encountered an interesting case of E127, which pretty much sums up why it would occur in almost any situation. Let me explain.
First, let's look at what the docs say.
E127 E122
When a function by this name already exists and [!] is
not used an error message is given. There is one
exception: When sourcing a script again, a function
that was previously defined in that script will be
silently replaced.
When [!] is used, an existing function is silently
replaced. **Unless it is currently being executed, that
is an error.**
For the next part notice what the last line has to say.
Let's understand this by an example. Below is a function that guesses and sources the current script based on what filetype it has. Notice how the exec command will initiate an endless recursive sourcing of the current file on calling this function.
function! s:SourceScriptImplicit()
if !&readonly
w
endif
let l:bin=system("which " . &filetype)[:-2]
let l:sourcecommand=
\ #{
\ vim: "source %",
\ sh: "!source %",
\ javascript: "!node %",
\ python: "!python3 %"
\ }
exec l:sourcecommand[split(l:bin, "/")[-1]]
endfunction
To fix this, simply remove the recursive part out of the function.
function! s:SourceScriptImplicit()
if !&readonly
w
endif
let l:bin=system("which " . &filetype)[:-2]
let l:sourcecommand=
\ #{
\ vim: "source %",
\ sh: "!source %",
\ javascript: "!node %",
\ python: "!python3 %"
\ }
return l:sourcecommand[split(l:bin, "/")[-1]]
endfunction
nn <leader>so :exec <SID>SourceScriptImplicit()<cr>
Now it works perfectly!
I think you should notice that | can be useful for execute command in the bottom command line,such as :source expand("%") | source ./awesome.vim
Here is my .init.vim(or .vimrc) snippet whose func is sourcing all .vim files in /home/zarkli/.config/nvim/myInitCustom/ directory:
function SourceVimScripts()
let l:command = ""
let l:files = split(globpath('/home/zarkli/.config/nvim/myInitCustom/','*.vim'),'\n') " use absolute path to avoid problems when opening an non-nvim_init file
for l:file in l:files
let l:command .= "source ".l:file." |"
endfor
" the end of the l:command should be '|',but that doesn't matter
return l:command
endfunction
exec SourceVimScripts()
It can perfectly deals with your problem.