How could I read about:config entries for firefox version 30.0 using Python ? I tried to use what is pointed by this answer (in JavaScript) but it did not help.
Yeah, that's a problem. Firefox comes with default values for most preferences, and only stores values different from the default in the profile. Added to this, each add-on may come with additional default values and create new preferences at runtime.
The default pref files might be contained within zip files, which complicates matters a little.
Files
Files you'd have to check for default preferences (in a standard Firefox distribution)
$APPDIR/omni.ja:greprefs.js
$APPDIR/omni.ja:defaults/preferences/*.js
$APPDIR/browser/omni.ja:greprefs.js
$APPDIR/browser/omni.ja:defaults/preferences/*.js
$PROFILE/extensions/*/defaults/preferences/*.js
$PROFILE/extensions/*.xpi:defaults/preferences/*.js
While preferences that were overridden from the default reside in $PROFILE/prefs.js.
So first you need to figure out $APPDIR (installation path of Firefox) and then $PROFILE (Firefox user profile path).
Then you need to read some files either in some directories (easy) or in some zip files (hard). A major problem is that you cannot just use zipfile to read omni.ja (and potentially some of the xpi files) because a typical python zipfile implementation is too rigid in the interpretation of the zip structure and fails to open these files. So you'd need your own zipfile implementation that can deal with this.
Format
In the *.js files there are essentially two types of lines (+ blank lines, comment lines):
pref("name", value)
user_pref("name", value)
The pref lines are default preferences, user_pref lines are user preferences (overridden from default).
Values
value is a Javascript expression such as "abc", true, 1 or 2 * 3. The latter is a problem, as you'd need a JS engine to properly evaluate it. But this isn't really a problem in practice, as you won't find expressions computing something in the wild (usually).
Conclusion
Really replicating the preferences system (or about:config) isn't an easy task and full of obstacles. It is probably far easier just reading user pref.js to see what's overridden and knowing the default values.
Example (just prefs.js)
import re
import json
PROFILE = "/path/to/firefox/profile"
def read_user_prefs(preffile):
r = re.compile(r"\s*user_pref\(([\"'])(.+?)\1,\s*(.+?)\);")
rv = {}
for l in preffile:
m = r.match(l)
if not m:
continue
k, v = m.group(2), m.group(3)
try:
rv[k] = json.loads(v)
except Exception as ex:
print "failed to parse", k, v, ex
return rv
with open("{}/prefs.js".format(PROFILE), "rb") as p:
prefs = read_user_prefs(p)
for k, v in prefs.items():
print u"({type:<16}) {key}: {value}".format(
key=k, value=v, type=str(type(v)))
print
print "Chrome debugging enabled:",
print prefs.get("devtools.chrome.enabled", False)
print "Last sync:",
print prefs.get("services.sync.tabs.lastSync", 0.0)
print "Pref that might not exist:",
print prefs.get("does.not.exist", "default")
Alternatives
Write a firefox-addon that dumps interesting Preferences to a known file, or uses another form of IPC (sockets, whatever) to communicate with your python script.
Related
In Windows image files can be tagged. These tags can be viewed and edited by right clicking on a file, clicking over to the Details tab, then clicking on the Tags property value cell.
I want to be able to read and write these tags using Python 3.
This is not EXIF data so EXIF solutions won't work. I believe it's part of the Windows Property System, but I can't find a reference in Dev Center. I looked into win32com.propsys and couldn't see anything in there either.
I wrote a program that does this once before, but I've since lost it, so I know it's possible. Previously I did it without pywin32, but any solution would be great. I think I used windll, but I can't remember.
Here is some sample code that's using the IPropertyStore interface through propsys:
import pythoncom
from win32com.propsys import propsys
from win32com.shell import shellcon
# get PROPERTYKEY for "System.Keywords"
pk = propsys.PSGetPropertyKeyFromName("System.Keywords")
# get property store for a given shell item (here a file)
ps = propsys.SHGetPropertyStoreFromParsingName("c:\\path\\myfile.jpg", None, shellcon.GPS_READWRITE, propsys.IID_IPropertyStore)
# read & print existing (or not) property value, System.Keywords type is an array of string
keywords = ps.GetValue(pk).GetValue()
print(keywords)
# build an array of string type PROPVARIANT
newValue = propsys.PROPVARIANTType(["hello", "world"], pythoncom.VT_VECTOR | pythoncom.VT_BSTR)
# write property
ps.SetValue(pk, newValue)
ps.Commit()
This code is pretty generic for any Windows property.
I'm using System.Keywords because that's what corresponds to jpeg's "tags" property that you see in the property sheet.
And the code works for jpeg and other formats for reading (GetValue) properties, but not all Windows codecs support property writing (SetValue), to it doesn't work for writing extended properties back to a .png for example.
I want to make a script to change the default page zoom in Chrome, however I do not know where these options are stored.
I guess that I have to find an appropriate options text file, parse it, and then make a textual replacement there, using powershell in order to apply the changes.
I need to do it every time I plugin my laptop to an external monitor, and it is kinda annowying to do it by hand
Any ideas?
The default zoom level is stored in a huge JSON config file called Preferences, that can be found in the local appdata folder:
$LocalAppData = [Environment]::GetFolderPath( [Environment+SpecialFolder]::LocalApplicationData )
$ChromeDefaults = Join-Path $LocalAppData "Google\Chrome\User Data\default"
$ChromePrefFile = Join-Path $ChromeDefaults "Preferences"
$Settings = Get-Content $ChromePrefFile | ConvertFrom-Json
The default Page Zoom level is stored under the partition object, although it seems to store it as a unique identifier with some sort of ratio value, this is what it looks like with 100% zoom:
PS C:\> $Settings.partition.default_zoom_level | Format-List
2166136261 : 0.0
Other than that, I have no idea. I don't expect this to be a good idea, Chrome seems to update a number of binary values everytime the default files are updated, you might end up with a corrupt Preferences file
$Env:
Is a special PSdrive that contains many of the SpecialFolder Paths
$Env:LOCALAPPDATA
and
[Environment]::GetFolderPath( [Environment+SpecialFolder]::LocalApplicationData )
Yield the same result in addition to the rest of Mathias answer.
I have created syntax in SPSS that gives me 90 separate iterations of general linear model, each with slightly different variations fixed factors and covariates. In the output file, they are all just named as "General Linear Model." I have to then manually rename each analysis in the output, and I want to find syntax that will add a more specific name to each result that will help me identify it out of the other 89 results (e.g. "General Linear Model - Males Only: Mean by Gender w/ Weight covariate").
This is an example of one analysis from the syntax:
USE ALL.
COMPUTE filter_$=(Muscle = "BICEPS" & Subj = "S1" & SMU = 1 ).
VARIABLE LABELS filter_$ 'Muscle = "BICEPS" & Subj = "S1" & SMU = 1 (FILTER)'.
VALUE LABELS filter_$ 0 'Not Selected' 1 'Selected'.
FORMATS filter_$ (f1.0). FILTER BY filter_$.
EXECUTE.
GLM Frequency_Wk6 Frequency_Wk9
Frequency_Wk12 Frequency_Wk16
Frequency_Wk20
/WSFACTOR=Time 5 Polynomial
/METHOD=SSTYPE(3)
/PLOT=PROFILE(Time)
/EMMEANS=TABLES(Time)
/CRITERIA=ALPHA(.05)
/WSDESIGN=Time.
I am looking for syntax to add to this that will name this analysis as: "S1, SMU1 BICEPS, GLM" Not to name the whole output file, but each analysis within the output so I don't have to do it one-by-one. I have over 200 iterations at times that come out in a single output file, and renaming them individually within the output file is taking too much time.
Making an assumption that you are exporting the models to Excel (please clarify otherwise).
There is an undocumented command (OUTPUT COMMENT TEXT) that you can utilize here, though there is also a custom extension TEXT also designed to achieve the same but that would need to be explicitly downloaded via:
Utilities-->Extension Bundles-->Download And Install Extension Bundles--->TEXT
You can use OUTPUT COMMENT TEXT to assign a title/descriptive text just before the output of the GLM model (in the example below I have used FREQUENCIES as an example).
get file="C:\Program Files\IBM\SPSS\Statistics\23\Samples\English\Employee data.sav".
oms /select all /if commands=['output comment' 'frequencies'] subtypes=['comment' 'frequencies']
/destination format=xlsx outfile='C:\Temp\ExportOutput.xlsx' /tag='ExportOutput'.
output comment text="##Model##: This is a long/descriptive title to help me identify the next model that is to be run - jobcat".
freq jobcat.
output comment text="##Model##: This is a long/descriptive title to help me identify the next model that is to be run - gender".
freq gender.
output comment text="##Model##: This is a long/descriptive title to help me identify the next model that is to be run - minority".
freq minority.
omsend tag=['ExportOutput'].
You could use TITLE command here also but it is limited to only 60 characters.
You would have to change the OMS tags appropriately if using TITLE or TEXT.
Edit:
Given the OP wants to actually add a title to the left hand pane in the output viewer, a solution for this is as follows (credit to Albert-Jan Roskam for the Python code):
First save the python file "editTitles.py" to a valid Python search path (for example (for me anyway): "C:\ProgramData\IBM\SPSS\Statistics\23\extensions")
#editTitles.py
import tempfile, os, sys
import SpssClient
def _titleToPane():
"""See titleToPane(). This function does the actual job"""
outputDoc = SpssClient.GetDesignatedOutputDoc()
outputItemList = outputDoc.GetOutputItems()
textFormat = SpssClient.DocExportFormat.SpssFormatText
filename = tempfile.mktemp() + ".txt"
for index in range(outputItemList.Size()):
outputItem = outputItemList.GetItemAt(index)
if outputItem.GetDescription() == u"Page Title":
outputItem.ExportToDocument(filename, textFormat)
with open(filename) as f:
outputItem.SetDescription(f.read().rstrip())
os.remove(filename)
return outputDoc
def titleToPane(spv=None):
"""Copy the contents of the TITLE command of the designated output document
to the left output viewer pane"""
try:
outputDoc = None
SpssClient.StartClient()
if spv:
SpssClient.OpenOutputDoc(spv)
outputDoc = _titleToPane()
if spv and outputDoc:
outputDoc.SaveAs(spv)
except:
print "Error filling TITLE in Output Viewer [%s]" % sys.exc_info()[1]
finally:
SpssClient.StopClient()
Re-start SPSS Statistics and run below as a test:
get file="C:\Program Files\IBM\SPSS\Statistics\23\Samples\English\Employee data.sav".
title="##Model##: jobcat".
freq jobcat.
title="##Model##: gender".
freq gender.
title="##Model##: minority".
freq minority.
begin program.
import editTitles
editTitles.titleToPane()
end program.
The TITLE command will initially add a title to main output viewer (right hand side) but then the python code will transfer that text to the left hand pane output tree structure. As mentioned already, note TITLE is capped to 60 characters only, a warning will be triggered to highlight this also.
This editTitles.py approach is the closest you are going to get to include a descriptive title to identify each model. To replace the actual title "General Linear Model." with a custom title would require scripting knowledge and would involve a lot more code. This is a simpler alternative approach. Python integration required for this to work.
Also consider using:
SPLIT FILE SEPARATE BY <list of filter variables>.
This will automatically produce filter labels in the left hand pane.
This is easy to use for mutually exclusive filters but even if you have overlapping filters you can re-run multiple times (and have filters applied to get as close to your desired set of results).
For example:
get file="C:\Program Files\IBM\SPSS\Statistics\23\Samples\English\Employee data.sav".
sort cases by jobcat minority.
split file separate by jobcat minority.
freq educ.
split file off.
Is there a way to create a single snippet file where the content output is dependent on the language? For example, keyboard shortcut x outputs "abc" when used in a css file, but "def" when used in a javascript file?
Snippets don't contain much processing capability — you can perform substitutions in them via Boost-style regexes and format strings, and they have access to a number of environment variables within Sublime such as the current file's name, the line number, etc., but beyond that they don't have much programmatic processing capability. It might be possible to set up a series of regexes that try to case-insensitively match $TM_FILENAME against \.css$ and output abc, then immediately match $TM_FILENAME against \.js$ and output def - only one of them will be successful.
However, in my mind such processing is much more easily handled by a plugin written in Python. The API documentation is mostly complete (all the functions you'll need are documented there) and there are a ton of examples around the net to learn/borrow from. Here's a quick example:
import sublime_plugin
class PrintScopeCommand(sublime_plugin.TextCommand):
def run(self, edit):
pos = self.view.sel()[0].begin()
scope = self.view.scope_name(pos)
if 'source.js' in scope:
self.view.insert(edit, pos, "This is JavaScript!")
elif 'source.css' in scope:
self.view.insert(edit, pos, "This is CSS!")
Save the file in your Packages/User directory (accessible via Preferences -> Browse Packages...) as print_scope.py. Next, assign it to a key binding by opening your user keymap (Preferences -> Key Bindings-User) and adding the following:
[
{ "keys": ["ctrl+alt+shift+p"], "command": "print_scope" }
]
if the file is empty. If you already have other custom key bindings, just add a comma , after the last one, then paste the line above after it, before the closing square bracket ].
You should now be able to hit CtrlAltShiftP (or whatever other key binding you choose), and if the file's syntax is set to JavaScript it will insert the This is JavaScript! message at the current cursor position. If the syntax is set to CSS, This is CSS! will print, and if the syntax is anything else, then nothing will print.
I've been writing a program in R that outputs randomization schemes for a research project I'm working on with a few other people this summer, and I'm done with the majority of it, except for one feature. Part of what I've been doing is making it really user friendly, so that the program will prompt the user for certain pieces of information, and therefore know what needs to be randomized. I have it set up to check every piece of user input to make sure it's a valid input, and give an error message/prompt the user again if it's not. The only thing I can't quite figure out is how to get it to check whether or not the file name for the .csv output is valid. Does anyone know if there is a way to get R to check if a string makes a valid windows file name? Thanks!
These characters aren't allowed: /\:*?"<>|. So warn the user if it contains any of those.
Some other names are also disallowed: COM, AUX, NUL, COM1 to COM9, LPT1 to LPT9.
You probably want to check that the filename is valid using a regular expression. See this other answer for a Java example that should take minimal tweaking to work in R.
https://stackoverflow.com/a/6804755/134830
You may also want to check the filename length (260 characters for maximum portability, though longer names are allowed on some systems).
Finally, in R, if you try to create a file in a directory that doesn't exist, it will still fail, so you need to split the name up into the filename and directory name (using basename and dirname) and try to create the directory first, if necessary.
That said, David Heffernan gives good advice in his comment to let Windows do the wok in deciding whether or not it can create the file: you don't want to erroneously tell the user that a filename is invalid.
You want something a little like this:
nice_file_create <- function(filename)
{
directory_name <- dirname(filename)
if(!file.exists(directory_name))
{
ok <- dir.create(directory_name)
if(!ok)
{
warning("The directory of that path could not be created.")
return(invisible())
}
}
tryCatch(
file.create(filename),
error = function(e)
{
warning("The file could not be created.")
}
)
}
But test it thoroughly first! There are all sorts of edge cases where things can fall over: try UNC network path names, "~", and paths with "." and ".." in them.
I'd suggest that the easiest way to make sure a filename is valid is to use fs::path_sanitize().
It removes control characters, reserved characters, and Windows-reserved filenames, truncating the string at 255 bytes in length.