How to properly run tests on github using pytest? - python

I wrote a program in haskell and would like to write tests for it using pytest. I would also like to set up a workflow on github. So here is the code for the tests:
def path_to_bin():
stream = os.popen('cabal exec which haskell-lab4-exe')
bin_p = stream.read()
bin_p = bin_p.replace('\n', '')
return bin_p
def test_1():
os.popen(path_to_bin() +' --use ./test_files/left.use --dox ./test_files/left.dox')
time.sleep(3)
file1 = open("./python/test/expected_results/lu_ld_diff.md", "r")
file2 = open("diff.md", "r")
expected = file1.read()
res = file2.read()
assert(res == expected)
def test_2():
os.popen(path_to_bin() +' --use ./test_files/right.use --dox ./test_files/left.dox')
time.sleep(3)
file1 = open("./python/test/expected_results/ru_ld_diff.md", "r")
file2 = open("diff.md", "r")
expected = file1.read()
res = file2.read()
assert(res == expected)
So, my program should compare the 2 files and output the result in diff.md
Locally the tests work fine, but on github the first test always gets bogged down by this:
E FileNotFoundError: [Errno 2] No such file or directory: 'diff.md'
python/test/test.py:16: FileNotFoundError
24
----------------------------- Captured stderr call -----------------------------
25
/bin/sh: 1: Resolving: not found
I tried swapping tests, but the problem is the same, the first test always crashes, the others always pass. I tried to increase the delay after the execution of the command to generate, but it does not help.
So, I would like to know why this is possible?

Related

Execute a function on first startup only

How to - let a function run only on the first startup?
I have tried creating a value-adding mechanism (adding 1 to a variable after startup) but I failed.
result = _winreg.QueryValueEx(key, "MachineGuid")
ID = str(result)
licence_path = 'C:\\Program Files\\Common Files\\System\\read.txt'
oon = 0
def first_time_open_only():
file = open(licence_path, 'w')
file.write(ID[2:38])
file.close()
onn = 1 + onn
first_time_open_only()
with open(licence_path) as f:
contents = f.read()
if contents == str:
pass
else:
root.destroy()
There is a way that can solve this problem. On each run of the code, in order to understand that a function is run before or not, is to save the flag to a file such as pickle or a database. The code below shows a simple example such that the function only runs one time. This kind of problems can be solved by saving the file in order to let the code know the previous state.
In this code, if it is the first run of program, the Flag.pkl would not exists, so the flag will be equal to zero and the function will run, but in second execution the flag will have 1 as its value and the function would not execute.
import pickle
import os.path
def runOnce():
print("first time of execution")
flag = 1
with open('./Flag.pkl', 'wb') as f:
pickle.dump(flag, f)
if os.path.isfile('./Flag.pkl'):
with open('./Flag.pkl','rb') as f:
flag = pickle.load(f)
else:
flag = 0
if flag ==0:
runOnce()
else:
print("This function has been executed before!")

How to watch the file change and compare the two files in python?

I have a requirement where I need to do the following:
Watch a file for any changes - done
Compare the file with the changed file - pending
That means, say I have a text file with the content "hello world" as below:
hello.txt
hello world
Then I will add another line to the same file as below
hello world
some other line
up on the save, it should create a new file without actually writing to the same file so, I should end up with two files instead of one:
hello.txt - original file
hello world
hello_modified.txt - modified (appended) file
hello world
some other
How can I do this with python ?
I have already used watchdog for listening to file modification, I have even implemented the function to display the diff between the two files too. But I have no idea how to write the logic for the file replication. i.e. how can I create and write to another file up on saving the hello.txt without really saving the hello.txt ?
I think you can do this by using a while loop and time module. Note that, reading a file each time a while statements loops over itself, is probitively expensive for your computer processor. So, in this answer, I decided to check the files every 3 seconds.
from time import time
startTime = time()
diffTime = 3
with open("hello.txt") as f:
checkFile = f.read()
while True:
now = time()
if now > startTime+diffTime:
startTime = now
with open("hello.txt") as f:
myString = f.read()
if checkFile != myString:
with open("hello_modified.txt", "w") as f:
f.write(myString)
with open("hello.txt", "w") as f:
f.write(checkFile)
Here's an implementation using a coroutine file_copier. See usage and test for usage.
import itertools
from pathlib import Path
import shutil
def copy(src: Path, dst: Path):
print(f"Copying {src} to {dst}")
shutil.copyfile(src, dst)
def file_copier(watched_path: str|Path):
if isinstance(watched_path, str):
watched_path = Path(watched_path)
shutil.copyfile(watched_path, watched_path.with_stem(f'{watched_path.stem}_0'))
for counter in itertools.count():
yield
copy(watched_path, watched_path.with_stem(f'{watched_path.stem}_{counter+1}'))
copy(watched_path.with_stem(f'{watched_path.stem}_{counter}'), watched_path)
path = Path("hello.txt")
def usage():
fc = file_copier(path)
next(fc) # start/init
# When 'hello.txt' has been modified:
next(fc) # copies 'hello.txt' to new history file and resets 'hello.txt' to previous history file
# TEST
def create():
"""Creates empty 'hello.txt'"""
with open(path, "w") as f:
pass
def append(line: str):
"""Simulates modification of 'hello.txt'"""
with open("hello.txt", "a") as f:
print(line, file=f)
def test():
fc = file_copier(path)
create()
append("hello world")
next(fc)
append("edit 1")
next(fc)
append("edit 2")
next(fc)
append("edit 3")
next(fc)
if __name__ == '__main__':
test()

Python Iterate through files, Search for certain string, if found copy rest of the lines and consolidate to a combined file

I have a folder contains 500 text files.
Python Iterate through files Search for certain string if found copy and consolidate to a combined file as "Output.txt".
The string we are looking for in each of the file in the directory
import os
searchquery = 'No' #string we are looking for in each of the file in the directory
def my_function(fname):
Output=[]
with fname as f1:
with Output as f2:
Lines = f1.readlines()
try:
i = Lines.index(searchquery)
for iline in range(i+1, i+18): # we need to copy rest of the 18 or less line after 'No' is found
f2.write(Lines[iline])
except:
print(" ")
return Output
for filename in os.listdir('C:\\Users\\XXX\\Desktop\\Tox\\tcm2'):
M1=open(filename)
M2=my_function(M1)
opened_file = open(Output.txt, 'a')
opened_file.write("%r\n" % M1)
opened_file.close()
I am seeing the following error
with Output as f2:
AttributeError: __enter__
you cannot do with Output as f2 , because Output is a list and it doesn't support that, and gives you AttributeError: __enter__ , another problem is the line where you did f2.write() again you cannot write to a list, use append() instead.
Here is the full working code, i tested it :
import os
searchquery = 'No'
path = 'C:\\Users\\XXX\\Desktop\\Tox\\tcm2\\'
def my_function(fname):
Output=[]
Lines = fname.readlines()
found = False
for line in Lines :
if (found == True):
Output.append(line)
if line.startswith(searchquery):
found = True
return Output
opened_file = open('Output.txt', 'a')
for filename in os.listdir(path):
M1=open(path+filename)
result=my_function(M1)
for e in result:
opened_file.write(e)
M1.close()
opened_file.close()
Why not simply using a cmd line, go to the directory and run:
grep no -A18 * | egrep -v "no|--" > output.txt
In case you do not have egrep:
grep no -A18 * | grep -v no | grep -v "--" > output.txt

File reading from one to another file and printing in Python

The following code is working as expected. As I have taken InputStr.txt in that I have filled some string of statements and generating the Output.txt by adding those InputStr.txt statements whether PASS or FAIL.
Python Code:
str = "FAIL";
flag = False;
resultList = [];
#Here InputStr.txt is the file where all your output format strings are stored.
Stringlines = [line.strip() for line in open('InputStr.txt')]
out_file = open("Output.txt", "w")
for i in range (1,3):
fileName1 = "./largeFile%d.txt"%i
print fileName1;
fileName2 = "./largeFile_%d.txt"%i
with open(fileName1, 'r') as inF1:
for line in inF1:
if 'VERSION' in line:
print "VERSION FOUND";
flag = True;
if flag:
with open(fileName2, 'r') as inF2:
for line in inF2:
if 'ID' in line:
print "ID FOUND";
str = "PASS";
resultList.append(str);
out_file.write("\n %s - %s" %(Stringlines[i-1],resultList[i-1]))
out_file.close()
Output I got:
Output in Output.txt is:*
TEST CASE-1 PASS
TEST CASE-2 PASS
TEST CASE-3 PASS
I am trying to print the TC1 should PASS when 4TCs should PASS as these 4TCs i took from another InputStr2.txt.
Example:
InputStr.txt contains following statements:
Req 1. How How are you
Req 2. I am Fine and Thanks.
Req 3. How are you doing
InputStr2.txt contains:
TC1: ABCDEFGHIJ
TC2: KLMNOPQRST
TC3: UVWXYZABCD
TC4: EFGHIJKLMN
So expected output is:
Req 1. How How are you - PASS
Req 2. I am Fine and Thanks. - PASS
Req 3. How are you doing - PASS
First All the Test cases of TC1 to TC4 should PASS(In InputStr2.txt), then only my Req 1 will PASS. Means, In Output.txt i am printing all the requirements are PASS or FAIL.
Logic/suggestions please?

How to replace command line arguments sys.argv by stdin stdout?

I realize, that my question is a very simple one, but I can't find any explicit example of the implementation of the stdin stdout into a Python script.
I have a script, working perfectly well with command line arguments:
newlist = []
def f1()
....
def f2(input_file):
vol_id = sys.argv[3]
for line in input_file:
if ... :
line = line.replace('abc','def')
line = line.replace('id', 'id'+vol_id)
....
newlist.append(line)
return newlist
def main():
if len(sys.argv) < 4:
print 'usage: ./myscript.py [file_in... file_out... volume_id]'
sys.exit(1)
else:
filename = sys.argv[1]
filename_out = sys.argv[2]
tree = etree.parse(filename)
extract(tree)
input_file = open(filename, 'rU')
change_class(input_file)
file_new = open(filename_out, 'w')
for x in newlist:
if '\n' in x:
x = x.replace('\n', '')
print>>file_new, x
Now I should somehow use stdin and stdout instead of my arguments in order to make my script usable within pipelines, like for example using multiple files as input:
cat input1 input1 input3 | myscript.py
Or to process its output with some UNIX tools before printing it to a file.
I tried to replace arguments in my script by sys.stdin:
filename = sys.stdin
filename_out = sys.stdout
Then I ran my script like this:
./myscript.py < inputfile > outputfile
It resulted in an empty outputfile, but didn't yeld any error messages at all.
Could you please help me with this replacement?
P.S. Then I modified my main() like this:
filename = sys.argv[1]
filename_out = sys.argv[2]
if filename == '-':
filename = sys.stdin
else:
input_file = open(filename, 'rU')
if filename_out == '-':
filename_out = sys.stdout
file_new = filename_out
else:
file_new = open(filename_out, 'w')
tree = etree.parse(filename)
extract(tree)
input_file = filename
change_class(input_file)
for x in newlist:
if '\n' in x:
x = x.replace('\n', '')
print>>file_new, x
I tried to run it from the command line like this:
./myscript.py - - volumeid < filein > fileout
But I still got an empty output file :(
The common placeholder for stdin or stdout is -:
./myscript.py - - volumeid
and:
if filename == '-':
input_file = sys.stdin
else:
input_file = open(filename, 'rU')
etc.
In addition, you could default filename and filename_out to - when there are fewer than 3 command line arguments. You should consider using a dedicated command-line argument parser such as argparse, which can handle these cases for you, including defaulting to stdin and stdout, and using -.
As a side note, I'd not use print to write to a file; I'd just use:
file_new.write(x)
which removes the need to strip off the newlines as well.
You appear to read from the input file twice; once to parse the XML tree, once again to call change_class() with the open file object. What are you trying to do there? You'll have problems replicating that with sys.stdin as you cannot re-read the data from a stream the way you can from a file on disk.
You'd have to read all the data into memory first, then parse the XML from it, then read it it again for change_class(). It'd be better if you used the parsed XML tree for this instead, if possible (e.g. read the file only once, then use the parsed structure from there on out).

Categories

Resources