Changing FirefoxProfile() preferences more than once using Selenium/Python - python-2.7

So I am trying to download multiple excel links to different file paths depending on the link using Selenium.
I am able to set up the FirefoxProfile to download all links to a certain single path, but I can't change the path on the fly as I try to download different files into different file paths. Does anyone have a fix for this?
self.fp = webdriver.FirefoxProfile()
self.ft.set_preferences("browser.download.folderList", 2)
self.ft.set_preferences("browser.download.showWhenStarting", 2)
self.ft.set_preferences("browser.download.dir", "C:\SOURCE FILES\BACKHAUL")
self.ft.set_preferences("browser.helperApps.neverAsk.saveToDisk", ("application/vnd.ms-excel))
self.driver = webdriver.Firefox(firefox_profile = self.fp)
This code will set the path I want once. But I want to be able to set it multiple times while running one script.

On Linux and Mac you can set the profile preferences to download to a directory that is a symbolic link to another directory. Then, while running the Selenium driver, you can change the destination of the symlink to the directory you want to download a file in, using the os library in Python.
Code outline (without try/except etc):
import os
from selenium import webdriver
DRIVER = "/usr/local/bin/geckodriver"
fp = webdriver.FirefoxProfile()
fp.set_preference("browser.download.dir", "/your/symlink/name")
fp.set_preference("browser.download.folderList",2)
fp.set_preference("browser.helperApps.neverAsk.saveToDisk", "your/mime/type")
driver = webdriver.Firefox(firefox_profile=fp, executable_path=DRIVER)
# delete symlink before changing to prevent a FileExistsError when changing the link
if os.path.exists("/your/symlink/name"):
os.unlink("/your/symlink/name")
# actually change/create the link
os.symlink("/real/target/directory", "/your/symlink/name")
# download the file
driver.get("https://example.com/file")
# set new target directory
os.unlink("/your/symlink/name")
os.symlink("/different/target/directory", "/your/symlink/name")
driver.get("https://example.com/otherfile")

You can define it only while initializing driver. So to do it with a new path you should driver.quit and start it again.

Related

Using custom fonts on shinyapps.io

I would like to use a custom font in my shiny app (on plots) on shinyapps.io. I have my Roboto-Regular.ttf in the ./www/ directory. And this is the upper portion of my app.R file:
dir.create('~/.fonts')
system("chmod +x ./www/Roboto-Regular.ttf")
system("cp ./www/Roboto-Regular.ttf ~/.fonts/")
system('fc-cache -f -v ~/.fonts/')
system('fc-match Roboto')
library(ggplot2)
library(shiny)
library(shinythemes)
library(extrafont)
font_import(pattern="Roboto",prompt=FALSE)
loadfonts()
print(fonts())
Upon deploying the app, I end up with an error that looks like this:
Registering fonts with R
Scanning ttf files in /usr/share/fonts/, ~/.fonts/ ...
Extracting .afm files from .ttf files...
/home/shiny/.fonts/Roboto-Regular.ttfWarning in gzfile(dest, "w") :
cannot open compressed file '/opt/R/3.5.1/lib/R/library/extrafontdb/metrics/Roboto-Regular.afm.gz', probable reason 'Permission denied'
Error in value[[3L]](cond) : cannot open the connection
Calls: local ... tryCatch -> tryCatchList -> tryCatchOne -> <Anonymous>
Execution halted
Does anyone see what might be wrong?
After a bit of struggle I found an even simpler solution that works on shinyapps.io:
Here we go:
Place custom font in www directory: e.g. IndieFlower.ttf from here
Follow the steps from here
This leads to the following upper part of the app.R file:
dir.create('~/.fonts')
file.copy("www/IndieFlower.ttf", "~/.fonts")
system('fc-cache -f ~/.fonts')
Since Linux looks into the .fonts directory to search fonts, you don't need the extrafont package, but you can directly use those fonts like:
ggplot(mapping=aes(x=seq(1,10,.1), y=seq(1,10,.1))) +
geom_line(position="jitter", color="red", size=2) + theme_bw() +
theme(text=element_text(size = 16, family = "IndieFlower"))
This is the answer I received from RStudio regarding this. I haven't tested this out myself.
Hi,
Our developer was able to advise this is due to a possibly unfortunate design choice made when they created extrafont and the associated extrafontdb package. The extrafont font database is stored in the extrafontdb package directory -- that's essentially all that the extrafontdb package is used for.
This means that the extrafontdb directory needs to be user-writable. If the user installs the package, this will work fine, but if root installs the package (as is the case on shinyapps.io), then it won't work.
One potential workaround is to install the extrafontdb package to library that is in subdirectory of the app.
To do it: create an r-lib/ subdir, and download the extrafontdb source package there:
dir.create('r-lib')
download.file('https://cran.r-project.org/src/contrib/extrafontdb_1.0.tar.gz','r-lib/extrafontdb_1.0.tar.gz')
When deployed, the app will include this r-lib/ subdirectory and the extrafontdb source package.
Then, at the top of the app, install the extrafontdb package from the source package, into the r-lib directory.
.libPaths(c('r-lib', .libPaths()))
install.packages('r-lib/extrafontdb_1.0.tar.gz',type = 'source',repos = NULL)
They deployed an app on shinyapps.io that does the extrafontdb installation, and it works fine. The libpath is set so so that install.packages() will install from the provided source package to the r-lib/ subdirectory of the app.
Please let us know if you're able to implement the above or have any additional questions.
Thanks,
Adding an alternative answer to symbolrush's answer which I found did not work. Here was the code I used initially:
# Add fonts to shiny linux server
if (Sys.info()[['sysname']] == 'Linux') {
dir.create('~/.fonts')
fonts = c(
"www/IBMPlexSans-Regular.ttf",
"www/IBMPlexSans-Bold.ttf",
"www/IBMPlexSans-Medium.ttf"
)
file.copy(fonts, "~/.fonts")
system('fc-cache -f ~/.fonts')
}
# Load fonts and set theme
font_paths("fonts")
font_add("IBMPlexSans", regular = "IBMPlexSans-Regular.ttf")
font_add("IBMPlexSans-Bold", regular = "IBMPlexSans-Bold.ttf")
font_add("IBMPlexSans-Medium", regular = "IBMPlexSans-Medium.ttf")
showtext_auto()
The bizarre thing is that the first instance of the app on shinyapps.io worked, including the custom fonts. However when the app went to sleep and was opened a second time, I get this error in the log:
Error in value[[3L]](cond) : font file not found for 'regular' type
I was never able to debug why this was the case, but I tried a simpler solution that has worked perfectly so far. I moved my fonts to a /font folder in the app folder (I don't think using the /www folder is necessary) and added the /font folder using path_folder():
library(showtext)
# Load fonts and set theme
font_paths("fonts")
font_add("IBMPlexSans", regular = "IBMPlexSans-Regular.ttf")
font_add("IBMPlexSans-Bold", regular = "IBMPlexSans-Bold.ttf")
font_add("IBMPlexSans-Medium", regular = "IBMPlexSans-Medium.ttf")
showtext_auto()
I hope this helps anyone who is having problems with their app not running after the first instance, as I could not find the same situation anywhere on stackoverflow.

How can I open a pdf with a relative path using the default application in a Qt program

I am trying to open a pdf manual for some hardware from within my application. It will be triggered from the help menu. I can't seem to get my application to open a file from a relative path using the OS default application. I found
QDesktopServices::openUrl(QUrl("file:///home/folder/Manual.pdf"));
referenced on the Qt forums and this works for me except I am going to install my software on another computer and the absolute path won't be the same. I'd like to install the manual next to my application and open it with something like
QDesktopServices::openUrl(QUrl("file:///Manual.pdf"));
but this fails to open with
ShellExecute 'file:///Manual.pdf' failed (error 2).
Has anyone done this before?
You can retrieve the absolute path with
QString a = QFileInfo("Manual.pdf").absoluteFilePath();
then pass it to QUrl, this way:
QUrl url = QUrl::fromLocalFile(a);
If Manual.pdf is in the folder of the executable, use:
QDesktopServices::openUrl(QUrl("file:///" + QApplication::applicationDirPath() + "/Manual.pdf"));
If you later decide to put the pdf in a dedicated sub-folder, e.g. doc, in the code above replace /Manual.pdf with /doc/Manual.pdf.

Locating project-specifc configuration files from imported modules

Project structure:
/lib/modules/mod1.py
/mod2.py
/subdir1/subdir2/mod3.py
/configs/config.yaml
mod3.py imports mod2.py. mod2.py imports mod1.py. mod1.py loads configuration files that are at a relative path to mod2.py using os.getcwd().
The problem is that when mod3.py imports mod2.py, mod1.py attempts to load the config files from a path relative to mod3.py (i.e. /subdir1/subdir2/configs/config.yaml instead of /configs/config.yaml)--this, of course, doesn't work.
I believe understand why this isn't working (os.getcwd() get the path of the originally executed file).
How can I fix this so that mod1.py will use a path relative to mod2.py even when mod2.py is imported from mod3.py?
I haven't been able to find a built-in way to do this in Python, so what I ended up doing is this:
mod1.py:
configs_list = os.getcwd().split('/')
for x in configs_list:
# Check each directory in list, bottom up. 'pop()' list on
# each failure. Assign var and break loop when configs path is found.
if not os.path.exists('/'.join(configs_list) + '/configs'):
configs_list.pop()
else:
configs_path = '/'.join(configs_list) + '/configs'
break
configs_path is then used to prefix the specific configuration file name(s) in mod1.py. Since every call to mod1.py will occur from within a project's directory structure, and every project has only one configs directory, this should (and has so far) correctly identified the configs directory regardless of where in the project the given script is being run from.
I'm open to better or more Pythonic ways of doing this, if anyone has input.

How to write a file in to an OS X app Resources folder?

I have an xcode project, the used language is C++. while my program is running writes a txt file in to
My App.app/Contents/Resources/
folder using fstream. After a month pause don't work anymore. Nothing is modified on the project but the OS X is updated. The file path is ok, i can read the file. What is wrong?
You should not write into your app bundle, and instead use one of the following folders to store files, which can be obtained using NSSearchPathForDirectoriesInDomains:
Document folder (NSDocumentDirectory).
Application Support folder (NSApplicationSupportDirectory).
Caches folder (NSCachesDirectory).
If you write to your app bundle you will cause issues with the code signing of the app and might not even have write access, if it's installed in the default location (/Applications).

Django tutorial path: TEMPLATE_PATH dir on a Mac networked computer

I'm (slowly!) working my way through the Django tutorial, and I've reached the point in Part 2 where I'm supposed to set the template_dir. I'm on a Mac (at work) where my user profile resides on a server, and I can't figure out how to set the path.
The tutorial files are in a folder called "tutorialshell", inside a folder called "Django," which is a first-level file inside my user folder "mattshepherd". That folder is the native folder when I launch the Terminal, for instance: it always starts me inside "mattshepherd".
I've tried
"~/Django/tutorialshell/templates"
and
"home/Django/tutorialshell/templates"
with no luck so far. I imagine there's some trick to doing this, as the files I'm trying to link to are on the network drive in my user folder, not on my local hard drive. Advice?
You want the absolute, not relative path. If you go to ~/Django/tutorialshell/templates in your terminal and then type pwd, it will tell you the full path to that folder. That's the value you should enter for the path.
Also: I assume you're actually talking about TEMPLATE_DIRS? If so, keep in mind that it's a list of paths, so it should look like:
TEMPLATE_DIRS = (
"/path/to/Django/tutorialshell/templates", # don't forget that trailing comma!
)
/Users/mattshepherd/Django/tutorialshell/templates
Please keep in mind that there is a LIST of template directories as mentioned by Jordan. The above location should work. In mac the user home directories are located at /Users/ + yourusername
It might be /home/ if /Users/ does not work.
As others have said you need the absolute path. But i would really suggest you to use relative path. It will make your code much more flexible. There are many ways to do it, this is what i usually do:
import os
ROOT = os.path.abspath(os.path.dirname(__file__))
then for the templates just do:
os.path.join(ROOT, 'templates')
You said you are using a Mac but you can make your code even more flexible by replacing "//" with "/" in the case you are using windows.