Creates all the logical property.

        The list of names of properties to be created is passed
        with frozenset log_props. The getter/setter information is
        taken from _{get,set}dict.

        This method resolves also wildcards in names, and performs
        all checks to ensure correctness.

        Returns the frozen set of the actually created properties
        (as not log_props may be really created, e.g. when no
        getter is provided, and a warning is issued).

def __create_log_props(cls, log_props, _getdict, _setdict):  # @NoSelf
        """Creates all the logical property.

        The list of names of properties to be created is passed
        with frozenset log_props. The getter/setter information is
        taken from _{get,set}dict.

        This method resolves also wildcards in names, and performs
        all checks to ensure correctness.

        Returns the frozen set of the actually created properties
        (as not log_props may be really created, e.g. when no
        getter is provided, and a warning is issued).
        """

        real_log_props = set()
        resolved_getdict = {}
        resolved_setdict = {}

        for _dict_name, _dict, _resolved_dict in (
                                      ("getter", _getdict, resolved_getdict),
                                      ("setter", _setdict, resolved_setdict)):
            # first resolve all wildcards
            for pat, ai in ((pat, ai)
                            for pat, ai in _dict.items()
                            if frozenset(pat) & WILDCARDS):
                matches = fnmatch.filter(log_props, pat)
                for match in matches:
                    if match in _resolved_dict:
                        raise NameError("In class %s.%s %s property '%s' "
                                        "is matched multiple times"
                                        " by patterns" % \
                            (cls.__module__, cls.__name__, _dict_name, match))
                    _resolved_dict[match] = ai

                if not matches:
                    logger.warning("In class %s.%s %s pattern '%s' "
                                   "did not match any existing "
                                   "logical property",
                                   cls.__module__, cls.__name__, _dict_name, pat)

            # now adds the exact matches (no wilcards) which override
            # the pattern-matches
            _resolved_dict.update((name, ai)
                                  for name, ai in _dict.items()
                                  if name in log_props)

            # checks that all getter/setter have a corresponding logical
            # property
            not_found = [name for name in _resolved_dict
                         if name not in log_props]

            if not_found:
                logger.warning("In class %s.%s logical %s were declared for "
                               "non-existent observables: %s",
                               cls.__module__, cls.__name__, _dict_name,
                               str(not_found))

        # creates the properties
        for name in log_props:
            # finds the getter
            ai_get = resolved_getdict.get(name, None)
            if ai_get:
                # decorator-based
                _getter = type(cls).get_getter(cls, name, ai_get.func,
                                               ai_get.has_args)
                _deps = ai_get.deps
            else:
                # old style
                _getter = type(cls).get_getter(cls, name)
                if _getter is None:
                    raise RuntimeError("In class %s.%s "
                                       "logical observable '%s' "
                                        "has no getter method" % \
                                  (cls.__module__, cls.__name__, name))
                _deps = type(cls)._get_old_style_getter_deps(cls, name,
                                                             _getter)

            # finds the setter
            ai_set = resolved_setdict.get(name, None)
            if ai_set:
                # decorator-based
                if ai_get:
                    _setter = type(cls).get_setter(cls, name,
                                                ai_set.func, ai_set.has_args,
                                                ai_get.func, ai_get.has_args)
                else:
                    # the getter is old style. _getter is already
                    # resolved wrt the name it may take, so
                    # getter_takes_name is False
                    _setter = type(cls).get_setter(cls, name,
                                               ai_set.func, ai_set.has_args,
                                               _getter, False)
            else:
                # old style setter
                if ai_get:
                    _setter = type(cls).get_setter(cls, name,
                                                   None, None,
                                                   ai_get.func,
                                                   ai_get.has_args)
                else:
                    _setter = type(cls).get_setter(cls, name)

            # creates the logical property, here _setter can be None
            prop = PropertyMeta.LogicalOP(_getter, _setter, frozenset(_deps))
            setattr(cls, name, prop)
            real_log_props.add(name)

        # checks that all setters have a getter
        setters_no_getters = (set(resolved_setdict) - real_log_props) & \
                                log_props
        if setters_no_getters:
            logger.warning("In class %s.%s logical setters have no "
                           "getters: %s",
                           cls.__module__, cls.__name__,
                           ", ".join(setters_no_getters))

        return frozenset(real_log_props)