Files

202 lines
6.1 KiB
Python
Raw Permalink Normal View History

'''
This file is part of the PyPhantomJS project.
Copyright (C) 2011 James Roe <roejames12@hotmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
2011-09-23 04:40:56 -07:00
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
2011-09-23 04:40:56 -07:00
along with this program. If not, see <http://www.gnu.org/licenses/>.
'''
import os
2011-06-21 10:44:55 -07:00
import sys
from collections import defaultdict
2011-09-15 17:18:08 -07:00
from glob import glob
2011-06-03 21:15:59 -07:00
2011-06-26 18:09:53 -07:00
hooks = defaultdict(dict)
2011-05-31 16:23:06 -07:00
def createHook(func):
'''Decorator that will create a hook if the hook doesn't exist'''
def innerWrap(*args, **kwargs):
if args[0] not in hooks:
hooks[args[0]]['count'] = 0
hooks[args[0]]['plugins'] = []
return func(*args, **kwargs)
return innerWrap
2011-09-18 02:58:43 -07:00
def checkHookExists(func):
'''Decorator that will raise LookupError if the hook doesn't exist'''
def innerWrap(*args, **kwargs):
if args[0] not in hooks:
raise LookupError("Hook '%s' was not found" % args[0])
return func(*args, **kwargs)
return innerWrap
@createHook
2011-06-26 18:09:53 -07:00
def add_action(hook, priority=10):
'''Decorator to be used for registering a function to
a specific hook. Functions with lower priority are
executed first (priority of 1 for example).
'''
def register(func):
2011-09-18 02:58:43 -07:00
hooks[hook]['plugins'].append((priority, func))
return func
return register
2011-05-31 16:23:06 -07:00
@checkHookExists
def did_action(hook):
'''Find out how many times a hook was fired'''
2011-06-26 18:09:53 -07:00
return hooks[hook]['count']
2011-05-31 16:23:06 -07:00
@createHook
def do_action(hook, *args, **kwargs):
2011-06-26 18:09:53 -07:00
'''Trigger a hook. It will run any functions that have registered
themselves to the hook. Any additional arguments or keyword
arguments you pass in will be passed to the functions.
'''
2011-09-18 02:58:43 -07:00
# sort plugins by priority
hooks[hook]['plugins'].sort()
for plugin in hooks[hook]['plugins']:
hooks[hook]['count'] += 1
plugin[1](*args, **kwargs)
2011-05-31 16:23:06 -07:00
2011-09-18 02:58:43 -07:00
def get(name, depth=4, scope='local'):
2011-07-04 02:37:18 -07:00
'''Gets the value of a variable in the parents namespace
Args:
depth controls how deep to go into the stack
scope controls the namespace used; valid values are: local,global,builtin
'''
if scope == 'local':
scope = 'f_locals'
elif scope == 'global':
scope = 'f_globals'
elif scope == 'builtin':
scope = 'f_builtins'
return getattr(sys._getframe(depth), scope)[name]
2011-07-04 02:37:18 -07:00
2011-05-31 16:23:06 -07:00
def has_action(hook, func=None):
'''Check if hook exists. If function is specified,
check if function has been registered for hook.
'''
2011-09-18 02:58:43 -07:00
if func is None:
if hook in hooks:
2011-05-31 16:23:06 -07:00
return True
2011-09-18 02:58:43 -07:00
else:
if hook not in hooks:
raise LookupError("Hook '%s' was not found" % hook)
for plugin in hooks[hook]['plugins']:
2011-12-11 22:59:50 -08:00
if plugin[1] is func:
2011-09-18 02:58:43 -07:00
return True
return False
2011-05-31 16:23:06 -07:00
2011-06-26 18:09:53 -07:00
def remove_action(hook, func=None, priority=10):
2011-05-31 16:23:06 -07:00
'''Remove hook if hook exists. If function is specified,
2011-06-26 18:09:53 -07:00
remove function from hook. If priority is not same as
functions priority, it will not remove the function.
2011-05-31 16:23:06 -07:00
'''
2011-09-18 02:58:43 -07:00
if func is None:
if hook in hooks:
2011-06-26 18:09:53 -07:00
del hooks[hook]
2011-05-31 16:23:06 -07:00
return True
2011-09-18 02:58:43 -07:00
else:
if hook not in hooks:
raise LookupError("Hook '%s' was not found" % hook)
for i, plugin in enumerate(hooks[hook]['plugins']):
2011-12-11 22:59:50 -08:00
if plugin[1] is func and plugin[0] == priority:
2011-09-18 02:58:43 -07:00
del hooks[hook]['plugins'][i]
return True
return False
2011-05-31 16:23:06 -07:00
@checkHookExists
2011-06-26 18:09:53 -07:00
def remove_all_actions(hook, priority=None):
'''Remove all functions that have been registered to hook.
If priority is used, remove all actions from that priority
instead.
'''
2011-09-18 02:58:43 -07:00
if priority is None:
del hooks[hook][:]
else:
indexes = []
for i, plugin in enumerate(hooks[hook]['plugins']):
if plugin[0] == priority:
indexes.append(i)
for index in indexes:
del hooks[hook]['plugins'][index]
2011-05-31 16:23:06 -07:00
2011-09-18 02:58:43 -07:00
def set_(name, value, depth=4, scope='local'):
2011-07-04 02:37:18 -07:00
'''Sets the value of a variable in the parents namespace
Args:
depth controls how deep to go into the stack
scope controls the namespace used; valid values are: local,global,builtin
'''
if scope == 'local':
scope = 'f_locals'
elif scope == 'global':
scope = 'f_globals'
elif scope == 'builtin':
scope = 'f_builtins'
getattr(sys._getframe(depth), scope)[name] = value
def load_plugins():
''' Loads the plugins.
Plugins must be in folders under plugins/ (or plugins_path),
and must also be the same name as the plugin folder.
E.g. a plugin folder named my_plugin will
have my_plugin.py inside the folder loaded.
'''
plugins_path = os.environ.get('PYPHANTOMJS_PLUGINS_PATH')
if plugins_path is None:
# path is different when frozen
if hasattr(sys, 'frozen'):
plugins_path = os.path.dirname(os.path.abspath(sys.executable))
else:
plugins_path = os.path.dirname(os.path.abspath(__file__))
plugins_path = os.path.join(plugins_path, 'plugins')
2011-06-21 10:44:55 -07:00
else:
# make sure it's an absolute path
plugins_path = os.path.abspath(plugins_path)
sys.path.insert(1, plugins_path)
plugin_list = glob(os.path.join(plugins_path, '*/*.py'))
# now convert list to [('plugin_folder', 'file'), ...]
plugin_list = [(os.path.split(os.path.dirname(f))[1], os.path.splitext(os.path.split(f)[1])[0]) for f in plugin_list]
# initialize plugins
for plugin in plugin_list:
if plugin[0] == plugin[1]:
moduleName = '.'.join((plugin[0], plugin[1]))
__import__(moduleName, globals(), locals(), [], -1)