Selenium Webdriver using Ruby: write text to file - ruby

I would like to write text to a file multiple times (appending).
Currently I am using: In this scenario I captured the system time in endtime and starttime.
File.open("c:\\temp\\myfile.txt", "w").write("My first input: #{endtime-starttime} seconds \n")
I would like to continue this multiple times in various places in my script but it does not seem to be working correctly. The text file seems to be writing over itself. Is there a way in a script to write text in different rows?
Thanks,
Scott
Here's a better example
#------------------------------------------------------------------------------------------------ ---------------------
#Log into System
#---------------------------------------------------------------------------------------------------------------------
starttime=Time.new
LoginButton = driver.find_element(:xpath, "/html/body/div[3]/div/div[2]/ul/li[3]/a")
LoginButton.click
option = driver.find_element(:xpath, "/html/body/div/div[1]/div/div[3]/div[1]/form/div[3]/ul/li[1]/input")
option.send_keys"blah"
option = driver.find_element(:id, "password")
option.send_keys"blah"
option = driver.find_element(:xpath, "/html/body/div/div[1]/div/div[3]/div[1]/form/div[3]/ul/li[3]/input")
option.click
endtime=Time.new
puts"Login: #{endtime-starttime} seconds"
File.open("c:\\temp\\myfile.txt", "w").write("Login: #{endtime-starttime} seconds \n")
puts"Login Done"
#---------------------------------------------------------------------------------------------------------------------
#Performance Test Course
#---------------------------------------------------------------------------------------------------------------------
starttime=Time.new
driver.switch_to.frame "contentFrame" #Sets focus on the "UR Courses Online Module"
option = driver.find_element(:link_text, "Performance Test Course")
option.click
endtime=Time.new
puts"Performance Test Course Link: #{endtime-starttime} seconds"
File.open("c:\\temp\\myfile.txt", "w").write("Performance Test Course Link: #{endtime-starttime} seconds \n")
puts"Performance Test Course Done"

You probably want to store the open file object in a variable so that when you write a new line to your file it is written to the end. Your previous code would open the given file write the line at position 0 in the file then close the file.
file = File.open("text.txt", "w")
file.write "hello world"
Or you can use the "a" flag which opens a file for write at the end of the file.
File.open("c:\\temp\\myfile.txt", "a+").write("My first input: #{endtime-starttime} seconds \n")

You are using w which truncates the file before writing to it.
Use:
File.open("c:\\temp\\myfile.txt", "a+").write("My first input: #{endtime-starttime} seconds \n")

Related

Printing characters(with delay) on the same widget multiple times in Tkinter

I'm trying to print with delay (one character appears, a few milliseconds pass and then the next one appears) on the same widget multiple times one after the other, being something like >text appears with delay > a second passes> more text appears with delay... and so on. time.sleep() doesn't seems to work and i don't know how to properly use .after()
Here's the code i'm using
from tkinter import *
def insert_slow(widget, string):
if len(string) > 0:
widget.insert(END, string[0])
if len(string) > 1:
widget.after(50, insert_slow, widget, string[1:])
root=Tk()
tx=Text(root)
tx.pack()
insert_slow(tx, "this is a testing piece of text\n")
tx.after(3000)
loop=insert_slow(tx, "this is another testing piece of text")
root.mainloop()
The problem with your code is that after(3000) is almost exactly the same as time.sleep -- it freezes the whole UI.
The solution is pretty simple: use after to call your second insert_slow.
insert_slow(tx, "this is a testing piece of text\n")
tx.after(3000, insert_slow, tx, "this is another testing piece of text")
However, you need to be aware that after is relative to the time that you call after. Since the second line of code in the above example runs just a millisecond after the first, the second invocation won't happen 3 seconds after the first string appears, it will happen 3 seconds after it starts to appear.
If you want to wait for the first one to finish and then wait three seconds, you'll either have to do the math yourself (add 50ms times the number of characters to the starting value), or add some other mechanism. You could pass multiple strings to insert_slow, and it could automatically wait three seconds between each string.
Your code is executing the both texts in parallel so you get this output:
text1 = 'Hi to you'
text2 = 'Hi to me'
OUTPUT:
HHii tt oo ymoeu
Your insert_slow behaves well but you dont need to use after() again if you try to run text in two separate lines.
And if so, this should be on a different new text widget.
This code works if you want to output text on the same widget:
from tkinter import *
def insert_slow(widget, string):
if len(string) > 0:
widget.insert(END, string[0])
if len(string) > 1:
widget.after(50, insert_slow, widget, string[1:])
root=Tk()
tx=Text(root)
tx.pack()
text_body = "this is a testing piece of text\n" \
"this is another testing piece of text"
insert_slow(tx, text_body)
root.mainloop()
if you want the text lines to insert slow together, you can use this also:
from tkinter import *
def insert_slow(widget, string):
if len(string) > 0:
widget.insert(END, string[0])
if len(string) > 1:
widget.after(50, insert_slow, widget, string[1:])
root=Tk()
tx1=Text(root)
tx2=Text(root)
tx1.pack()
tx2.pack()
text_body1 = "this is a testing piece of text\n"
text_body2 = "this is another testing piece of text"
insert_slow(tx1, text_body1)
insert_slow(tx2, text_body2)
root.mainloop()

Python: Opening auto-generated file

As part of my larger program, I want to create a logfile with the current time & date as part of the title. I can create it as follows:
malwareLog = open(datetime.datetime.now().strftime("%Y%m%d - %H.%M " + pcName + " Malware scan log.txt"), "w+")
Now, my app is going to call a number of other functions, so I'll need to open the file, write some output to it and close the file, several times. It doesn't seem to work if I simply go:
malwareLog.open(malwareLog, "a+")
or similar. So how should I open a dynamically created txt file that I don't know the actual filename for...?
When you create malwareLog object, it has name attribute which contains the file name.
Here's an example: (my test is your malwareLog)
import random
test = open(str(random.randint(0,999999))+".txt", "w+")
test.write("hello ")
test.close()
test = open(test.name, "a+")
test.write("world!")
test.close()
with open(test.name, "r") as f: print(f.read())
You also can store the file name in a variable before or after creating the file.
###Before
file_name = "123"
malwareLog = open(file_name, "w")
###After
malwareLog = open(random.randint(0,999999), "w")
file_name = malwareLog.name

Ruby shoes4 package over 1.5GB

I've made a small CLI script in ruby to manage a small shop for a friend, but then he wanted me to make a GUI for him, so I looked around and found shoes4.
So, I went and download it, created a small test, and run:
./bin/shoes -p swt:jar ./path/to/app.rb
and left it to create the package, then I got a warning from system that I'm running low on disc space, so I went to check the jar file, and it was over 1.5GB and still not done packaging... and the code is very small and basic:
require 'yaml'
Shoes.app do
button "Add client" do
filename = ask_open_file
para File.read(filename)
clients = YAML.load_file(filename)
id = clients[clients.length - 1][0].to_i + 1
name = ask("Enter the client's full name: ")
items = ask("Enter list of items.")
patients[id] = ["ID = "+ id.to_s,"Name = "+ pname,"list of items:\n"+ items]
File.open(filename, 'w') { |f| YAML.dump(clients, f) }
alert ("Added new patient.")
end
button "Exit" do
exit()
end
end
any idea why this small app is more than 1.5GB?? or did I try to package it wrong way??
The packager will include everything in the directory of your shoes script and below.

Automatic reopening file for reading if it was recreated

There is some (compiled and not my) program A, which starts .log file from the beginning each time, when I launch it. And I wrote the program B to work with this log using this approach:
File.open("qconsole.log") do |log|
log.gets nil # I am interested only in new lines
loop do
next sleep 0.1 unless line = log.gets
line.chomp!
puts line
# some code
end
end
For example, after two new lines in the .log file I see this output:
player1: i talk blabla
player2: no way!
But when I quit and restart the program A:
]\quit
----- Server Shutdown -----
==== ShutdownGame ====
AAS shutdown.
---------------------------
----- CL_Shutdown -----
RE_Shutdown( 1 )
Shutting down OpenGL subsystem
...wglMakeCurrent( NULL, NULL ): success
...deleting GL context: success
...releasing DC: success
...destroying window
...shutting down QGL
...unloading OpenGL DLL
-----------------------
the program B seems to lose the .log file after this. It doesn't print me new lines anymore. I suppose, it gets eternal nil from log.gets.
So how can I know, that I need to stop doing log.gets and reopen the .log file?
UPD: Windows 7
My current dirty solution:
logfilesize = File.stat(logfile).size
log = File.open logfile
log.gets nil
loop do
logfilesize = File.stat(logfile).size.tap{ |t|
if t < logfilesize
log.close
log = File.open logfile
end
}
next sleep 0.1 unless line = log.gets
line.chomp!
puts line
# some code
end

Find and delete oldest AVI file recursively

I've been trying to write a Ruby script to find and delete the oldest AVI file in a folder. I found a script in Python that is very close, and I got a good start on the Ruby solution myself with:
require 'fileutils'
stat = Sys::Filesystem.stat("/")
mb_available = stat.block_size * stat.blocks_available / 1024 / 1024
#if there is less than 130MB free
if mb_available < 130000
require 'find'
movie_file_paths = []
#grab all the files in the folder
Find.find('/Users/jody/Movies') do |path|
movie_file_paths << path if /.*\.avi/.match(path) != nil
end
end
But, I'm having a tough time with the rest. Any help would be appreciated!
EDIT:
This was the solution:
movie_file_paths = []
Dir.glob("/Users/jody/Movies/**/*.avi").each { |file| movie_file_paths << file if File.file? file }
movie_file_paths.sort_by {|f| File.mtime(f)}
deleteme = movie_file_paths.first
I see you've already selected an answer but it can be a one-liner:
File.delete(Dir.glob("/Users/jody/Movies/**/*.avi").sort_by{|f| File.mtime(f)}.first)
Update: I came across this a few years later and thought to myself, "I can make that shorter!"
File.delete(Dir["/Users/jody/Movies/**/*.avi"]).min_by{|f| File.mtime(f)})
File has the methods you want, specifically ctime for "last changed" times (creation times on NTFS), mtime if you want "last modified" times, or atime for "last accessed" times. Combining this with Dir::glob, you can easily get a list of files sorted by datetime:
videos = Dir['/Users/jody/Movies/*.avi'].sort_by(&:ctime)
Deleting the last one is very simple:
File.delete videos.last
Use File.mtime(filename) to get the last modified time of the file.
movie_file_path.sort_by {|f| File.mtime(f)} will return a sorted array by mtime. You can then delete the file using File.delete(filename).
Edit: Last accessed time atime might be a better option than mtime.

Resources