Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
32a71457
Commit
32a71457
authored
Oct 06, 2014
by
Terry Jan Reedy
Browse files
Options
Browse Files
Download
Plain Diff
Merge with 3.4: idlelib.configHandler
parents
b91ed56b
deb7bf12
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
233 additions
and
255 deletions
+233
-255
Lib/idlelib/configHandler.py
Lib/idlelib/configHandler.py
+233
-255
No files found.
Lib/idlelib/configHandler.py
View file @
32a71457
...
@@ -15,8 +15,9 @@ idle. This is to allow IDLE to continue to function in spite of errors in
...
@@ -15,8 +15,9 @@ idle. This is to allow IDLE to continue to function in spite of errors in
the retrieval of config information. When a default is returned instead of
the retrieval of config information. When a default is returned instead of
a requested config value, a message is printed to stderr to aid in
a requested config value, a message is printed to stderr to aid in
configuration problem notification and resolution.
configuration problem notification and resolution.
"""
"""
# TODOs added Oct 2014, tjr
import
os
import
os
import
sys
import
sys
...
@@ -35,7 +36,7 @@ class IdleConfParser(ConfigParser):
...
@@ -35,7 +36,7 @@ class IdleConfParser(ConfigParser):
"""
"""
cfgFile - string, fully specified configuration file name
cfgFile - string, fully specified configuration file name
"""
"""
self
.
file
=
cfgFile
self
.
file
=
cfgFile
ConfigParser
.
__init__
(
self
,
defaults
=
cfgDefaults
,
strict
=
False
)
ConfigParser
.
__init__
(
self
,
defaults
=
cfgDefaults
,
strict
=
False
)
def
Get
(
self
,
section
,
option
,
type
=
None
,
default
=
None
,
raw
=
False
):
def
Get
(
self
,
section
,
option
,
type
=
None
,
default
=
None
,
raw
=
False
):
...
@@ -45,26 +46,22 @@ class IdleConfParser(ConfigParser):
...
@@ -45,26 +46,22 @@ class IdleConfParser(ConfigParser):
"""
"""
if
not
self
.
has_option
(
section
,
option
):
if
not
self
.
has_option
(
section
,
option
):
return
default
return
default
if
type
==
'bool'
:
if
type
==
'bool'
:
return
self
.
getboolean
(
section
,
option
)
return
self
.
getboolean
(
section
,
option
)
elif
type
==
'int'
:
elif
type
==
'int'
:
return
self
.
getint
(
section
,
option
)
return
self
.
getint
(
section
,
option
)
else
:
else
:
return
self
.
get
(
section
,
option
,
raw
=
raw
)
return
self
.
get
(
section
,
option
,
raw
=
raw
)
def
GetOptionList
(
self
,
section
):
def
GetOptionList
(
self
,
section
):
"""
"Return a list of options for given section, else []."
Get an option list for given section
"""
if
self
.
has_section
(
section
):
if
self
.
has_section
(
section
):
return
self
.
options
(
section
)
return
self
.
options
(
section
)
else
:
#return a default value
else
:
#return a default value
return
[]
return
[]
def
Load
(
self
):
def
Load
(
self
):
"""
"Load the configuration file from disk."
Load the configuration file from disk
"""
self
.
read
(
self
.
file
)
self
.
read
(
self
.
file
)
class
IdleUserConfParser
(
IdleConfParser
):
class
IdleUserConfParser
(
IdleConfParser
):
...
@@ -72,61 +69,50 @@ class IdleUserConfParser(IdleConfParser):
...
@@ -72,61 +69,50 @@ class IdleUserConfParser(IdleConfParser):
IdleConfigParser specialised for user configuration handling.
IdleConfigParser specialised for user configuration handling.
"""
"""
def
AddSection
(
self
,
section
):
def
AddSection
(
self
,
section
):
"""
"If section doesn't exist, add it."
if section doesn't exist, add it
"""
if
not
self
.
has_section
(
section
):
if
not
self
.
has_section
(
section
):
self
.
add_section
(
section
)
self
.
add_section
(
section
)
def
RemoveEmptySections
(
self
):
def
RemoveEmptySections
(
self
):
"""
"Remove any sections that have no options."
remove any sections that have no options
"""
for
section
in
self
.
sections
():
for
section
in
self
.
sections
():
if
not
self
.
GetOptionList
(
section
):
if
not
self
.
GetOptionList
(
section
):
self
.
remove_section
(
section
)
self
.
remove_section
(
section
)
def
IsEmpty
(
self
):
def
IsEmpty
(
self
):
"""
"Return True if no sections after removing empty sections."
Remove empty sections and then return 1 if parser has no sections
left, else return 0.
"""
self
.
RemoveEmptySections
()
self
.
RemoveEmptySections
()
if
self
.
sections
():
return
not
self
.
sections
()
return
0
else
:
return
1
def
RemoveOption
(
self
,
section
,
option
):
def
RemoveOption
(
self
,
section
,
option
):
"""
"""
Return True if option is removed from section, else False.
If section/option exists, remove it.
Returns 1 if option was removed, 0 otherwise
.
False if either section does not exist or did not have option
.
"""
"""
if
self
.
has_section
(
section
):
if
self
.
has_section
(
section
):
return
self
.
remove_option
(
section
,
option
)
return
self
.
remove_option
(
section
,
option
)
return
False
def
SetOption
(
self
,
section
,
option
,
value
):
def
SetOption
(
self
,
section
,
option
,
value
):
"""
"""
Return True if option is added or changed to value, else False.
Sets option to value, adding section if required.
Returns 1 if option was added or changed, otherwise 0
.
Add section if required. False means option already had value
.
"""
"""
if
self
.
has_option
(
section
,
option
):
if
self
.
has_option
(
section
,
option
):
if
self
.
get
(
section
,
option
)
==
value
:
if
self
.
get
(
section
,
option
)
==
value
:
return
0
return
False
else
:
else
:
self
.
set
(
section
,
option
,
value
)
self
.
set
(
section
,
option
,
value
)
return
1
return
True
else
:
else
:
if
not
self
.
has_section
(
section
):
if
not
self
.
has_section
(
section
):
self
.
add_section
(
section
)
self
.
add_section
(
section
)
self
.
set
(
section
,
option
,
value
)
self
.
set
(
section
,
option
,
value
)
return
1
return
True
def
RemoveFile
(
self
):
def
RemoveFile
(
self
):
"""
"Remove user config file self.file from disk if it exists."
Removes the user config file from disk if it exists.
"""
if
os
.
path
.
exists
(
self
.
file
):
if
os
.
path
.
exists
(
self
.
file
):
os
.
remove
(
self
.
file
)
os
.
remove
(
self
.
file
)
...
@@ -150,60 +136,57 @@ class IdleUserConfParser(IdleConfParser):
...
@@ -150,60 +136,57 @@ class IdleUserConfParser(IdleConfParser):
self
.
RemoveFile
()
self
.
RemoveFile
()
class
IdleConf
:
class
IdleConf
:
"""
"""Hold config parsers for all idle config files in singleton instance.
holds config parsers for all idle config files:
default config files
Default config files, self.defaultCfg --
(idle install dir)/config-main.def
for config_type in self.config_types:
(idle install dir)/config-extensions.def
(idle install dir)/config-{config-type}.def
(idle install dir)/config-highlight.def
(idle install dir)/config-keys.def
User config files, self.userCfg --
user config files
for config_type in self.config_types:
(user home dir)/.idlerc/config-main.cfg
(user home dir)/.idlerc/config-{config-type}.cfg
(user home dir)/.idlerc/config-extensions.cfg
(user home dir)/.idlerc/config-highlight.cfg
(user home dir)/.idlerc/config-keys.cfg
"""
"""
def
__init__
(
self
):
def
__init__
(
self
):
self
.
defaultCfg
=
{}
self
.
config_types
=
(
'main'
,
'extensions'
,
'highlight'
,
'keys'
)
self
.
userCfg
=
{}
self
.
defaultCfg
=
{}
self
.
cfg
=
{}
self
.
userCfg
=
{}
self
.
cfg
=
{}
# TODO use to select userCfg vs defaultCfg
self
.
CreateConfigHandlers
()
self
.
CreateConfigHandlers
()
self
.
LoadCfgFiles
()
self
.
LoadCfgFiles
()
#self.LoadCfg()
def
CreateConfigHandlers
(
self
):
def
CreateConfigHandlers
(
self
):
"""
"Populate default and user config parser dictionaries."
set up a dictionary of config parsers for default and user
configurations respectively
"""
#build idle install path
#build idle install path
if
__name__
!=
'__main__'
:
# we were imported
if
__name__
!=
'__main__'
:
# we were imported
idleDir
=
os
.
path
.
dirname
(
__file__
)
idleDir
=
os
.
path
.
dirname
(
__file__
)
else
:
# we were exec'ed (for testing only)
else
:
# we were exec'ed (for testing only)
idleDir
=
os
.
path
.
abspath
(
sys
.
path
[
0
])
idleDir
=
os
.
path
.
abspath
(
sys
.
path
[
0
])
userDir
=
self
.
GetUserCfgDir
()
userDir
=
self
.
GetUserCfgDir
()
configTypes
=
(
'main'
,
'extensions'
,
'highlight'
,
'keys'
)
defCfgFiles
=
{}
defCfgFiles
=
{}
usrCfgFiles
=
{}
usrCfgFiles
=
{}
for
cfgType
in
configTypes
:
#build config file names
# TODO eliminate these temporaries by combining loops
defCfgFiles
[
cfgType
]
=
os
.
path
.
join
(
idleDir
,
'config-'
+
cfgType
+
'.def'
)
for
cfgType
in
self
.
config_types
:
#build config file names
usrCfgFiles
[
cfgType
]
=
os
.
path
.
join
(
userDir
,
'config-'
+
cfgType
+
'.cfg'
)
defCfgFiles
[
cfgType
]
=
os
.
path
.
join
(
for
cfgType
in
configTypes
:
#create config parsers
idleDir
,
'config-'
+
cfgType
+
'.def'
)
self
.
defaultCfg
[
cfgType
]
=
IdleConfParser
(
defCfgFiles
[
cfgType
])
usrCfgFiles
[
cfgType
]
=
os
.
path
.
join
(
self
.
userCfg
[
cfgType
]
=
IdleUserConfParser
(
usrCfgFiles
[
cfgType
])
userDir
,
'config-'
+
cfgType
+
'.cfg'
)
for
cfgType
in
self
.
config_types
:
#create config parsers
self
.
defaultCfg
[
cfgType
]
=
IdleConfParser
(
defCfgFiles
[
cfgType
])
self
.
userCfg
[
cfgType
]
=
IdleUserConfParser
(
usrCfgFiles
[
cfgType
])
def
GetUserCfgDir
(
self
):
def
GetUserCfgDir
(
self
):
"""
"""Return a filesystem directory for storing user config files.
Creates (if required) and returns a filesystem directory for storing
user config files.
Creates it if required.
"""
"""
cfgDir
=
'.idlerc'
cfgDir
=
'.idlerc'
userDir
=
os
.
path
.
expanduser
(
'~'
)
userDir
=
os
.
path
.
expanduser
(
'~'
)
if
userDir
!=
'~'
:
# expanduser() found user home dir
if
userDir
!=
'~'
:
# expanduser() found user home dir
if
not
os
.
path
.
exists
(
userDir
):
if
not
os
.
path
.
exists
(
userDir
):
warn
=
(
'
\
n
Warning: os.path.expanduser("~") points to
\
n
'
+
warn
=
(
'
\
n
Warning: os.path.expanduser("~") points to
\
n
'
+
userDir
+
',
\
n
but the path does not exist.'
)
userDir
+
',
\
n
but the path does not exist.'
)
try
:
try
:
print
(
warn
,
file
=
sys
.
stderr
)
print
(
warn
,
file
=
sys
.
stderr
)
except
OSError
:
except
OSError
:
...
@@ -217,28 +200,28 @@ class IdleConf:
...
@@ -217,28 +200,28 @@ class IdleConf:
try
:
try
:
os
.
mkdir
(
userDir
)
os
.
mkdir
(
userDir
)
except
OSError
:
except
OSError
:
warn
=
(
'
\
n
Warning: unable to create user config directory
\
n
'
+
warn
=
(
'
\
n
Warning: unable to create user config directory
\
n
'
+
userDir
+
'
\
n
Check path and permissions.
\
n
Exiting!
\
n
'
)
userDir
+
'
\
n
Check path and permissions.
\
n
Exiting!
\
n
'
)
print
(
warn
,
file
=
sys
.
stderr
)
print
(
warn
,
file
=
sys
.
stderr
)
raise
SystemExit
raise
SystemExit
# TODO continue without userDIr instead of exit
return
userDir
return
userDir
def
GetOption
(
self
,
configType
,
section
,
option
,
default
=
None
,
type
=
None
,
def
GetOption
(
self
,
configType
,
section
,
option
,
default
=
None
,
type
=
None
,
warn_on_default
=
True
,
raw
=
False
):
warn_on_default
=
True
,
raw
=
False
):
"""
"""Return a value for configType section option, or default.
Get an option value for given config type and given general
configuration section/option or return a default. If type is specified,
If type is not None, return a value of that type. Also pass raw
return as type. Firstly the user configuration is checked, with a
to the config parser. First try to return a valid value
fallback to the default configuration, and a final 'catch all'
(including type) from a user configuration. If that fails, try
fallback to a useable passed-in default if the option isn't present in
the default configuration. If that fails, return default, with a
either the user or the default configuration.
default of None.
configType must be one of ('main','extensions','highlight','keys')
If a default is returned, and warn_on_default is True, a warning is
printed to stderr.
Warn if either user or default configurations have an invalid value.
Warn if default is returned and warn_on_default is True.
"""
"""
try
:
try
:
if
self
.
userCfg
[
configType
].
has_option
(
section
,
option
):
if
self
.
userCfg
[
configType
].
has_option
(
section
,
option
):
return
self
.
userCfg
[
configType
].
Get
(
section
,
option
,
return
self
.
userCfg
[
configType
].
Get
(
section
,
option
,
type
=
type
,
raw
=
raw
)
type
=
type
,
raw
=
raw
)
except
ValueError
:
except
ValueError
:
...
@@ -246,16 +229,15 @@ class IdleConf:
...
@@ -246,16 +229,15 @@ class IdleConf:
' invalid %r value for configuration option %r
\
n
'
' invalid %r value for configuration option %r
\
n
'
' from section %r: %r'
%
' from section %r: %r'
%
(
type
,
option
,
section
,
(
type
,
option
,
section
,
self
.
userCfg
[
configType
].
Get
(
section
,
option
,
self
.
userCfg
[
configType
].
Get
(
section
,
option
,
raw
=
raw
)))
raw
=
raw
)))
try
:
try
:
print
(
warning
,
file
=
sys
.
stderr
)
print
(
warning
,
file
=
sys
.
stderr
)
except
OSError
:
except
OSError
:
pass
pass
try
:
try
:
if
self
.
defaultCfg
[
configType
].
has_option
(
section
,
option
):
if
self
.
defaultCfg
[
configType
].
has_option
(
section
,
option
):
return
self
.
defaultCfg
[
configType
].
Get
(
section
,
option
,
return
self
.
defaultCfg
[
configType
].
Get
(
type
=
type
,
raw
=
raw
)
section
,
option
,
type
=
type
,
raw
=
raw
)
except
ValueError
:
except
ValueError
:
pass
pass
#returning default, print warning
#returning default, print warning
...
@@ -272,22 +254,19 @@ class IdleConf:
...
@@ -272,22 +254,19 @@ class IdleConf:
return
default
return
default
def
SetOption
(
self
,
configType
,
section
,
option
,
value
):
def
SetOption
(
self
,
configType
,
section
,
option
,
value
):
"""In user's config file, set section's option to value.
"""Set section option to value in user config file."""
"""
self
.
userCfg
[
configType
].
SetOption
(
section
,
option
,
value
)
self
.
userCfg
[
configType
].
SetOption
(
section
,
option
,
value
)
def
GetSectionList
(
self
,
configSet
,
configType
):
def
GetSectionList
(
self
,
configSet
,
configType
):
"""
"""Return sections for configSet configType configuration.
Get a list of sections from either the user or default config for
the given config type.
configSet must be either 'user' or 'default'
configSet must be either 'user' or 'default'
configType must be
one of ('main','extensions','highlight','keys')
configType must be
in self.config_types.
"""
"""
if
not
(
configType
in
(
'main'
,
'extensions'
,
'highlight'
,
'keys'
)
):
if
not
(
configType
in
self
.
config_types
):
raise
InvalidConfigType
(
'Invalid configType specified'
)
raise
InvalidConfigType
(
'Invalid configType specified'
)
if
configSet
==
'user'
:
if
configSet
==
'user'
:
cfgParser
=
self
.
userCfg
[
configType
]
cfgParser
=
self
.
userCfg
[
configType
]
elif
configSet
==
'default'
:
elif
configSet
==
'default'
:
cfgParser
=
self
.
defaultCfg
[
configType
]
cfgParser
=
self
.
defaultCfg
[
configType
]
else
:
else
:
...
@@ -295,22 +274,22 @@ class IdleConf:
...
@@ -295,22 +274,22 @@ class IdleConf:
return
cfgParser
.
sections
()
return
cfgParser
.
sections
()
def
GetHighlight
(
self
,
theme
,
element
,
fgBg
=
None
):
def
GetHighlight
(
self
,
theme
,
element
,
fgBg
=
None
):
"""
"""
Return individual highlighting theme elements.
return individual highlighting theme elements.
fgBg - string ('fg'or'bg') or None, if None return a dictionary
fgBg - string ('fg'or'bg') or None, if None return a dictionary
containing fg and bg colours (appropriate for passing to Tkinter in,
containing fg and bg colours (appropriate for passing to Tkinter in,
e.g., a tag_config call), otherwise fg or bg colour only as specified.
e.g., a tag_config call), otherwise fg or bg colour only as specified.
"""
"""
if
self
.
defaultCfg
[
'highlight'
].
has_section
(
theme
):
if
self
.
defaultCfg
[
'highlight'
].
has_section
(
theme
):
themeDict
=
self
.
GetThemeDict
(
'default'
,
theme
)
themeDict
=
self
.
GetThemeDict
(
'default'
,
theme
)
else
:
else
:
themeDict
=
self
.
GetThemeDict
(
'user'
,
theme
)
themeDict
=
self
.
GetThemeDict
(
'user'
,
theme
)
fore
=
themeDict
[
element
+
'-foreground'
]
fore
=
themeDict
[
element
+
'-foreground'
]
if
element
==
'cursor'
:
#there is no config value for cursor bg
if
element
==
'cursor'
:
#there is no config value for cursor bg
back
=
themeDict
[
'normal-background'
]
back
=
themeDict
[
'normal-background'
]
else
:
else
:
back
=
themeDict
[
element
+
'-background'
]
back
=
themeDict
[
element
+
'-background'
]
highlight
=
{
"foreground"
:
fore
,
"background"
:
back
}
highlight
=
{
"foreground"
:
fore
,
"background"
:
back
}
if
not
fgBg
:
#return dict of both colours
if
not
fgBg
:
#return dict of both colours
return
highlight
return
highlight
else
:
#return specified colour only
else
:
#return specified colour only
...
@@ -321,26 +300,26 @@ class IdleConf:
...
@@ -321,26 +300,26 @@ class IdleConf:
else
:
else
:
raise
InvalidFgBg
(
'Invalid fgBg specified'
)
raise
InvalidFgBg
(
'Invalid fgBg specified'
)
def
GetThemeDict
(
self
,
type
,
themeName
):
def
GetThemeDict
(
self
,
type
,
themeName
):
"""
"""Return {option:value} dict for elements in themeName.
type - string, 'default' or 'user' theme type
type - string, 'default' or 'user' theme type
themeName - string, theme name
themeName - string, theme name
Returns a dictionary which holds {option:value} for each element
Values are loaded over ultimate fallback defaults to guarantee
in the specified theme. Values are loaded over a set of ultimate last
that all theme elements are present in a newly created theme.
fallback defaults to guarantee that all theme elements are present in
a newly created theme.
"""
"""
if
type
==
'user'
:
if
type
==
'user'
:
cfgParser
=
self
.
userCfg
[
'highlight'
]
cfgParser
=
self
.
userCfg
[
'highlight'
]
elif
type
==
'default'
:
elif
type
==
'default'
:
cfgParser
=
self
.
defaultCfg
[
'highlight'
]
cfgParser
=
self
.
defaultCfg
[
'highlight'
]
else
:
else
:
raise
InvalidTheme
(
'Invalid theme type specified'
)
raise
InvalidTheme
(
'Invalid theme type specified'
)
#foreground and background values are provded for each theme element
#foreground and background values are provded for each theme element
#(apart from cursor) even though all these values are not yet used
#(apart from cursor) even though all these values are not yet used
#by idle, to allow for their use in the future. Default values are
#by idle, to allow for their use in the future. Default values are
#generally black and white.
#generally black and white.
theme
=
{
'normal-foreground'
:
'#000000'
,
# TODO make theme, a constant, a module or class attribute
theme
=
{
'normal-foreground'
:
'#000000'
,
'normal-background'
:
'#ffffff'
,
'normal-background'
:
'#ffffff'
,
'keyword-foreground'
:
'#000000'
,
'keyword-foreground'
:
'#000000'
,
'keyword-background'
:
'#ffffff'
,
'keyword-background'
:
'#ffffff'
,
...
@@ -370,9 +349,9 @@ class IdleConf:
...
@@ -370,9 +349,9 @@ class IdleConf:
'console-foreground'
:
'#000000'
,
'console-foreground'
:
'#000000'
,
'console-background'
:
'#ffffff'
}
'console-background'
:
'#ffffff'
}
for
element
in
theme
:
for
element
in
theme
:
if
not
cfgParser
.
has_option
(
themeName
,
element
):
if
not
cfgParser
.
has_option
(
themeName
,
element
):
#we are going to return a default, print warning
#we are going to return a default, print warning
warning
=
(
'
\
n
Warning: configHandler.py - IdleConf.GetThemeDict'
warning
=
(
'
\
n
Warning: configHandler.py - IdleConf.GetThemeDict'
' -
\
n
problem retrieving theme element %r'
' -
\
n
problem retrieving theme element %r'
'
\
n
from theme %r.
\
n
'
'
\
n
from theme %r.
\
n
'
' returning default value: %r'
%
' returning default value: %r'
%
...
@@ -381,41 +360,39 @@ class IdleConf:
...
@@ -381,41 +360,39 @@ class IdleConf:
print
(
warning
,
file
=
sys
.
stderr
)
print
(
warning
,
file
=
sys
.
stderr
)
except
OSError
:
except
OSError
:
pass
pass
colour
=
cfgParser
.
Get
(
themeName
,
element
,
default
=
theme
[
element
])
colour
=
cfgParser
.
Get
(
themeName
,
element
,
default
=
theme
[
element
])
theme
[
element
]
=
colour
theme
[
element
]
=
colour
return
theme
return
theme
def
CurrentTheme
(
self
):
def
CurrentTheme
(
self
):
"""
"Return the name of the currently active theme."
Returns the name of the currently active theme
return
self
.
GetOption
(
'main'
,
'Theme'
,
'name'
,
default
=
''
)
"""
return
self
.
GetOption
(
'main'
,
'Theme'
,
'name'
,
default
=
''
)
def
CurrentKeys
(
self
):
def
CurrentKeys
(
self
):
"""
"Return the name of the currently active key set."
Returns the name of the currently active key set
return
self
.
GetOption
(
'main'
,
'Keys'
,
'name'
,
default
=
''
)
"""
return
self
.
GetOption
(
'main'
,
'Keys'
,
'name'
,
default
=
''
)
def
GetExtensions
(
self
,
active_only
=
True
,
editor_only
=
False
,
shell_only
=
False
):
def
GetExtensions
(
self
,
active_only
=
True
,
editor_only
=
False
,
shell_only
=
False
):
"""Return extensions in default and user config-extensions files.
If active_only True, only return active (enabled) extensions
and optionally only editor or shell extensions.
If active_only False, return all extensions.
"""
"""
Gets a list of all idle extensions declared in the config files.
extns
=
self
.
RemoveKeyBindNames
(
active_only - boolean, if true only return active (enabled) extensions
self
.
GetSectionList
(
'default'
,
'extensions'
))
"""
userExtns
=
self
.
RemoveKeyBindNames
(
extns
=
self
.
RemoveKeyBindNames
(
self
.
GetSectionList
(
'user'
,
'extensions'
))
self
.
GetSectionList
(
'default'
,
'extensions'
))
userExtns
=
self
.
RemoveKeyBindNames
(
self
.
GetSectionList
(
'user'
,
'extensions'
))
for
extn
in
userExtns
:
for
extn
in
userExtns
:
if
extn
not
in
extns
:
#user has added own extension
if
extn
not
in
extns
:
#user has added own extension
extns
.
append
(
extn
)
extns
.
append
(
extn
)
if
active_only
:
if
active_only
:
activeExtns
=
[]
activeExtns
=
[]
for
extn
in
extns
:
for
extn
in
extns
:
if
self
.
GetOption
(
'extensions'
,
extn
,
'enable'
,
default
=
True
,
if
self
.
GetOption
(
'extensions'
,
extn
,
'enable'
,
default
=
True
,
type
=
'bool'
):
type
=
'bool'
):
#the extension is enabled
#the extension is enabled
if
editor_only
or
shell_only
:
if
editor_only
or
shell_only
:
# TODO if both, contradictory
if
editor_only
:
if
editor_only
:
option
=
"enable_editor"
option
=
"enable_editor"
else
:
else
:
...
@@ -430,107 +407,108 @@ class IdleConf:
...
@@ -430,107 +407,108 @@ class IdleConf:
else
:
else
:
return
extns
return
extns
def
RemoveKeyBindNames
(
self
,
extnNameList
):
def
RemoveKeyBindNames
(
self
,
extnNameList
):
#get rid of keybinding section names
"Return extnNameList with keybinding section names removed."
names
=
extnNameList
# TODO Easier to return filtered copy with list comp
kbNameIndicies
=
[]
names
=
extnNameList
kbNameIndicies
=
[]
for
name
in
names
:
for
name
in
names
:
if
name
.
endswith
((
'_bindings'
,
'_cfgBindings'
)):
if
name
.
endswith
((
'_bindings'
,
'_cfgBindings'
)):
kbNameIndicies
.
append
(
names
.
index
(
name
))
kbNameIndicies
.
append
(
names
.
index
(
name
))
kbNameIndicies
.
sort
()
kbNameIndicies
.
sort
(
reverse
=
True
)
kbNameIndicies
.
reverse
()
for
index
in
kbNameIndicies
:
#delete each keybinding section name
for
index
in
kbNameIndicies
:
#delete each keybinding section name
del
(
names
[
index
])
del
(
names
[
index
])
return
names
return
names
def
GetExtnNameForEvent
(
self
,
virtualEvent
):
def
GetExtnNameForEvent
(
self
,
virtualEvent
):
"""
"""Return the name of the extension binding virtualEvent, or None.
Returns the name of the extension that virtualEvent is bound in, or
None if not bound in any extension.
virtualEvent - string, name of the virtual event to test for,
virtualEvent - string, name of the virtual event to test for, without
without the enclosing '<< >>'
the enclosing '<< >>'
"""
"""
extName
=
None
extName
=
None
vEvent
=
'<<'
+
virtualEvent
+
'>>'
vEvent
=
'<<'
+
virtualEvent
+
'>>'
for
extn
in
self
.
GetExtensions
(
active_only
=
0
):
for
extn
in
self
.
GetExtensions
(
active_only
=
0
):
for
event
in
self
.
GetExtensionKeys
(
extn
):
for
event
in
self
.
GetExtensionKeys
(
extn
):
if
event
==
vEvent
:
if
event
==
vEvent
:
extName
=
extn
extName
=
extn
# TODO return here?
return
extName
return
extName
def
GetExtensionKeys
(
self
,
extensionName
):
def
GetExtensionKeys
(
self
,
extensionName
):
"""
"""Return dict: {configurable extensionName event : active keybinding}.
returns a dictionary of the configurable keybindings for a particular
extension,as they exist in the dictionary returned by GetCurrentKeySet;
Events come from default config extension_cfgBindings section.
that is, where previously used bindings are disabled.
Keybindings come from GetCurrentKeySet() active key dict,
where previously used bindings are disabled.
"""
"""
keysName
=
extensionName
+
'_cfgBindings'
keysName
=
extensionName
+
'_cfgBindings'
activeKeys
=
self
.
GetCurrentKeySet
()
activeKeys
=
self
.
GetCurrentKeySet
()
extKeys
=
{}
extKeys
=
{}
if
self
.
defaultCfg
[
'extensions'
].
has_section
(
keysName
):
if
self
.
defaultCfg
[
'extensions'
].
has_section
(
keysName
):
eventNames
=
self
.
defaultCfg
[
'extensions'
].
GetOptionList
(
keysName
)
eventNames
=
self
.
defaultCfg
[
'extensions'
].
GetOptionList
(
keysName
)
for
eventName
in
eventNames
:
for
eventName
in
eventNames
:
event
=
'<<'
+
eventName
+
'>>'
event
=
'<<'
+
eventName
+
'>>'
binding
=
activeKeys
[
event
]
binding
=
activeKeys
[
event
]
extKeys
[
event
]
=
binding
extKeys
[
event
]
=
binding
return
extKeys
return
extKeys
def
__GetRawExtensionKeys
(
self
,
extensionName
):
def
__GetRawExtensionKeys
(
self
,
extensionName
):
"""Return dict {configurable extensionName event : keybinding list}.
Events come from default config extension_cfgBindings section.
Keybindings list come from the splitting of GetOption, which
tries user config before default config.
"""
"""
returns a dictionary of the configurable keybindings for a particular
keysName
=
extensionName
+
'_cfgBindings'
extension, as defined in the configuration files, or an empty dictionary
extKeys
=
{}
if no bindings are found
"""
keysName
=
extensionName
+
'_cfgBindings'
extKeys
=
{}
if
self
.
defaultCfg
[
'extensions'
].
has_section
(
keysName
):
if
self
.
defaultCfg
[
'extensions'
].
has_section
(
keysName
):
eventNames
=
self
.
defaultCfg
[
'extensions'
].
GetOptionList
(
keysName
)
eventNames
=
self
.
defaultCfg
[
'extensions'
].
GetOptionList
(
keysName
)
for
eventName
in
eventNames
:
for
eventName
in
eventNames
:
binding
=
self
.
GetOption
(
'extensions'
,
keysName
,
binding
=
self
.
GetOption
(
eventName
,
default
=
''
).
split
()
'extensions'
,
keysName
,
eventName
,
default
=
''
).
split
()
event
=
'<<'
+
eventName
+
'>>'
event
=
'<<'
+
eventName
+
'>>'
extKeys
[
event
]
=
binding
extKeys
[
event
]
=
binding
return
extKeys
return
extKeys
def
GetExtensionBindings
(
self
,
extensionName
):
def
GetExtensionBindings
(
self
,
extensionName
):
"""
"""
Return dict {extensionName event : active or defined keybinding}.
Returns a dictionary of all the event bindings for a particular
extension. The configurable keybindings are returned as they exist in
Augment self.GetExtensionKeys(extensionName) with mapping of non-
the dictionary returned by GetCurrentKeySet; that is, where re-used
configurable events (from default config) to GetOption splits,
keybindings are disabled
.
as in self.__GetRawExtensionKeys
.
"""
"""
bindsName
=
extensionName
+
'_bindings'
bindsName
=
extensionName
+
'_bindings'
extBinds
=
self
.
GetExtensionKeys
(
extensionName
)
extBinds
=
self
.
GetExtensionKeys
(
extensionName
)
#add the non-configurable bindings
#add the non-configurable bindings
if
self
.
defaultCfg
[
'extensions'
].
has_section
(
bindsName
):
if
self
.
defaultCfg
[
'extensions'
].
has_section
(
bindsName
):
eventNames
=
self
.
defaultCfg
[
'extensions'
].
GetOptionList
(
bindsName
)
eventNames
=
self
.
defaultCfg
[
'extensions'
].
GetOptionList
(
bindsName
)
for
eventName
in
eventNames
:
for
eventName
in
eventNames
:
binding
=
self
.
GetOption
(
'extensions'
,
bindsName
,
binding
=
self
.
GetOption
(
eventName
,
default
=
''
).
split
()
'extensions'
,
bindsName
,
eventName
,
default
=
''
).
split
()
event
=
'<<'
+
eventName
+
'>>'
event
=
'<<'
+
eventName
+
'>>'
extBinds
[
event
]
=
binding
extBinds
[
event
]
=
binding
return
extBinds
return
extBinds
def
GetKeyBinding
(
self
,
keySetName
,
eventStr
):
def
GetKeyBinding
(
self
,
keySetName
,
eventStr
):
"""Return the keybinding list for keySetName eventStr.
keySetName - name of key binding set (config-keys section).
eventStr - virtual event, including brackets, as in '<<event>>'.
"""
"""
returns the keybinding for a specific event.
eventName
=
eventStr
[
2
:
-
2
]
#trim off the angle brackets
keySetName - string, name of key binding set
binding
=
self
.
GetOption
(
'keys'
,
keySetName
,
eventName
,
default
=
''
).
split
()
eventStr - string, the virtual event we want the binding for,
represented as a string, eg. '<<event>>'
"""
eventName
=
eventStr
[
2
:
-
2
]
#trim off the angle brackets
binding
=
self
.
GetOption
(
'keys'
,
keySetName
,
eventName
,
default
=
''
).
split
()
return
binding
return
binding
def
GetCurrentKeySet
(
self
):
def
GetCurrentKeySet
(
self
):
"Return CurrentKeys with 'darwin' modifications."
result
=
self
.
GetKeySet
(
self
.
CurrentKeys
())
result
=
self
.
GetKeySet
(
self
.
CurrentKeys
())
if
sys
.
platform
==
"darwin"
:
if
sys
.
platform
==
"darwin"
:
# OS X Tk variants do not support the "Alt" keyboard modifier.
# OS X Tk variants do not support the "Alt" keyboard modifier.
# So replace all keybingings that use "Alt" with ones that
# So replace all keybingings that use "Alt" with ones that
# use the "Option" keyboard modifier.
# use the "Option" keyboard modifier.
# TO
DO
: the "Option" modifier does not work properly for
# TO
DO (Ned?)
: the "Option" modifier does not work properly for
# Cocoa Tk and XQuartz Tk so we should not use it
# Cocoa Tk and XQuartz Tk so we should not use it
# in default OS X KeySets.
# in default OS X KeySets.
for
k
,
v
in
result
.
items
():
for
k
,
v
in
result
.
items
():
...
@@ -540,40 +518,43 @@ class IdleConf:
...
@@ -540,40 +518,43 @@ class IdleConf:
return
result
return
result
def
GetKeySet
(
self
,
keySetName
):
def
GetKeySet
(
self
,
keySetName
):
"""
"""
Return event-key dict for keySetName core plus active extensions.
Returns a dictionary of: all requested core keybindings, plus the
keybindings for all currently active extensions. If a binding defined
If a binding defined in an extension is already in use, the
in an extension is already in use, that binding is disabled.
extension binding is disabled by being set to ''
"""
"""
keySet
=
self
.
GetCoreKeys
(
keySetName
)
keySet
=
self
.
GetCoreKeys
(
keySetName
)
activeExtns
=
self
.
GetExtensions
(
active_only
=
1
)
activeExtns
=
self
.
GetExtensions
(
active_only
=
1
)
for
extn
in
activeExtns
:
for
extn
in
activeExtns
:
extKeys
=
self
.
__GetRawExtensionKeys
(
extn
)
extKeys
=
self
.
__GetRawExtensionKeys
(
extn
)
if
extKeys
:
#the extension defines keybindings
if
extKeys
:
#the extension defines keybindings
for
event
in
extKeys
:
for
event
in
extKeys
:
if
extKeys
[
event
]
in
keySet
.
values
():
if
extKeys
[
event
]
in
keySet
.
values
():
#the binding is already in use
#the binding is already in use
extKeys
[
event
]
=
''
#disable this binding
extKeys
[
event
]
=
''
#disable this binding
keySet
[
event
]
=
extKeys
[
event
]
#add binding
keySet
[
event
]
=
extKeys
[
event
]
#add binding
return
keySet
return
keySet
def
IsCoreBinding
(
self
,
virtualEvent
):
def
IsCoreBinding
(
self
,
virtualEvent
):
"""
"""
Return True if the virtual event is one of the core idle key events.
returns true if the virtual event is bound in the core idle keybindings.
virtualEvent - string, name of the virtual event to test for,
without
virtualEvent - string, name of the virtual event to test for,
the enclosing '<< >>'
without
the enclosing '<< >>'
"""
"""
return
(
'<<'
+
virtualEvent
+
'>>'
)
in
self
.
GetCoreKeys
()
return
(
'<<'
+
virtualEvent
+
'>>'
)
in
self
.
GetCoreKeys
()
# TODO make keyBindins a file or class attribute used for test above
# and copied in function below
def
GetCoreKeys
(
self
,
keySetName
=
None
):
def
GetCoreKeys
(
self
,
keySetName
=
None
):
"""
"""
Return dict of core virtual-key keybindings for keySetName.
returns the requested set of core keybindings, with fallbacks if
required.
The default keySetName None corresponds to the keyBindings base
Keybindings loaded from the config file(s) are loaded _over_ these
dict. If keySetName is not None, bindings from the config
defaults, so if there is a problem getting any core binding there will
file(s) are loaded _over_ these defaults, so if there is a
be an 'ultimate last resort fallback' to the CUA-ish bindings
problem getting any core binding there will be an 'ultimate last
defined here.
resort fallback' to the CUA-ish bindings
defined here.
"""
"""
keyBindings
=
{
keyBindings
=
{
'<<copy>>'
:
[
'<Control-c>'
,
'<Control-C>'
],
'<<copy>>'
:
[
'<Control-c>'
,
'<Control-C>'
],
...
@@ -628,9 +609,9 @@ class IdleConf:
...
@@ -628,9 +609,9 @@ class IdleConf:
}
}
if
keySetName
:
if
keySetName
:
for
event
in
keyBindings
:
for
event
in
keyBindings
:
binding
=
self
.
GetKeyBinding
(
keySetName
,
event
)
binding
=
self
.
GetKeyBinding
(
keySetName
,
event
)
if
binding
:
if
binding
:
keyBindings
[
event
]
=
binding
keyBindings
[
event
]
=
binding
else
:
#we are going to return a default, print warning
else
:
#we are going to return a default, print warning
warning
=
(
'
\
n
Warning: configHandler.py - IdleConf.GetCoreKeys'
warning
=
(
'
\
n
Warning: configHandler.py - IdleConf.GetCoreKeys'
' -
\
n
problem retrieving key binding for event %r'
' -
\
n
problem retrieving key binding for event %r'
...
@@ -643,8 +624,8 @@ class IdleConf:
...
@@ -643,8 +624,8 @@ class IdleConf:
pass
pass
return
keyBindings
return
keyBindings
def
GetExtraHelpSourceList
(
self
,
configSet
):
def
GetExtraHelpSourceList
(
self
,
configSet
):
"""
Fetch
list of extra help sources from a given configSet.
"""
Return
list of extra help sources from a given configSet.
Valid configSets are 'user' or 'default'. Return a list of tuples of
Valid configSets are 'user' or 'default'. Return a list of tuples of
the form (menu_item , path_to_help_file , option), or return the empty
the form (menu_item , path_to_help_file , option), or return the empty
...
@@ -653,19 +634,19 @@ class IdleConf:
...
@@ -653,19 +634,19 @@ class IdleConf:
therefore the returned list must be sorted by 'option'.
therefore the returned list must be sorted by 'option'.
"""
"""
helpSources
=
[]
helpSources
=
[]
if
configSet
==
'user'
:
if
configSet
==
'user'
:
cfgParser
=
self
.
userCfg
[
'main'
]
cfgParser
=
self
.
userCfg
[
'main'
]
elif
configSet
==
'default'
:
elif
configSet
==
'default'
:
cfgParser
=
self
.
defaultCfg
[
'main'
]
cfgParser
=
self
.
defaultCfg
[
'main'
]
else
:
else
:
raise
InvalidConfigSet
(
'Invalid configSet specified'
)
raise
InvalidConfigSet
(
'Invalid configSet specified'
)
options
=
cfgParser
.
GetOptionList
(
'HelpFiles'
)
options
=
cfgParser
.
GetOptionList
(
'HelpFiles'
)
for
option
in
options
:
for
option
in
options
:
value
=
cfgParser
.
Get
(
'HelpFiles'
,
option
,
default
=
';'
)
value
=
cfgParser
.
Get
(
'HelpFiles'
,
option
,
default
=
';'
)
if
value
.
find
(
';'
)
==
-
1
:
#malformed config entry with no ';'
if
value
.
find
(
';'
)
==
-
1
:
#malformed config entry with no ';'
menuItem
=
''
#make these empty
menuItem
=
''
#make these empty
helpPath
=
''
#so value won't be added to list
helpPath
=
''
#so value won't be added to list
else
:
#config entry contains ';' as expected
else
:
#config entry contains ';' as expected
value
=
value
.
split
(
';'
)
value
=
value
.
split
(
';'
)
menuItem
=
value
[
0
].
strip
()
menuItem
=
value
[
0
].
strip
()
...
@@ -676,47 +657,44 @@ class IdleConf:
...
@@ -676,47 +657,44 @@ class IdleConf:
return
helpSources
return
helpSources
def
GetAllExtraHelpSourcesList
(
self
):
def
GetAllExtraHelpSourcesList
(
self
):
"""Return a list of the details of all additional help sources.
Tuples in the list are those of GetExtraHelpSourceList.
"""
"""
Returns a list of tuples containing the details of all additional help
allHelpSources
=
(
self
.
GetExtraHelpSourceList
(
'default'
)
+
sources configured, or an empty list if there are none. Tuples are of
the format returned by GetExtraHelpSourceList.
"""
allHelpSources
=
(
self
.
GetExtraHelpSourceList
(
'default'
)
+
self
.
GetExtraHelpSourceList
(
'user'
)
)
self
.
GetExtraHelpSourceList
(
'user'
)
)
return
allHelpSources
return
allHelpSources
def
LoadCfgFiles
(
self
):
def
LoadCfgFiles
(
self
):
"""
"Load all configuration files."
load all configuration files.
"""
for
key
in
self
.
defaultCfg
:
for
key
in
self
.
defaultCfg
:
self
.
defaultCfg
[
key
].
Load
()
self
.
defaultCfg
[
key
].
Load
()
self
.
userCfg
[
key
].
Load
()
#same keys
self
.
userCfg
[
key
].
Load
()
#same keys
def
SaveUserCfgFiles
(
self
):
def
SaveUserCfgFiles
(
self
):
"""
"Write all loaded user configuration files to disk."
write all loaded user configuration files back to disk
"""
for
key
in
self
.
userCfg
:
for
key
in
self
.
userCfg
:
self
.
userCfg
[
key
].
Save
()
self
.
userCfg
[
key
].
Save
()
idleConf
=
IdleConf
()
idleConf
=
IdleConf
()
# TODO Revise test output, write expanded unittest
### module test
### module test
if
__name__
==
'__main__'
:
if
__name__
==
'__main__'
:
def
dumpCfg
(
cfg
):
def
dumpCfg
(
cfg
):
print
(
'
\
n
'
,
cfg
,
'
\
n
'
)
print
(
'
\
n
'
,
cfg
,
'
\
n
'
)
for
key
in
cfg
:
for
key
in
cfg
:
sections
=
cfg
[
key
].
sections
()
sections
=
cfg
[
key
].
sections
()
print
(
key
)
print
(
key
)
print
(
sections
)
print
(
sections
)
for
section
in
sections
:
for
section
in
sections
:
options
=
cfg
[
key
].
options
(
section
)
options
=
cfg
[
key
].
options
(
section
)
print
(
section
)
print
(
section
)
print
(
options
)
print
(
options
)
for
option
in
options
:
for
option
in
options
:
print
(
option
,
'='
,
cfg
[
key
].
Get
(
section
,
option
))
print
(
option
,
'='
,
cfg
[
key
].
Get
(
section
,
option
))
dumpCfg
(
idleConf
.
defaultCfg
)
dumpCfg
(
idleConf
.
defaultCfg
)
dumpCfg
(
idleConf
.
userCfg
)
dumpCfg
(
idleConf
.
userCfg
)
print
(
idleConf
.
userCfg
[
'main'
].
Get
(
'Theme'
,
'name'
))
print
(
idleConf
.
userCfg
[
'main'
].
Get
(
'Theme'
,
'name'
))
#print idleConf.userCfg['highlight'].GetDefHighlight('Foo','normal')
#print idleConf.userCfg['highlight'].GetDefHighlight('Foo','normal')
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment