Example #1
0
class Bool(Setting):
    schema = Schema(bool)
    true_words = frozenset(["1", "true", "yes", "y", "on"])
    false_words = frozenset(["0", "false", "no", "n", "off"])
    all_words = true_words | false_words

    def _parse_env_var(self, value):
        value = value.lower()
        if value in self.true_words:
            return True
        elif value in self.false_words:
            return False
        else:
            raise ConfigurationError(
                "Expected $%s to be one of: %s" %
                (self._env_var_name, ", ".join(self.all_words)))
Example #2
0
class PipInstallRemaps(Setting):
    """Ordered, pip install remappings."""
    PARDIR, SEP = map(re.escape, (os.pardir, os.sep))
    RE_TOKENS = {'sep': SEP, 's': SEP, 'pardir': PARDIR, 'p': PARDIR}
    TOKENS = {'sep': os.sep, 's': os.sep, 'pardir': os.pardir, 'p': os.pardir}
    KEYS = ["record_path", "pip_install", "rez_install"]

    schema = Schema([{key: And(str, len) for key in KEYS}])

    def validate(self, data):
        """Extended to substitute regex-escaped path tokens."""
        return [{
            key: expression.format(
                **(self.RE_TOKENS if key == "record_path" else self.TOKENS))
            for key, expression in remap.items()
        } for remap in super(PipInstallRemaps, self).validate(data)]
    def __init__(self, context_model=None, attributes=None, parent=None):
        """
        Args:
            attributes (list of str): Select only certain settings to expose. If
                None, all settings are exposed.
        """
        super(ContextSettingsWidget, self).__init__(parent)
        ContextViewMixin.__init__(self, context_model)

        self.schema_keys = set(self.schema_dict.iterkeys())
        if attributes:
            self.schema_keys &= set(attributes)
            assert self.schema_keys

        schema_dict = dict((k, v) for k, v in self.schema_dict.iteritems()
                           if k in self.schema_keys)
        self.schema = Schema(schema_dict)

        self.edit = QtGui.QTextEdit()
        self.edit.setStyleSheet("font: 9pt 'Courier'")
        self.default_btn = QtGui.QPushButton("Set To Defaults")
        self.discard_btn = QtGui.QPushButton("Discard Changes...")
        self.apply_btn = QtGui.QPushButton("Apply")
        self.discard_btn.setEnabled(False)
        self.apply_btn.setEnabled(False)
        btn_pane = create_pane([None, self.default_btn, self.discard_btn,
                                self.apply_btn], True)

        layout = QtGui.QVBoxLayout()
        layout.addWidget(self.edit)
        layout.addWidget(btn_pane)
        self.setLayout(layout)

        self.apply_btn.clicked.connect(self.apply_changes)
        self.default_btn.clicked.connect(self.set_defaults)
        self.discard_btn.clicked.connect(partial(self.discard_changes, True))
        self.edit.textChanged.connect(self._settingsChanged)

        self._update_text()
Example #4
0
config_schema = Schema({
    "packages_path": PathList,
    "plugin_path": PathList,
    "bind_module_path": PathList,
    "standard_system_paths": PathList,
    "package_definition_build_python_paths": PathList,
    "platform_map": OptionalDict,
    "default_relocatable_per_package": OptionalDict,
    "default_relocatable_per_repository": OptionalDict,
    "default_cachable_per_package": OptionalDict,
    "default_cachable_per_repository": OptionalDict,
    "default_cachable": OptionalBool,
    "implicit_packages": StrList,
    "parent_variables": StrList,
    "resetting_variables": StrList,
    "release_hooks": StrList,
    "context_tracking_context_fields": StrList,
    "prompt_release_message": Bool,
    "critical_styles": OptionalStrList,
    "error_styles": OptionalStrList,
    "warning_styles": OptionalStrList,
    "info_styles": OptionalStrList,
    "debug_styles": OptionalStrList,
    "heading_styles": OptionalStrList,
    "local_styles": OptionalStrList,
    "implicit_styles": OptionalStrList,
    "ephemeral_styles": OptionalStrList,
    "alias_styles": OptionalStrList,
    "memcached_uri": OptionalStrList,
    "pip_extra_args": OptionalStrList,
    "pip_install_remaps": PipInstallRemaps,
    "local_packages_path": Str,
    "release_packages_path": Str,
    "dot_image_format": Str,
    "build_directory": Str,
    "documentation_url": Str,
    "suite_visibility": SuiteVisibility_,
    "rez_tools_visibility": RezToolsVisibility_,
    "create_executable_script_mode": ExecutableScriptMode_,
    "suite_alias_prefix_char": Char,
    "cache_packages_path": OptionalStr,
    "package_definition_python_path": OptionalStr,
    "tmpdir": OptionalStr,
    "context_tmpdir": OptionalStr,
    "default_shell": OptionalStr,
    "terminal_emulator_command": OptionalStr,
    "editor": OptionalStr,
    "image_viewer": OptionalStr,
    "difftool": OptionalStr,
    "browser": OptionalStr,
    "critical_fore": OptionalStr,
    "critical_back": OptionalStr,
    "error_fore": OptionalStr,
    "error_back": OptionalStr,
    "warning_fore": OptionalStr,
    "warning_back": OptionalStr,
    "info_fore": OptionalStr,
    "info_back": OptionalStr,
    "debug_fore": OptionalStr,
    "debug_back": OptionalStr,
    "heading_fore": OptionalStr,
    "heading_back": OptionalStr,
    "local_fore": OptionalStr,
    "local_back": OptionalStr,
    "implicit_fore": OptionalStr,
    "implicit_back": OptionalStr,
    "ephemeral_fore": OptionalStr,
    "ephemeral_back": OptionalStr,
    "alias_fore": OptionalStr,
    "alias_back": OptionalStr,
    "package_preprocess_function": OptionalStrOrFunction,
    "package_preprocess_mode": PreprocessMode_,
    "context_tracking_host": OptionalStr,
    "variant_shortlinks_dirname": OptionalStr,
    "build_thread_count": BuildThreadCount_,
    "resource_caching_maxsize": Int,
    "max_package_changelog_chars": Int,
    "max_package_changelog_revisions": Int,
    "memcached_package_file_min_compress_len": Int,
    "memcached_context_file_min_compress_len": Int,
    "memcached_listdir_min_compress_len": Int,
    "memcached_resolve_min_compress_len": Int,
    "shell_error_truncate_cap": Int,
    "package_cache_log_days": Int,
    "package_cache_max_variant_days": Int,
    "package_cache_clean_limit": Float,
    "allow_unversioned_packages": Bool,
    "rxt_as_yaml": Bool,
    "package_cache_during_build": Bool,
    "package_cache_local": Bool,
    "package_cache_same_device": Bool,
    "color_enabled": ForceOrBool,
    "resolve_caching": Bool,
    "cache_package_files": Bool,
    "cache_listdir": Bool,
    "prune_failed_graph": Bool,
    "all_parent_variables": Bool,
    "all_resetting_variables": Bool,
    "package_commands_sourced_first": Bool,
    "use_variant_shortlinks": Bool,
    "warn_shell_startup": Bool,
    "warn_untimestamped": Bool,
    "warn_all": Bool,
    "warn_none": Bool,
    "debug_file_loads": Bool,
    "debug_plugins": Bool,
    "debug_package_release": Bool,
    "debug_bind_modules": Bool,
    "debug_resources": Bool,
    "debug_package_exclusions": Bool,
    "debug_memcache": Bool,
    "debug_resolve_memcache": Bool,
    "debug_all": Bool,
    "debug_none": Bool,
    "quiet": Bool,
    "show_progress": Bool,
    "catch_rex_errors": Bool,
    "default_relocatable": Bool,
    "set_prompt": Bool,
    "prefix_prompt": Bool,
    "warn_old_commands": Bool,
    "error_old_commands": Bool,
    "debug_old_commands": Bool,
    "warn_commands2": Bool,
    "error_commands2": Bool,
    "rez_1_environment_variables": Bool,
    "rez_1_cmake_variables": Bool,
    "disable_rez_1_compatibility": Bool,
    "make_package_temporarily_writable": Bool,
    "read_package_cache": Bool,
    "write_package_cache": Bool,
    "env_var_separators": Dict,
    "variant_select_mode": VariantSelectMode_,
    "package_filter": OptionalDictOrDictList,
    "package_orderers": OptionalDictOrDictList,
    "new_session_popen_args": OptionalDict,
    "context_tracking_amqp": OptionalDict,
    "context_tracking_extra_fields": OptionalDict,

    # GUI settings
    "use_pyside": Bool,
    "use_pyqt": Bool,
    "gui_threads": Bool
})
Example #5
0
# database or filesystem.
pets = dict(
    kitten=dict(obi=dict(colors=["black", "white"], male=True, age=1.0),
                scully=dict(colors=["tabby"], male=False, age=0.5),
                mordor=dict(colors=["black"], male=True,
                            age="infinite")),  # bad data
    puppy=dict(taco=dict(colors=["brown"],
                         male=True,
                         age=0.6,
                         owner="joe.bloggs"),
               ringo=dict(colors=["white", "grey"], male=True, age=0.8)))

pet_schema = Schema({
    Required("name"): basestring,
    Required("colors"): And([basestring], Use(set)),
    Required("male"): bool,
    Required("age"): float,
    Optional("owner"): basestring
})


class BasePetResource(Resource):
    schema_error = PetResourceError

    def __init__(self, variables=None):
        super(BasePetResource, self).__init__(variables)
        self.validations = {}

    # tracks validations
    def _validate_key(self, key, attr, key_schema):
        self.validations[key] = self.validations.get(key, 0) + 1
Example #6
0
from rez.vendor.version.version import Version
from contextlib import contextmanager
import os


# this schema will automatically harden request strings like 'python-*'; see
# the 'expand_requires' function for more info.
#
package_request_schema = Or(And(basestring, Use(expand_requirement)),
                            And(PackageRequest, Use(str)))

tests_schema = Schema({
    Optional(basestring): Or(
        Or(basestring, [basestring]),
        {
            "command": Or(basestring, [basestring]),
            Optional("requires"): [package_request_schema]
        }
    )
})


package_schema = Schema({
    Optional("requires_rez_version"):   And(basestring, Use(Version)),

    Required("name"):                   basestring,
    Optional("base"):                   basestring,
    Optional("version"):                Or(basestring,
                                           And(Version, Use(str))),
    Optional('description'):            basestring,
    Optional('authors'):                [basestring],
Example #7
0
#------------------------------------------------------------------------------
# utility schemas
#------------------------------------------------------------------------------

help_schema = Or(basestring,  # single help entry
                 [[basestring]])  # multiple help entries

_is_late = And(SourceCode, lambda x: hasattr(x, "_late"))

def late_bound(schema):
    return Or(SourceCode, schema)

# used when 'requires' is late bound
late_requires_schema = Schema([
    Or(PackageRequest, And(basestring, Use(PackageRequest)))
])


#------------------------------------------------------------------------------
# schema dicts
#------------------------------------------------------------------------------

# requirements of all package-related resources
#

base_resource_schema_dict = {
    Required("name"):                   basestring
}

Example #8
0
class Str(Setting):
    schema = Schema(basestring)

    def _parse_env_var(self, value):
        return value
Example #9
0
class CommandReleaseHook(ReleaseHook):

    commands_schema = Schema({
        "command":
        basestring,
        Optional("args"):
        Or(And(basestring, Use(lambda x: x.strip().split())), [basestring]),
        Optional("user"):
        basestring
    })

    schema_dict = {
        "print_commands": bool,
        "print_output": bool,
        "print_error": bool,
        "cancel_on_error": bool,
        "stop_on_error": bool,
        "pre_build_commands": [commands_schema],
        "pre_release_commands": [commands_schema],
        "post_release_commands": [commands_schema]
    }

    @classmethod
    def name(cls):
        return "command"

    def __init__(self, source_path):
        super(CommandReleaseHook, self).__init__(source_path)

    def execute_command(self, cmd_name, cmd_arguments, user, errors):
        def _err(msg):
            errors.append(msg)
            if self.settings.print_error:
                print >> sys.stderr, msg

        def _execute(cmd, arguments):
            try:
                result = cmd(*(arguments or []))
                if self.settings.print_output:
                    print result.stdout.strip()
            except ErrorReturnCode as e:
                # `e` shows the command that was run
                msg = "command failed:\n%s" % str(e)
                _err(msg)
                return False
            return True

        if not os.path.isfile(cmd_name):
            cmd_full_path = which(cmd_name)
        else:
            cmd_full_path = cmd_name
        if not cmd_full_path:
            msg = "%s: command not found" % cmd_name
            _err(msg)
            return False

        run_cmd = Command(cmd_full_path)
        if user == 'root':
            with sudo:
                return _execute(run_cmd, cmd_arguments)
        elif user and user != getpass.getuser():
            raise NotImplementedError  # TODO
        else:
            return _execute(run_cmd, cmd_arguments)

    def _release(self, commands, errors=None):
        for conf in commands:
            if self.settings.print_commands or config.debug("package_release"):
                from subprocess import list2cmdline
                toks = [conf["command"]] + conf.get("args", [])
                msg = "running command: %s" % list2cmdline(toks)
                if self.settings.print_commands:
                    print msg
                else:
                    print_debug(msg)

            if not self.execute_command(cmd_name=conf.get("command"),
                                        cmd_arguments=conf.get("args"),
                                        user=conf.get("user"),
                                        errors=errors):
                if self.settings.stop_on_error:
                    return

    def pre_build(self, user, install_path, **kwargs):
        errors = []
        self._release(self.settings.pre_build_commands, errors=errors)
        if errors and self.settings.cancel_on_error:
            raise ReleaseHookCancellingError(
                "The following pre-build commands failed:\n%s" %
                '\n\n'.join(errors))

    def pre_release(self, user, install_path, **kwargs):
        errors = []
        self._release(self.settings.pre_release_commands, errors=errors)
        if errors and self.settings.cancel_on_error:
            raise ReleaseHookCancellingError(
                "The following pre-release commands failed:\n%s" %
                '\n\n'.join(errors))

    def post_release(self, user, install_path, variants, **kwargs):
        self._release(self.settings.post_release_commands)
Example #10
0
class CommandReleaseHook(ReleaseHook):

    commands_schema = Schema({
        "command":
        basestring,
        Optional("args"):
        Or(And(basestring, Use(lambda x: x.strip().split())), [basestring]),
        Optional("pretty_args"):
        bool,
        Optional("user"):
        basestring,
        Optional("env"):
        dict
    })

    schema_dict = {
        "print_commands": bool,
        "print_output": bool,
        "print_error": bool,
        "cancel_on_error": bool,
        "stop_on_error": bool,
        "pre_build_commands": [commands_schema],
        "pre_release_commands": [commands_schema],
        "post_release_commands": [commands_schema]
    }

    @classmethod
    def name(cls):
        return "command"

    def __init__(self, source_path):
        super(CommandReleaseHook, self).__init__(source_path)

    def execute_command(self, cmd_name, cmd_arguments, user, errors, env=None):
        def _err(msg):
            errors.append(msg)
            if self.settings.print_error:
                print(msg, file=sys.stderr)

        kwargs = {}
        if env:
            kwargs["env"] = env

        def _execute(commands):
            process = Popen(commands, stdout=PIPE, stderr=STDOUT, **kwargs)
            stdout, _ = process.communicate()

            if process.returncode != 0:
                msg = "command failed:\n%s" % stdout
                _err(msg)
                return False
            if self.settings.print_output:
                print(stdout.strip())
            return True

        if not os.path.isfile(cmd_name):
            cmd_full_path = which(cmd_name)
        else:
            cmd_full_path = cmd_name
        if not cmd_full_path:
            msg = "%s: command not found" % cmd_name
            _err(msg)
            return False

        cmds = [cmd_full_path] + (cmd_arguments or [])
        if user == 'root':
            cmds = ['sudo'] + cmds
            return _execute(cmds)
        elif user and user != getpass.getuser():
            raise NotImplementedError  # TODO
        else:
            return _execute(cmds)

    def pre_build(self, user, install_path, variants=None, **kwargs):
        errors = []
        self._execute_commands(self.settings.pre_build_commands,
                               install_path=install_path,
                               package=self.package,
                               errors=errors,
                               variants=variants)

        if errors and self.settings.cancel_on_error:
            raise ReleaseHookCancellingError(
                "The following pre-build commands failed:\n%s" %
                '\n\n'.join(errors))

    def pre_release(self, user, install_path, variants=None, **kwargs):
        errors = []
        self._execute_commands(self.settings.pre_release_commands,
                               install_path=install_path,
                               package=self.package,
                               errors=errors,
                               variants=variants)

        if errors and self.settings.cancel_on_error:
            raise ReleaseHookCancellingError(
                "The following pre-release commands failed:\n%s" %
                '\n\n'.join(errors))

    def post_release(self, user, install_path, variants, **kwargs):
        # note that the package we use here is the *installed* package, not the
        # developer package (self.package). Otherwise, attributes such as 'root'
        # will be None
        errors = []
        if variants:
            package = variants[0].parent
        else:
            package = self.package

        self._execute_commands(self.settings.post_release_commands,
                               install_path=install_path,
                               package=package,
                               errors=errors,
                               variants=variants)
        if errors:
            print_debug("The following post-release commands failed:\n" +
                        '\n\n'.join(errors))

    def _execute_commands(self,
                          commands,
                          install_path,
                          package,
                          errors=None,
                          variants=None):
        release_dict = dict(path=install_path)
        variant_infos = []
        if variants:
            for variant in variants:
                if isinstance(variant, (int, long)):
                    variant_infos.append(variant)
                else:
                    package = variant.parent
                    var_dict = dict(variant.resource.variables)
                    # using '%s' will preserve potential str/unicode nature
                    var_dict['variant_requires'] = [
                        '%s' % x for x in variant.resource.variant_requires
                    ]
                    variant_infos.append(var_dict)
        formatter = scoped_formatter(system=system,
                                     release=release_dict,
                                     package=package,
                                     variants=variant_infos,
                                     num_variants=len(variant_infos))

        for conf in commands:
            program = conf["command"]

            env_ = None
            env = conf.get("env")
            if env:
                env_ = os.environ.copy()
                env_.update(env)

            # If we have, ie, a list, and format_pretty is True, it will be printed
            # as "1 2 3" instead of "[1, 2, 3]"
            formatter.__dict__['format_pretty'] = conf.get("pretty_args", True)

            args = conf.get("args", [])
            args = [formatter.format(x) for x in args]
            args = [expandvars(x, environ=env_) for x in args]

            if self.settings.print_commands or config.debug("package_release"):
                from subprocess import list2cmdline
                toks = [program] + args

                msgs = []
                msgs.append("running command: %s" % list2cmdline(toks))
                if env:
                    for key, value in env.iteritems():
                        msgs.append("    with: %s=%s" % (key, value))

                if self.settings.print_commands:
                    print('\n'.join(msgs))
                else:
                    for msg in msgs:
                        print_debug(msg)

            if not self.execute_command(cmd_name=program,
                                        cmd_arguments=args,
                                        user=conf.get("user"),
                                        errors=errors,
                                        env=env_):
                if self.settings.stop_on_error:
                    return
Example #11
0
# package
package_schema_dict = package_base_schema_dict.copy()
package_schema_dict.update({
    Optional("variants"):               [[PackageRequest]]
})


# variant
variant_schema_dict = package_base_schema_dict.copy()


#------------------------------------------------------------------------------
# resource schemas
#------------------------------------------------------------------------------

package_family_schema = Schema(package_family_schema_dict)


package_schema = Schema(package_schema_dict)


variant_schema = Schema(variant_schema_dict)


#------------------------------------------------------------------------------
# schemas for converting from POD datatypes
#------------------------------------------------------------------------------

_commands_schema = Or(SourceCode,       # commands as converted function
                      callable,         # commands as function
                      basestring,       # commands in text block
Example #12
0
# utility schemas
# ------------------------------------------------------------------------------

help_schema = Or(
    basestring,  # single help entry
    [[basestring]])  # multiple help entries

_is_late = And(SourceCode, lambda x: hasattr(x, "_late"))


def late_bound(schema):
    return Or(SourceCode, schema)


# used when 'requires' is late bound
late_requires_schema = Schema(
    [Or(PackageRequest, And(basestring, Use(PackageRequest)))])

# ------------------------------------------------------------------------------
# schema dicts
# ------------------------------------------------------------------------------

# requirements of all package-related resources
#

base_resource_schema_dict = {Required("name"): basestring}

# package family
#

package_family_schema_dict = base_resource_schema_dict.copy()
Example #13
0
class ContextSettingsWidget(QtGui.QWidget, ContextViewMixin):

    titles = {
        "packages_path":        "Search path for Rez packages",
        "implicit_packages":    "Packages that are implicitly added to the request",
        "package_filter":       "Package exclusion/inclusion rules"
    }

    schema_dict = {
        "packages_path":        [basestring],
        "implicit_packages":    [basestring],
        "package_filter":       Or(And(None, Use(lambda x: [])),
                                   And(dict, Use(lambda x: [x])),
                                   [dict])
    }

    def __init__(self, context_model=None, attributes=None, parent=None):
        """
        Args:
            attributes (list of str): Select only certain settings to expose. If
                None, all settings are exposed.
        """
        super(ContextSettingsWidget, self).__init__(parent)
        ContextViewMixin.__init__(self, context_model)

        self.schema_keys = set(self.schema_dict.iterkeys())
        if attributes:
            self.schema_keys &= set(attributes)
            assert self.schema_keys

        schema_dict = dict((k, v) for k, v in self.schema_dict.iteritems()
                           if k in self.schema_keys)
        self.schema = Schema(schema_dict)

        self.edit = QtGui.QTextEdit()
        self.edit.setStyleSheet("font: 12pt 'Courier'")
        self.default_btn = QtGui.QPushButton("Set To Defaults")
        self.discard_btn = QtGui.QPushButton("Discard Changes...")
        self.apply_btn = QtGui.QPushButton("Apply")
        self.discard_btn.setEnabled(False)
        self.apply_btn.setEnabled(False)
        btn_pane = create_pane([None, self.default_btn, self.discard_btn,
                                self.apply_btn], True)

        layout = QtGui.QVBoxLayout()
        layout.addWidget(self.edit)
        layout.addWidget(btn_pane)
        self.setLayout(layout)

        self.apply_btn.clicked.connect(self.apply_changes)
        self.default_btn.clicked.connect(self.set_defaults)
        self.discard_btn.clicked.connect(partial(self.discard_changes, True))
        self.edit.textChanged.connect(self._settingsChanged)

        self._update_text()

    def _contextChanged(self, flags=0):
        if not (flags & ContextModel.CONTEXT_CHANGED):
            return
        self._update_text()

    def apply_changes(self):
        def _content_error(title, text):
            ret = QtGui.QMessageBox.warning(self, title, text,
                                            QtGui.QMessageBox.Discard,
                                            QtGui.QMessageBox.Cancel)
            if ret == QtGui.QMessageBox.Discard:
                self.discard_changes()

        # load new content
        try:
            txt = self.edit.toPlainText()
            data = yaml.load(str(txt))
        except YAMLError as e:
            _content_error("Invalid syntax", str(e))
            return

        # check against schema
        if self.schema:
            try:
                data = self.schema.validate(data)
            except SchemaError as e:
                _content_error("Settings validation failure", str(e))
                return

        # apply to context model
        self.context_model.set_packages_path(data["packages_path"])
        self.context_model.set_package_filter(data["package_filter"])
        self._update_text()

    def discard_changes(self, prompt=False):
        if prompt:
            ret = QtGui.QMessageBox.warning(
                self,
                "The context settings have been modified.",
                "Your changes will be lost. Are you sure?",
                QtGui.QMessageBox.Ok,
                QtGui.QMessageBox.Cancel)
            if ret != QtGui.QMessageBox.Ok:
                return

        self._update_text()

    def set_defaults(self):
        packages_path = config.packages_path
        implicits = [str(x) for x in config.implicit_packages]
        package_filter = config.package_filter

        data = {"packages_path": packages_path,
                "implicit_packages": implicits,
                "package_filter": package_filter}
        data = dict((k, v) for k, v in data.iteritems()
                    if k in self.schema_keys)

        self._set_text(data)
        self.discard_btn.setEnabled(True)
        self.apply_btn.setEnabled(True)

    def _update_text(self):
        model = self.context_model
        implicits = [str(x) for x in model.implicit_packages]
        data = {"packages_path": model.packages_path,
                "implicit_packages": implicits,
                "package_filter": model.package_filter}
        data = dict((k, v) for k, v in data.iteritems()
                    if k in self.schema_keys)

        self._set_text(data)
        self.discard_btn.setEnabled(False)
        self.apply_btn.setEnabled(False)

    def _set_text(self, data):
        lines = []
        for key, value in data.iteritems():
            lines.append('')
            txt = yaml.dump({key: value}, default_flow_style=False)
            title = self.titles.get(key)
            if title:
                lines.append("# %s" % title)
            lines.append(txt.rstrip())

        txt = '\n'.join(lines) + '\n'
        txt = txt.lstrip()
        self.edit.setPlainText(txt)

    def _settingsChanged(self):
        self.discard_btn.setEnabled(True)
        self.apply_btn.setEnabled(True)
Example #14
0
class Char(Setting):
    schema = Schema(basestring, lambda x: len(x) == 1)

    def _parse_env_var(self, value):
        return value
Example #15
0
    'plugin_for', 'requires', 'build_requires', 'private_build_requires',
    'variants', 'commands', 'pre_commands', 'post_commands', 'help', 'config',
    'uuid', 'timestamp', 'release_message', 'changelog', 'vcs', 'revision',
    'previous_version', 'previous_revision'
]

version_schema = Or(basestring, And(Version, Use(str)))

package_request_schema = Or(basestring, And(PackageRequest, Use(str)))

source_code_schema = Or(SourceCode, And(basestring, Use(SourceCode)))

tests_schema = Schema({
    Optional(basestring):
    Or(
        Or(basestring, [basestring]), {
            "command": Or(basestring, [basestring]),
            Optional("requires"): [package_request_schema]
        })
})

# package serialisation schema
package_serialise_schema = Schema({
    Required("name"):
    basestring,
    Optional("version"):
    version_schema,
    Optional("description"):
    basestring,
    Optional("authors"): [basestring],
    Optional("tools"):
    late_bound([basestring]),
Example #16
0
class Setting(object):
    """Setting subclasses implement lazy setting validators.

    Note that lazy setting validation only happens on master configuration
    settings - plugin settings are validated on load only.
    """
    schema = Schema(object)

    def __init__(self, config, key):
        self.config = config
        self.key = key

    @property
    def _env_var_name(self):
        return "REZ_%s" % self.key.upper()

    def _parse_env_var(self, value):
        raise NotImplementedError

    def validate(self, data):
        try:
            data = self._validate(data)
            data = self.schema.validate(data)
            data = expand_system_vars(data)
        except SchemaError as e:
            raise ConfigurationError("Misconfigured setting '%s': %s" %
                                     (self.key, str(e)))
        return data

    def _validate(self, data):
        # overridden settings take precedence. Note that `data` has already
        # taken override into account at this point
        if self.key in self.config.overrides:
            return data

        if not self.config.locked:

            # next, env-var
            value = os.getenv(self._env_var_name)
            if value is not None:
                return self._parse_env_var(value)

            # next, JSON-encoded env-var
            varname = self._env_var_name + "_JSON"
            value = os.getenv(varname)
            if value is not None:
                from rez.utils import json

                try:
                    return json.loads(value)
                except ValueError:
                    raise ConfigurationError(
                        "Expected $%s to be JSON-encoded string." % varname)

        # next, data unchanged
        if data is not None:
            return data

        # some settings have a programmatic default
        attr = "_get_%s" % self.key
        if hasattr(self.config, attr):
            return getattr(self.config, attr)()

        # setting is None
        return None
Example #17
0
File: config.py Project: mwiebe/rez
config_schema = Schema({
    "packages_path": PathList,
    "plugin_path": PathList,
    "bind_module_path": PathList,
    "implicit_packages": StrList,
    "parent_variables": StrList,
    "resetting_variables": StrList,
    "release_hooks": StrList,
    "critical_styles": OptionalStrList,
    "error_styles": OptionalStrList,
    "warning_styles": OptionalStrList,
    "info_styles": OptionalStrList,
    "debug_styles": OptionalStrList,
    "heading_styles": OptionalStrList,
    "local_styles": OptionalStrList,
    "implicit_styles": OptionalStrList,
    "alias_styles": OptionalStrList,
    "memcached_uri": OptionalStrList,
    "local_packages_path": Str,
    "release_packages_path": Str,
    "dot_image_format": Str,
    "build_directory": Str,
    "documentation_url": Str,
    "suite_visibility": SuiteVisibility_,
    "rez_tools_visibility": RezToolsVisibility_,
    "suite_alias_prefix_char": Char,
    "tmpdir": OptionalStr,
    "default_shell": OptionalStr,
    "terminal_emulator_command": OptionalStr,
    "editor": OptionalStr,
    "image_viewer": OptionalStr,
    "difftool": OptionalStr,
    "browser": OptionalStr,
    "critical_fore": OptionalStr,
    "critical_back": OptionalStr,
    "error_fore": OptionalStr,
    "error_back": OptionalStr,
    "warning_fore": OptionalStr,
    "warning_back": OptionalStr,
    "info_fore": OptionalStr,
    "info_back": OptionalStr,
    "debug_fore": OptionalStr,
    "debug_back": OptionalStr,
    "heading_fore": OptionalStr,
    "heading_back": OptionalStr,
    "local_fore": OptionalStr,
    "local_back": OptionalStr,
    "implicit_fore": OptionalStr,
    "implicit_back": OptionalStr,
    "alias_fore": OptionalStr,
    "alias_back": OptionalStr,
    "build_thread_count": Int,
    "resource_caching_maxsize": Int,
    "max_package_changelog_chars": Int,
    "memcached_package_file_min_compress_len": Int,
    "memcached_context_file_min_compress_len": Int,
    "memcached_listdir_min_compress_len": Int,
    "memcached_resolve_min_compress_len": Int,
    "color_enabled": Bool,
    "resolve_caching": Bool,
    "cache_package_files": Bool,
    "cache_listdir": Bool,
    "prune_failed_graph": Bool,
    "all_parent_variables": Bool,
    "all_resetting_variables": Bool,
    "package_commands_sourced_first": Bool,
    "warn_shell_startup": Bool,
    "warn_untimestamped": Bool,
    "warn_all": Bool,
    "warn_none": Bool,
    "debug_file_loads": Bool,
    "debug_plugins": Bool,
    "debug_package_release": Bool,
    "debug_bind_modules": Bool,
    "debug_resources": Bool,
    "debug_package_exclusions": Bool,
    "debug_resolve_memcache": Bool,
    "debug_memcache": Bool,
    "debug_all": Bool,
    "debug_none": Bool,
    "quiet": Bool,
    "show_progress": Bool,
    "catch_rex_errors": Bool,
    "set_prompt": Bool,
    "prefix_prompt": Bool,
    "warn_old_commands": Bool,
    "error_old_commands": Bool,
    "debug_old_commands": Bool,
    "warn_package_name_mismatch": Bool,
    "error_package_name_mismatch": Bool,
    "warn_version_mismatch": Bool,
    "error_version_mismatch": Bool,
    "warn_nonstring_version": Bool,
    "error_nonstring_version": Bool,
    "warn_commands2": Bool,
    "error_commands2": Bool,
    "rez_1_environment_variables": Bool,
    "rez_1_cmake_variables": Bool,
    "disable_rez_1_compatibility": Bool,
    "env_var_separators": Dict,
    "variant_select_mode": VariantSelectMode_,
    "package_filter": OptionalDictOrDictList,
    "new_session_popen_args": OptionalDict,

    # GUI settings
    "use_pyside": Bool,
    "use_pyqt": Bool
})
Example #18
0
                            And(PackageRequest, Use(str)))


package_schema = Schema({
    Required("name"):                   basestring,
    Optional("base"):                   basestring,
    Optional("version"):                Or(basestring,
                                           And(Version, Use(str))),
    Optional('description'):            basestring,
    Optional('authors'):                [basestring],

    Optional('requires'):               [package_request_schema],
    Optional('build_requires'):         [package_request_schema],
    Optional('private_build_requires'): [package_request_schema],
    Optional('variants'):               [[package_request_schema]],

    Optional('uuid'):                   basestring,
    Optional('config'):                 dict,
    Optional('tools'):                  [basestring],
    Optional('help'):                   help_schema,

    Optional('pre_commands'):           _commands_schema,
    Optional('commands'):               _commands_schema,
    Optional('post_commands'):          _commands_schema,

    Optional('custom'):                 dict,

    Optional(basestring):               object  # allows deprecated fields
})


package_schema_keys = schema_keys(package_schema)
Example #19
0
class CommandReleaseHook(ReleaseHook):

    commands_schema = Schema({
        "command":
        basestring,
        Optional("args"):
        Or(And(basestring, Use(lambda x: x.strip().split())), [basestring]),
        Optional("user"):
        basestring,
        Optional("env"):
        dict
    })

    schema_dict = {
        "print_commands": bool,
        "print_output": bool,
        "print_error": bool,
        "cancel_on_error": bool,
        "stop_on_error": bool,
        "pre_build_commands": [commands_schema],
        "pre_release_commands": [commands_schema],
        "post_release_commands": [commands_schema]
    }

    @classmethod
    def name(cls):
        return "command"

    def __init__(self, source_path):
        super(CommandReleaseHook, self).__init__(source_path)

    def execute_command(self, cmd_name, cmd_arguments, user, errors, env=None):
        def _err(msg):
            errors.append(msg)
            if self.settings.print_error:
                print >> sys.stderr, msg

        kwargs = {}
        if env:
            kwargs["_env"] = env

        def _execute(cmd, arguments):
            try:
                result = cmd(*(arguments or []), **kwargs)
                if self.settings.print_output:
                    print result.stdout.strip()
            except ErrorReturnCode as e:
                # `e` shows the command that was run
                msg = "command failed:\n%s" % str(e)
                _err(msg)
                return False
            return True

        if not os.path.isfile(cmd_name):
            cmd_full_path = which(cmd_name)
        else:
            cmd_full_path = cmd_name
        if not cmd_full_path:
            msg = "%s: command not found" % cmd_name
            _err(msg)
            return False

        run_cmd = Command(cmd_full_path)
        if user == 'root':
            with sudo:
                return _execute(run_cmd, cmd_arguments)
        elif user and user != getpass.getuser():
            raise NotImplementedError  # TODO
        else:
            return _execute(run_cmd, cmd_arguments)

    def pre_build(self, user, install_path, **kwargs):
        errors = []
        self._execute_commands(self.settings.pre_build_commands,
                               install_path=install_path,
                               package=self.package,
                               errors=errors)

        if errors and self.settings.cancel_on_error:
            raise ReleaseHookCancellingError(
                "The following pre-build commands failed:\n%s" %
                '\n\n'.join(errors))

    def pre_release(self, user, install_path, **kwargs):
        errors = []
        self._execute_commands(self.settings.pre_release_commands,
                               install_path=install_path,
                               package=self.package,
                               errors=errors)

        if errors and self.settings.cancel_on_error:
            raise ReleaseHookCancellingError(
                "The following pre-release commands failed:\n%s" %
                '\n\n'.join(errors))

    def post_release(self, user, install_path, variants, **kwargs):
        # note that the package we use here is the *installed* package, not the
        # developer package (self.package). Otherwise, attributes such as 'root'
        # will be None
        errors = []
        if variants:
            package = variants[0].parent
        else:
            package = self.package

        self._execute_commands(self.settings.post_release_commands,
                               install_path=install_path,
                               package=package,
                               errors=errors)
        if errors:
            print_debug("The following post-release commands failed:\n" +
                        '\n\n'.join(errors))

    def _execute_commands(self, commands, install_path, package, errors=None):
        release_dict = dict(path=install_path)
        formatter = scoped_formatter(system=system,
                                     release=release_dict,
                                     package=package)

        for conf in commands:
            program = conf["command"]

            env_ = None
            env = conf.get("env")
            if env:
                env_ = os.environ.copy()
                env_.update(env)

            args = conf.get("args", [])
            args = [formatter.format(x) for x in args]
            args = [expandvars(x, environ=env_) for x in args]

            if self.settings.print_commands or config.debug("package_release"):
                from subprocess import list2cmdline
                toks = [program] + args

                msgs = []
                msgs.append("running command: %s" % list2cmdline(toks))
                if env:
                    for key, value in env.iteritems():
                        msgs.append("    with: %s=%s" % (key, value))

                if self.settings.print_commands:
                    print '\n'.join(msgs)
                else:
                    for msg in msgs:
                        print_debug(msg)

            if not self.execute_command(cmd_name=program,
                                        cmd_arguments=args,
                                        user=conf.get("user"),
                                        errors=errors,
                                        env=env_):
                if self.settings.stop_on_error:
                    return
class ContextSettingsWidget(QtGui.QWidget, ContextViewMixin):

    titles = {
        "packages_path":        "Search path for Rez packages",
        "implicit_packages":    "Packages that are implicitly added to the request",
        "package_filter":       "Package exclusion/inclusion rules"
    }

    schema_dict = {
        "packages_path":        [basestring],
        "implicit_packages":    [basestring],
        "package_filter":       Or(And(None, Use(lambda x: [])),
                                   And(dict, Use(lambda x: [x])),
                                   [dict])
    }

    def __init__(self, context_model=None, attributes=None, parent=None):
        """
        Args:
            attributes (list of str): Select only certain settings to expose. If
                None, all settings are exposed.
        """
        super(ContextSettingsWidget, self).__init__(parent)
        ContextViewMixin.__init__(self, context_model)

        self.schema_keys = set(self.schema_dict.iterkeys())
        if attributes:
            self.schema_keys &= set(attributes)
            assert self.schema_keys

        schema_dict = dict((k, v) for k, v in self.schema_dict.iteritems()
                           if k in self.schema_keys)
        self.schema = Schema(schema_dict)

        self.edit = QtGui.QTextEdit()
        self.edit.setStyleSheet("font: 9pt 'Courier'")
        self.default_btn = QtGui.QPushButton("Set To Defaults")
        self.discard_btn = QtGui.QPushButton("Discard Changes...")
        self.apply_btn = QtGui.QPushButton("Apply")
        self.discard_btn.setEnabled(False)
        self.apply_btn.setEnabled(False)
        btn_pane = create_pane([None, self.default_btn, self.discard_btn,
                                self.apply_btn], True)

        layout = QtGui.QVBoxLayout()
        layout.addWidget(self.edit)
        layout.addWidget(btn_pane)
        self.setLayout(layout)

        self.apply_btn.clicked.connect(self.apply_changes)
        self.default_btn.clicked.connect(self.set_defaults)
        self.discard_btn.clicked.connect(partial(self.discard_changes, True))
        self.edit.textChanged.connect(self._settingsChanged)

        self._update_text()

    def _contextChanged(self, flags=0):
        if not (flags & ContextModel.CONTEXT_CHANGED):
            return
        self._update_text()

    def apply_changes(self):
        def _content_error(title, text):
            ret = QtGui.QMessageBox.warning(self, title, text,
                                            QtGui.QMessageBox.Discard,
                                            QtGui.QMessageBox.Cancel)
            if ret == QtGui.QMessageBox.Discard:
                self.discard_changes()

        # load new content
        try:
            txt = self.edit.toPlainText()
            data = yaml.load(str(txt))
        except YAMLError as e:
            _content_error("Invalid syntax", str(e))
            return

        # check against schema
        if self.schema:
            try:
                data = self.schema.validate(data)
            except SchemaError as e:
                _content_error("Settings validation failure", str(e))
                return

        # apply to context model
        self.context_model.set_packages_path(data["packages_path"])
        self.context_model.set_package_filter(data["package_filter"])
        self._update_text()

    def discard_changes(self, prompt=False):
        if prompt:
            ret = QtGui.QMessageBox.warning(
                self,
                "The context settings have been modified.",
                "Your changes will be lost. Are you sure?",
                QtGui.QMessageBox.Ok,
                QtGui.QMessageBox.Cancel)
            if ret != QtGui.QMessageBox.Ok:
                return

        self._update_text()

    def set_defaults(self):
        packages_path = config.packages_path
        implicits = [str(x) for x in config.implicit_packages]
        package_filter = config.package_filter

        data = {"packages_path": packages_path,
                "implicit_packages": implicits,
                "package_filter": package_filter}
        data = dict((k, v) for k, v in data.iteritems()
                    if k in self.schema_keys)

        self._set_text(data)
        self.discard_btn.setEnabled(True)
        self.apply_btn.setEnabled(True)

    def _update_text(self):
        model = self.context_model
        implicits = [str(x) for x in model.implicit_packages]
        data = {"packages_path": model.packages_path,
                "implicit_packages": implicits,
                "package_filter": model.package_filter}
        data = dict((k, v) for k, v in data.iteritems()
                    if k in self.schema_keys)

        self._set_text(data)
        self.discard_btn.setEnabled(False)
        self.apply_btn.setEnabled(False)

    def _set_text(self, data):
        lines = []
        for key, value in data.iteritems():
            lines.append('')
            txt = yaml.dump({key: value}, default_flow_style=False)
            title = self.titles.get(key)
            if title:
                lines.append("# %s" % title)
            lines.append(txt.rstrip())

        txt = '\n'.join(lines) + '\n'
        txt = txt.lstrip()
        self.edit.setPlainText(txt)

    def _settingsChanged(self):
        self.discard_btn.setEnabled(True)
        self.apply_btn.setEnabled(True)
Example #21
0
File: config.py Project: opcg/rez
class Str(Setting):
    schema = Schema(str_type)

    def _parse_env_var(self, value):
        return value
Example #22
0
package_serialise_schema = Schema({
    Required("name"):
    basestring,
    Optional("nice_name"):
    basestring,
    Optional("version"):
    version_schema,
    Optional("description"):
    basestring,
    Optional("authors"): [basestring],
    Optional("tools"): [basestring],
    Optional("tools_info"):
    dict,
    Optional("excluded_tools"): [basestring],
    Optional('requires'): [package_request_schema],
    Optional('build_requires'): [package_request_schema],
    Optional('private_build_requires'): [package_request_schema],
    Optional('variants'): [[package_request_schema]],
    Optional('has_plugins'):
    bool,
    Optional('plugin_for'): [basestring],
    Optional('plugin_launch_commands'):
    source_code_schema,
    Optional('pre_commands'):
    source_code_schema,
    Optional('commands'):
    source_code_schema,
    Optional('post_commands'):
    source_code_schema,
    Optional("help"):
    help_schema,
    Optional("uuid"):
    basestring,
    Optional("config"):
    dict,
    Optional("timestamp"):
    int,
    Optional('revision'):
    object,
    Optional('changelog'):
    basestring,
    Optional('release_message'):
    Or(None, basestring),
    Optional('previous_version'):
    version_schema,
    Optional('previous_revision'):
    object,
    Optional(basestring):
    object
})
Example #23
0
File: config.py Project: opcg/rez
 def _validate_key(self, key, value, key_schema):
     if type(key_schema) is type and issubclass(key_schema, Setting):
         key_schema = key_schema(self, key)
     elif not isinstance(key_schema, Schema):
         key_schema = Schema(key_schema)
     return key_schema.validate(value)
Example #24
0
 def _validate_key(self, key, value, key_schema):
     if type(key_schema) is type and issubclass(key_schema, Setting):
         key_schema = key_schema(self, key)
     elif not isinstance(key_schema, Schema):
         key_schema = Schema(key_schema)
     return key_schema.validate(value)
Example #25
0
class FileSystemCombinedPackageFamilyResource(PackageFamilyResource):
    key = "filesystem.family.combined"
    repository_type = "filesystem"

    schema = Schema({
        Optional("versions"): [
            And(basestring, Use(Version))
        ],
        Optional("version_overrides"): {
            And(basestring, Use(VersionRange)): dict
        }
    })

    @property
    def ext(self):
        return self.get("ext")

    @property
    def filepath(self):
        filename = "%s.%s" % (self.name, self.ext)
        return os.path.join(self.location, filename)

    def _uri(self):
        return self.filepath

    def get_last_release_time(self):
        try:
            return os.path.getmtime(self.filepath)
        except OSError:
            return 0

    def iter_packages(self):
        # unversioned package
        if config.allow_unversioned_packages and not self.versions:
            package = self._repository.get_resource(
                FileSystemCombinedPackageResource.key,
                location=self.location,
                name=self.name,
                ext=self.ext)
            yield package
            return

        # versioned packages
        for version in self.versions:
            package = self._repository.get_resource(
                FileSystemCombinedPackageResource.key,
                location=self.location,
                name=self.name,
                ext=self.ext,
                version=str(version))
            yield package

    def _load(self):
        format_ = FileFormat[self.ext]
        data = load_from_file(
            self.filepath,
            format_,
            disable_memcache=self._repository.disable_memcache
        )

        check_format_version(self.filepath, data)
        return data