diff options
Diffstat (limited to 'testing/mozbase/mozprofile/mozprofile/cli.py')
-rwxr-xr-x | testing/mozbase/mozprofile/mozprofile/cli.py | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/testing/mozbase/mozprofile/mozprofile/cli.py b/testing/mozbase/mozprofile/mozprofile/cli.py new file mode 100755 index 0000000000..7addb1165d --- /dev/null +++ b/testing/mozbase/mozprofile/mozprofile/cli.py @@ -0,0 +1,204 @@ +#!/usr/bin/env python + +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this file, +# You can obtain one at http://mozilla.org/MPL/2.0/. + +""" +Creates and/or modifies a Firefox profile. +The profile can be modified by passing in addons to install or preferences to set. +If no profile is specified, a new profile is created and the path of the +resulting profile is printed. +""" +import sys +from optparse import OptionParser + +from .prefs import Preferences +from .profile import FirefoxProfile, Profile + +__all__ = [ + "MozProfileCLI", + "cli", + "KeyValueParseError", + "parse_key_value", + "parse_preferences", +] + + +class KeyValueParseError(Exception): + """Error when parsing strings of serialized key-values.""" + + def __init__(self, msg, errors=()): + self.errors = errors + Exception.__init__(self, msg) + + +def parse_key_value(strings, separator="=", context="key, value"): + """Parse string-serialized key-value pairs in the form of `key = value`. + + Args: + strings (list): List of strings to parse. + separator (str): Identifier used to split the strings. + + Returns: + list: A list of (<key>, <value>) tuples. Whitespace is not stripped. + + Raises: + KeyValueParseError + """ + + # syntax check + missing = [string for string in strings if separator not in string] + if missing: + raise KeyValueParseError( + "Error: syntax error in %s: %s" % (context, ",".join(missing)), + errors=missing, + ) + return [string.split(separator, 1) for string in strings] + + +def parse_preferences(prefs, context="--setpref="): + """Parse preferences specified on the command line. + + Args: + prefs (list): A list of strings, usually of the form "<pref>=<value>". + + Returns: + dict: A dictionary of the form {<pref>: <value>} where values have been + cast. + """ + try: + prefs = dict(parse_key_value(prefs, context=context)) + except KeyValueParseError as e: + print(str(e)) + sys.exit(1) + + return {k: Preferences.cast(v) for k, v in prefs.items()} + + +class MozProfileCLI(object): + """The Command Line Interface for ``mozprofile``.""" + + module = "mozprofile" + profile_class = Profile + + def __init__(self, args=sys.argv[1:], add_options=None): + self.parser = OptionParser(description=__doc__) + self.add_options(self.parser) + if add_options: + add_options(self.parser) + (self.options, self.args) = self.parser.parse_args(args) + + def add_options(self, parser): + + parser.add_option( + "-p", + "--profile", + dest="profile", + help="The path to the profile to operate on. " + "If none, creates a new profile in temp directory", + ) + parser.add_option( + "-a", + "--addon", + dest="addons", + action="append", + default=[], + help="Addon paths to install. Can be a filepath, " + "a directory containing addons, or a url", + ) + parser.add_option( + "--pref", + dest="prefs", + action="append", + default=[], + help="A preference to set. " "Must be a key-value pair separated by a ':'", + ) + parser.add_option( + "--preferences", + dest="prefs_files", + action="append", + default=[], + metavar="FILE", + help="read preferences from a JSON or INI file. " + "For INI, use 'file.ini:section' to specify a particular section.", + ) + + def profile_args(self): + """arguments to instantiate the profile class""" + return dict( + profile=self.options.profile, + addons=self.options.addons, + preferences=self.preferences(), + ) + + def preferences(self): + """profile preferences""" + + # object to hold preferences + prefs = Preferences() + + # add preferences files + for prefs_file in self.options.prefs_files: + prefs.add_file(prefs_file) + + # change CLI preferences into 2-tuples + cli_prefs = parse_key_value(self.options.prefs, separator=":") + + # string preferences + prefs.add(cli_prefs, cast=True) + + return prefs() + + def profile(self, restore=False): + """create the profile""" + + kwargs = self.profile_args() + kwargs["restore"] = restore + return self.profile_class(**kwargs) + + +def cli(args=sys.argv[1:]): + """Handles the command line arguments for ``mozprofile`` via ``sys.argv``""" + + # add a view method for this cli method only + def add_options(parser): + parser.add_option( + "--view", + dest="view", + action="store_true", + default=False, + help="view summary of profile following invocation", + ) + parser.add_option( + "--firefox", + dest="firefox_profile", + action="store_true", + default=False, + help="use FirefoxProfile defaults", + ) + + # process the command line + cli = MozProfileCLI(args, add_options) + + if cli.args: + cli.parser.error("Program doesn't support positional arguments.") + + if cli.options.firefox_profile: + cli.profile_class = FirefoxProfile + + # create the profile + profile = cli.profile() + + if cli.options.view: + # view the profile, if specified + print(profile.summary()) + return + + # if no profile was passed in print the newly created profile + if not cli.options.profile: + print(profile.profile) + + +if __name__ == "__main__": + cli() |