Exemplo n.º 1
0
    def __init__(self, core: Core, attrs=None):

        self.data = {}

        # internal
        self.core = core
        # self.envs  do nothing
        self.envs = EnvManager()
        self.installer = None
        # next fields are loaded from yaml
        # meta
        self.name = None
        self.title = None
        self.description = None
        self.link = None
        self.author = None
        self.icon = None
        # string list
        self.tags = []
        self.eula = None

        # fiters
        self.os = None
        self.bitness = None
        self.web_server = None
        self.lang = None
        self.platform = None

        # versions
        self.version = ''
        self.installed_version = ''

        # installer stuff
        self.dependencies = []
        self.files = []
        self.install_command = None
        self.upgrade_command = None
        self.config = None
        self.uninstall_command = None
        self.find_installed_command = None
        self.parameters = {}

        if attrs is not None:
            for item in attrs.keys():
                self.__dict__[item] = attrs[item]

            self.name = attrs[self.get_typename()]

            if attrs.get('files'):
                # create File objects for every file item
                self.files = []
                for f in attrs.get('files', []):
                    if f.get('file'):
                        self.files.append(File(self, **f))

            self.installer = Installer(self, self.install_command,
                                       self.upgrade_command,
                                       self.uninstall_command,
                                       self.find_installed_command)
Exemplo n.º 2
0
    def merge(self, **kwargs):
        """
        Merges product representation in 'kwargs' dict with current product.
        Current product fields are overwritten by values from kwargs.
        :param kwargs: dict with product representation to merge.
        """
        # name of attribute (product, engine, application) with product name
        typename = self.get_typename()
        self.name = kwargs[typename]

        ####
        self.title = kwargs.get('title') or self.title
        self.description = kwargs.get('description') or self.description
        self.link = kwargs.get('link') or self.link
        self.author = kwargs.get('author') or self.author
        self.icon = kwargs.get('icon') or self.icon
        self.tags = kwargs.get('tags') or self.tags
        self.eula = kwargs.get('eula') or self.eula

        self.os = kwargs.get('os') or self.os
        self.bitness = kwargs.get('bitness') or self.bitness
        self.web_server = kwargs.get('webserver') or self.web_server
        self.lang = kwargs.get('lang') or self.lang

        # это поле не читается из ямла, оно создаётся из:
        self.platform = Platform(self.os, self.bitness, self.web_server, self.lang)

        self.dependencies = kwargs.get('dependencies', []) or self.dependencies
        self.version = str(kwargs.get('version', '')) or self.version
        self.installed_version = str(kwargs.get('installed_version', '')) or self.installed_version

        if kwargs.get('files'):
            # create File objects for every file item
            self.files = []
            for f in kwargs.get('files', []):
                fs = f.__getstate__() if isinstance(f, File) else f
                if fs.get('file'):
                    self.files.append(File(self, **fs))

        self.install_command = kwargs.get('install_command', None) or self.install_command
        if self.install_command:
            self.install_command = self.install_command.rstrip()

        self.upgrade_command = kwargs.get('upgrade_command', None) or self.upgrade_command
        if self.upgrade_command:
            self.upgrade_command = self.upgrade_command.rstrip()

        self.uninstall_command = kwargs.get('uninstall_command', None) or self.uninstall_command
        if self.uninstall_command:
            self.uninstall_command = self.uninstall_command.rstrip()

        self.find_installed_command = kwargs.get('find_installed_command', None) or self.find_installed_command
        if self.find_installed_command:
            self.find_installed_command = self.find_installed_command.rstrip()

        self.parameters = kwargs.get('parameters', None) or self.parameters

        # create Installer from commands,
        # installer knows to how call install_command, uninstall_command
        self.installer = Installer(self, self.install_command, self.upgrade_command, self.uninstall_command, self.find_installed_command)
Exemplo n.º 3
0
    def __init__(self, core: Core, attrs=None ):

        self.data = {}

        # internal
        self.core = core
        # self.envs  do nothing
        self.envs = EnvManager()
        self.installer = None
        # next fields are loaded from yaml
        # meta
        self.name = None
        self.title = None
        self.description = None
        self.link = None
        self.author = None
        self.icon = None
        # string list
        self.tags = []
        self.eula = None

        # fiters
        self.os = None
        self.bitness = None
        self.web_server = None
        self.lang = None
        self.platform = None

        # versions
        self.version = ''
        self.installed_version = ''

        # installer stuff
        self.dependencies = []
        self.files = []
        self.install_command = None
        self.upgrade_command = None
        self.config = None
        self.uninstall_command = None
        self.find_installed_command = None
        self.parameters = {}

        if attrs is not None:
            for item in attrs.keys():
                self.__dict__[item] = attrs[item]

            self.name = attrs[self.get_typename()]

            if attrs.get('files'):
                # create File objects for every file item
                self.files = []
                for f in attrs.get('files', []):
                    if f.get('file'):
                        self.files.append(File(self, **f))

            self.installer = Installer(self, self.install_command, self.upgrade_command,
                                        self.uninstall_command, self.find_installed_command)
Exemplo n.º 4
0
class BaseProduct(object):
    """
    Represent abstract class for product.
    Descendants: Product, Application, Engine.
    """

    def get_typename(self):
        """
        Descendant return string with type name: 'product', 'application' or 'engine'.
        This type name used in yaml represenstion for product:
        - product: Product1
          title: ...
        """
        raise NotImplementedError()

    def __init__(self, core: Core, attrs=None ):

        self.data = {}

        # internal
        self.core = core
        # self.envs  do nothing
        self.envs = EnvManager()
        self.installer = None
        # next fields are loaded from yaml
        # meta
        self.name = None
        self.title = None
        self.description = None
        self.link = None
        self.author = None
        self.icon = None
        # string list
        self.tags = []
        self.eula = None

        # fiters
        self.os = None
        self.bitness = None
        self.web_server = None
        self.lang = None
        self.platform = None

        # versions
        self.version = ''
        self.installed_version = ''

        # installer stuff
        self.dependencies = []
        self.files = []
        self.install_command = None
        self.upgrade_command = None
        self.config = None
        self.uninstall_command = None
        self.find_installed_command = None
        self.parameters = {}

        if attrs is not None:
            for item in attrs.keys():
                self.__dict__[item] = attrs[item]

            self.name = attrs[self.get_typename()]

            if attrs.get('files'):
                # create File objects for every file item
                self.files = []
                for f in attrs.get('files', []):
                    if f.get('file'):
                        self.files.append(File(self, **f))

            self.installer = Installer(self, self.install_command, self.upgrade_command,
                                        self.uninstall_command, self.find_installed_command)


    def merge(self, **kwargs):
        """
        Merges product representation in 'kwargs' dict with current product.
        Current product fields are overwritten by values from kwargs.
        :param kwargs: dict with product representation to merge.
        """
        # name of attribute (product, engine, application) with product name
        typename = self.get_typename()
        self.name = kwargs[typename]

        ####
        self.title = kwargs.get('title') or self.title
        self.description = kwargs.get('description') or self.description
        self.link = kwargs.get('link') or self.link
        self.author = kwargs.get('author') or self.author
        self.icon = kwargs.get('icon') or self.icon
        self.tags = kwargs.get('tags') or self.tags
        self.eula = kwargs.get('eula') or self.eula

        self.os = kwargs.get('os') or self.os
        self.bitness = kwargs.get('bitness') or self.bitness
        self.web_server = kwargs.get('webserver') or self.web_server
        self.lang = kwargs.get('lang') or self.lang

        # это поле не читается из ямла, оно создаётся из:
        self.platform = Platform(self.os, self.bitness, self.web_server, self.lang)

        self.dependencies = kwargs.get('dependencies', []) or self.dependencies

        self.version = str(kwargs.get('version', '')) or self.version
        self.installed_version = str(kwargs.get('installed_version', '')) or self.installed_version
        self.config = kwargs.get('config') or self.config

        files_list = kwargs.get('files', [])
        if files_list and len(files_list)>0:
            # create File objects for every file item
            self.files = []
            for f in files_list:
                fs = f.__getstate__() if isinstance(f, File) else f
                if fs.get('file'):
                    self.files.append(File(self, **fs))

        self.install_command = kwargs.get('install_command', None) or self.install_command
        if self.install_command:
            self.install_command = self.install_command.rstrip()

        self.upgrade_command = kwargs.get('upgrade_command', None) or self.upgrade_command
        if self.upgrade_command:
            self.upgrade_command = self.upgrade_command.rstrip()

        self.uninstall_command = kwargs.get('uninstall_command', None) or self.uninstall_command
        if self.uninstall_command:
            self.uninstall_command = self.uninstall_command.rstrip()

        self.find_installed_command = kwargs.get('find_installed_command', None) or self.find_installed_command
        if self.find_installed_command:
            self.find_installed_command = self.find_installed_command.rstrip()

        self.parameters = kwargs.get('parameters', None) or self.parameters
        # TODO must be deprecated
        # create Installer from commands,
        # installer knows to how call install_command, uninstall_command
        self.installer = Installer(self, self.install_command,
                                   self.upgrade_command,
                                   self.uninstall_command,
                                   self.find_installed_command)

    def __setattr__(self, name, value):
        self.__dict__[name] = value


    def __getstate__(self):
        """
        Returns ProductState object used in Yaml dumper.
        ProductState is smart OrderedDict wrapper.
        Method saves only non empty fields.
        :rtype : ProductState
        """
        result = ProductState()
        result[self.get_typename()] = self.name



        if self.title:
            result['title'] = self.title
        if self.description:
            result['description'] = Literal(self.description)
        if self.link:
            result['link'] = self.link
        if self.author:
            result['author'] = self.author
        if self.icon:
            result['icon'] = self.icon
        if self.tags:
            result['tags'] = self.tags
        if self.eula:
            result['eula'] = self.eula
        if self.os:
            result['os'] = self.os
        if self.bitness:
            result['bitness'] = self.bitness
        if self.web_server:
            result['web_server'] = self.web_server
        if self.lang:
            result['lang'] = self.lang
        if self.version:
            result['version'] = self.version

        result['installed_version'] = self.get_installed_version()

        if self.dependencies:
            result['dependencies'] = self.dependencies
        if self.files:
            result['files'] = [file.__getstate__() for file in self.files]
        if self.install_command:
            result['install_command'] = Literal(self.install_command)
        if self.upgrade_command:
            result['upgrade_command'] = Literal(self.upgrade_command)
        if self.uninstall_command:
            result['uninstall_command'] = Literal(self.uninstall_command)
        if self.find_installed_command:
            result['find_installed_command'] = Literal(self.find_installed_command)

        result['parameters'] = self.parameters or []
        if self.config:
            result["config"] = self.config
        return result

    def to_dict(self, rich=False)-> OrderedDict:
        """
        Dump product fields to OrderedDict used in JSON responses.
        :param rich: dump additional calculated fields.
        """
        product_dict = self.__getstate__().get_dict()
        if rich:
            product_dict['name'] = self.name
            product_dict['has_upgrade'] = self.has_upgrade()
            product_dict['is_upgradable'] = self.is_upgradable()
        return product_dict

    def __repr__(self):
        return '{0}({1}, {2})'.format(self.__class__.__name__, self.name, self.version or None)

    def is_installed(self)-> bool:
        """
        Check that great or equal version installed.
        Used in DependencyManager and self.install method.
        """
        if not self.installed_version:
            self.get_installed_version()
        if self.installed_version:
            compare_result = compare_versions(self.version, self.installed_version)
            return compare_result <= 0
        return False

    def is_installed_any_version(self):
        """
        Check that any version of product is installed.
        Used in DependencyManager and self.upgrade method.
        """
        if not self.installed_version:
            self.get_installed_version()
        return bool(self.installed_version)

    def install(self, parameters: dict)-> bool:
        """
        Installs itself:
        Skip installation if product is installed.
        Download files if they are not in cache yet.
        Call installer object with parameters.
        :param parameters: dict with parameters for installation, example: {'install_dir': 'c:\...'}
        :return: whether the installation was successful
        """
        if self.is_installed():
            return False
        # set name for log filename
        self.set_log_path('install')
        self.download()
        result = self.installer.install(parameters)
        self.unset_log_path('install')
        # logging.info("i have finished installing produxt {0}".format( str(result) ) )
        return result

    def upgrade(self, parameters: dict)-> bool:
        """
        Upgrades itself:
        Works like install(), but call 'upgrade' methid of installer.
        Download files if they are not in cache yet.
        Call installer object with parameters.
        :param parameters:
        :return: whether the upgrade was successful
        """
        # set name for lof filename
        self.set_log_path('upgrade')
        self.download()
        result = self.installer.upgrade(parameters)
        self.unset_log_path('upgrade')
        return result

    def uninstall(self):
        """
        Uninstalls itself.
        :return: whether the uninstallation was successful
        """
        self.set_log_path('uninstall')
        result = self.installer.uninstall()
        self.unset_log_path('uninstall')
        return result

    def find_installed(self)-> InstalledProductInfo:
        """
        Check whether itself is installed by calling find_installed_command.
        """
        result = None
        try:
            result = self.installer.find_installed()
            if result is not None:
                # remove trailing / from the end of
                if result.install_dir and (result.install_dir.startswith('/') or result.install_dir.endswith('\\')):
                    result.install_dir = result.install_dir[:-1]
        except Exception as e:
            raise ProductError("Product {0} find installed command failed ".format(self.name))

        return result

    def get_installed_version(self):
        """
        Searches and returns installed version in current products collection, see Core.current.
        """
        if not self.installed_version:
            # search in current by name if installed_version is empty
            synced_product = self.core.current_storage.feed.get_product(self.name)
            if synced_product:
                # save version if we are found itself in current
                self.installed_version = synced_product.installed_version
        return self.installed_version

    def get_dependencies(self)-> list:
        """
        Returns list of dependencies (product names)
        """
        return self.dependencies or []

    def download(self):
        """
        Downloads files for installation with DownloadManager.
        """
        if self.files:
            downloader = DownloadManager(self.core, self)
            downloader.download(self.files)


    # DEPRECATED
    def set_log_path(self, action: str):
        """
        Sets env variables with log paths. Used in installer.
        :param action: name of current action: 'install', 'uninstall', etc.
        """
        # self.envs['%{0}_LOG_PATH%'.format(action.upper())] = \
        #     LogManager.get_instance(self.core).get_log_path(action)

        # self.envs['%{0}_LOG_DIR%'.format(action.upper())] = \
        #     LogManager.get_instance(self.core).get_log_dir()
        pass

    # DEPRECATED
    def unset_log_path(self, action):
        """
        Removes env variables with log path. Called after installation.
        :param action: name of current action: 'install', 'uninstall', etc.
        """
        pass
        # del self.envs['%{0}_LOG_DIR%'.format(action.upper())]

    def has_search_tokens(self, *tokens)-> bool:
        """
        Checks that product attributes has at least one token from tokens list.
        Used in product search.
        :param tokens: list of string token to search: ['php', 'mysql']
        """
        for token in tokens:
            if not self.has_search_token(token):
                return False
        return True

    def has_search_token(self, token: str)-> bool:
        """
        Checks that search token are in product name, title, description, link or tags.
        Used in product search.
        :param token:
        """
        token = token.strip().lower()
        # search token in:
        # product.name
        if self.name.lower().find(token) >= 0:
            return True
        # product.title
        if self.title.lower().find(token) >= 0:
            return True
        # product.description
        if self.description and self.description.lower().find(token) >= 0:
            return True
        # product.link
        if self.link and self.link.lower().find(token) >= 0:
            return True
        # product.tags
        if self.tags:
            for tag in self.tags:
                if tag.lower().find(token) >= 0:
                    return True
        return False

    def has_upgrade(self)-> bool:
        """
        Checks that installed version is less then product version.
        This used as product attribute in templates for web ui.
        """
        # get installed version
        installed_version = self.get_installed_version()
        if installed_version:
            # compare installed and own version
            if compare_versions(self.version, installed_version) > 0:
                return True
        return False

    def is_upgradable(self)-> bool:
        """
        Check that product can be upgraded.
        This used as product attribute in templates for web ui.
        """
        return bool(self.upgrade_command)

    def get_product_with_version(self)-> str:
        """
        Returns product name with version formatted as 'Product==1.2.3.4'.
        Used in DependencyManager and ProductCollection.
        """
        return "{0}=={1}".format(self.name, self.version)
Exemplo n.º 5
0
    def merge(self, **kwargs):
        """
        Merges product representation in 'kwargs' dict with current product.
        Current product fields are overwritten by values from kwargs.
        :param kwargs: dict with product representation to merge.
        """
        # name of attribute (product, engine, application) with product name
        typename = self.get_typename()
        self.name = kwargs[typename]

        ####
        self.title = kwargs.get('title') or self.title
        self.description = kwargs.get('description') or self.description
        self.link = kwargs.get('link') or self.link
        self.author = kwargs.get('author') or self.author
        self.icon = kwargs.get('icon') or self.icon
        self.tags = kwargs.get('tags') or self.tags
        self.eula = kwargs.get('eula') or self.eula

        self.os = kwargs.get('os') or self.os
        self.bitness = kwargs.get('bitness') or self.bitness
        self.web_server = kwargs.get('webserver') or self.web_server
        self.lang = kwargs.get('lang') or self.lang

        # это поле не читается из ямла, оно создаётся из:
        self.platform = Platform(self.os, self.bitness, self.web_server,
                                 self.lang)

        self.dependencies = kwargs.get('dependencies', []) or self.dependencies

        self.version = str(kwargs.get('version', '')) or self.version
        self.installed_version = str(kwargs.get('installed_version',
                                                '')) or self.installed_version
        self.config = kwargs.get('config') or self.config

        files_list = kwargs.get('files', [])
        if files_list and len(files_list) > 0:
            # create File objects for every file item
            self.files = []
            for f in files_list:
                fs = f.__getstate__() if isinstance(f, File) else f
                if fs.get('file'):
                    self.files.append(File(self, **fs))

        self.install_command = kwargs.get('install_command',
                                          None) or self.install_command
        if self.install_command:
            self.install_command = self.install_command.rstrip()

        self.upgrade_command = kwargs.get('upgrade_command',
                                          None) or self.upgrade_command
        if self.upgrade_command:
            self.upgrade_command = self.upgrade_command.rstrip()

        self.uninstall_command = kwargs.get('uninstall_command',
                                            None) or self.uninstall_command
        if self.uninstall_command:
            self.uninstall_command = self.uninstall_command.rstrip()

        self.find_installed_command = kwargs.get(
            'find_installed_command', None) or self.find_installed_command
        if self.find_installed_command:
            self.find_installed_command = self.find_installed_command.rstrip()

        self.parameters = kwargs.get('parameters', None) or self.parameters
        # TODO must be deprecated
        # create Installer from commands,
        # installer knows to how call install_command, uninstall_command
        self.installer = Installer(self, self.install_command,
                                   self.upgrade_command,
                                   self.uninstall_command,
                                   self.find_installed_command)
Exemplo n.º 6
0
class BaseProduct(object):
    """
    Represent abstract class for product.
    Descendants: Product, Application, Engine.
    """
    def get_typename(self):
        """
        Descendant return string with type name: 'product', 'application' or 'engine'.
        This type name used in yaml represenstion for product:
        - product: Product1
          title: ...
        """
        raise NotImplementedError()

    def __init__(self, core: Core, attrs=None):

        self.data = {}

        # internal
        self.core = core
        # self.envs  do nothing
        self.envs = EnvManager()
        self.installer = None
        # next fields are loaded from yaml
        # meta
        self.name = None
        self.title = None
        self.description = None
        self.link = None
        self.author = None
        self.icon = None
        # string list
        self.tags = []
        self.eula = None

        # fiters
        self.os = None
        self.bitness = None
        self.web_server = None
        self.lang = None
        self.platform = None

        # versions
        self.version = ''
        self.installed_version = ''

        # installer stuff
        self.dependencies = []
        self.files = []
        self.install_command = None
        self.upgrade_command = None
        self.config = None
        self.uninstall_command = None
        self.find_installed_command = None
        self.parameters = {}

        if attrs is not None:
            for item in attrs.keys():
                self.__dict__[item] = attrs[item]

            self.name = attrs[self.get_typename()]

            if attrs.get('files'):
                # create File objects for every file item
                self.files = []
                for f in attrs.get('files', []):
                    if f.get('file'):
                        self.files.append(File(self, **f))

            self.installer = Installer(self, self.install_command,
                                       self.upgrade_command,
                                       self.uninstall_command,
                                       self.find_installed_command)

    def merge(self, **kwargs):
        """
        Merges product representation in 'kwargs' dict with current product.
        Current product fields are overwritten by values from kwargs.
        :param kwargs: dict with product representation to merge.
        """
        # name of attribute (product, engine, application) with product name
        typename = self.get_typename()
        self.name = kwargs[typename]

        ####
        self.title = kwargs.get('title') or self.title
        self.description = kwargs.get('description') or self.description
        self.link = kwargs.get('link') or self.link
        self.author = kwargs.get('author') or self.author
        self.icon = kwargs.get('icon') or self.icon
        self.tags = kwargs.get('tags') or self.tags
        self.eula = kwargs.get('eula') or self.eula

        self.os = kwargs.get('os') or self.os
        self.bitness = kwargs.get('bitness') or self.bitness
        self.web_server = kwargs.get('webserver') or self.web_server
        self.lang = kwargs.get('lang') or self.lang

        # это поле не читается из ямла, оно создаётся из:
        self.platform = Platform(self.os, self.bitness, self.web_server,
                                 self.lang)

        self.dependencies = kwargs.get('dependencies', []) or self.dependencies

        self.version = str(kwargs.get('version', '')) or self.version
        self.installed_version = str(kwargs.get('installed_version',
                                                '')) or self.installed_version
        self.config = kwargs.get('config') or self.config

        files_list = kwargs.get('files', [])
        if files_list and len(files_list) > 0:
            # create File objects for every file item
            self.files = []
            for f in files_list:
                fs = f.__getstate__() if isinstance(f, File) else f
                if fs.get('file'):
                    self.files.append(File(self, **fs))

        self.install_command = kwargs.get('install_command',
                                          None) or self.install_command
        if self.install_command:
            self.install_command = self.install_command.rstrip()

        self.upgrade_command = kwargs.get('upgrade_command',
                                          None) or self.upgrade_command
        if self.upgrade_command:
            self.upgrade_command = self.upgrade_command.rstrip()

        self.uninstall_command = kwargs.get('uninstall_command',
                                            None) or self.uninstall_command
        if self.uninstall_command:
            self.uninstall_command = self.uninstall_command.rstrip()

        self.find_installed_command = kwargs.get(
            'find_installed_command', None) or self.find_installed_command
        if self.find_installed_command:
            self.find_installed_command = self.find_installed_command.rstrip()

        self.parameters = kwargs.get('parameters', None) or self.parameters
        # TODO must be deprecated
        # create Installer from commands,
        # installer knows to how call install_command, uninstall_command
        self.installer = Installer(self, self.install_command,
                                   self.upgrade_command,
                                   self.uninstall_command,
                                   self.find_installed_command)

    def __setattr__(self, name, value):
        self.__dict__[name] = value

    def __getstate__(self):
        """
        Returns ProductState object used in Yaml dumper.
        ProductState is smart OrderedDict wrapper.
        Method saves only non empty fields.
        :rtype : ProductState
        """
        result = ProductState()
        result[self.get_typename()] = self.name

        if self.title:
            result['title'] = self.title
        if self.description:
            result['description'] = Literal(self.description)
        if self.link:
            result['link'] = self.link
        if self.author:
            result['author'] = self.author
        if self.icon:
            result['icon'] = self.icon
        if self.tags:
            result['tags'] = self.tags
        if self.eula:
            result['eula'] = self.eula
        if self.os:
            result['os'] = self.os
        if self.bitness:
            result['bitness'] = self.bitness
        if self.web_server:
            result['web_server'] = self.web_server
        if self.lang:
            result['lang'] = self.lang
        if self.version:
            result['version'] = self.version

        result['installed_version'] = self.get_installed_version()

        if self.dependencies:
            result['dependencies'] = self.dependencies
        if self.files:
            result['files'] = [file.__getstate__() for file in self.files]
        if self.install_command:
            result['install_command'] = Literal(self.install_command)
        if self.upgrade_command:
            result['upgrade_command'] = Literal(self.upgrade_command)
        if self.uninstall_command:
            result['uninstall_command'] = Literal(self.uninstall_command)
        if self.find_installed_command:
            result['find_installed_command'] = Literal(
                self.find_installed_command)

        result['parameters'] = self.parameters or []
        if self.config:
            result["config"] = self.config
        return result

    def to_dict(self, rich=False) -> OrderedDict:
        """
        Dump product fields to OrderedDict used in JSON responses.
        :param rich: dump additional calculated fields.
        """
        product_dict = self.__getstate__().get_dict()
        if rich:
            product_dict['name'] = self.name
            product_dict['has_upgrade'] = self.has_upgrade()
            product_dict['is_upgradable'] = self.is_upgradable()
        return product_dict

    def __repr__(self):
        return '{0}({1}, {2})'.format(self.__class__.__name__, self.name,
                                      self.version or None)

    def is_installed(self) -> bool:
        """
        Check that great or equal version installed.
        Used in DependencyManager and self.install method.
        """
        if not self.installed_version:
            self.get_installed_version()
        if self.installed_version:
            compare_result = compare_versions(self.version,
                                              self.installed_version)
            return compare_result <= 0
        return False

    def is_installed_any_version(self):
        """
        Check that any version of product is installed.
        Used in DependencyManager and self.upgrade method.
        """
        if not self.installed_version:
            self.get_installed_version()
        return bool(self.installed_version)

    def install(self, parameters: dict) -> bool:
        """
        Installs itself:
        Skip installation if product is installed.
        Download files if they are not in cache yet.
        Call installer object with parameters.
        :param parameters: dict with parameters for installation, example: {'install_dir': 'c:\...'}
        :return: whether the installation was successful
        """
        if self.is_installed():
            return False
        # set name for log filename
        self.set_log_path('install')
        self.download()
        result = self.installer.install(parameters)
        self.unset_log_path('install')
        # logging.info("i have finished installing produxt {0}".format( str(result) ) )
        return result

    def upgrade(self, parameters: dict) -> bool:
        """
        Upgrades itself:
        Works like install(), but call 'upgrade' methid of installer.
        Download files if they are not in cache yet.
        Call installer object with parameters.
        :param parameters:
        :return: whether the upgrade was successful
        """
        # set name for lof filename
        self.set_log_path('upgrade')
        self.download()
        result = self.installer.upgrade(parameters)
        self.unset_log_path('upgrade')
        return result

    def uninstall(self):
        """
        Uninstalls itself.
        :return: whether the uninstallation was successful
        """
        self.set_log_path('uninstall')
        result = self.installer.uninstall()
        self.unset_log_path('uninstall')
        return result

    def find_installed(self) -> InstalledProductInfo:
        """
        Check whether itself is installed by calling find_installed_command.
        """
        result = None
        try:
            result = self.installer.find_installed()
            if result is not None:
                # remove trailing / from the end of
                if result.install_dir and (result.install_dir.startswith('/')
                                           or
                                           result.install_dir.endswith('\\')):
                    result.install_dir = result.install_dir[:-1]
        except Exception as e:
            raise ProductError(
                "Product {0} find installed command failed ".format(self.name))

        return result

    def get_installed_version(self):
        """
        Searches and returns installed version in current products collection, see Core.current.
        """
        if not self.installed_version:
            # search in current by name if installed_version is empty
            synced_product = self.core.current_storage.feed.get_product(
                self.name)
            if synced_product:
                # save version if we are found itself in current
                self.installed_version = synced_product.installed_version
        return self.installed_version

    def get_dependencies(self) -> list:
        """
        Returns list of dependencies (product names)
        """
        return self.dependencies or []

    def download(self):
        """
        Downloads files for installation with DownloadManager.
        """
        if self.files:
            downloader = DownloadManager(self.core, self)
            downloader.download(self.files)

    # DEPRECATED
    def set_log_path(self, action: str):
        """
        Sets env variables with log paths. Used in installer.
        :param action: name of current action: 'install', 'uninstall', etc.
        """
        # self.envs['%{0}_LOG_PATH%'.format(action.upper())] = \
        #     LogManager.get_instance(self.core).get_log_path(action)

        # self.envs['%{0}_LOG_DIR%'.format(action.upper())] = \
        #     LogManager.get_instance(self.core).get_log_dir()
        pass

    # DEPRECATED
    def unset_log_path(self, action):
        """
        Removes env variables with log path. Called after installation.
        :param action: name of current action: 'install', 'uninstall', etc.
        """
        pass
        # del self.envs['%{0}_LOG_DIR%'.format(action.upper())]

    def has_search_tokens(self, *tokens) -> bool:
        """
        Checks that product attributes has at least one token from tokens list.
        Used in product search.
        :param tokens: list of string token to search: ['php', 'mysql']
        """
        for token in tokens:
            if not self.has_search_token(token):
                return False
        return True

    def has_search_token(self, token: str) -> bool:
        """
        Checks that search token are in product name, title, description, link or tags.
        Used in product search.
        :param token:
        """
        token = token.strip().lower()
        # search token in:
        # product.name
        if self.name.lower().find(token) >= 0:
            return True
        # product.title
        if self.title.lower().find(token) >= 0:
            return True
        # product.description
        if self.description and self.description.lower().find(token) >= 0:
            return True
        # product.link
        if self.link and self.link.lower().find(token) >= 0:
            return True
        # product.tags
        if self.tags:
            for tag in self.tags:
                if tag.lower().find(token) >= 0:
                    return True
        return False

    def has_upgrade(self) -> bool:
        """
        Checks that installed version is less then product version.
        This used as product attribute in templates for web ui.
        """
        # get installed version
        installed_version = self.get_installed_version()
        if installed_version:
            # compare installed and own version
            if compare_versions(self.version, installed_version) > 0:
                return True
        return False

    def is_upgradable(self) -> bool:
        """
        Check that product can be upgraded.
        This used as product attribute in templates for web ui.
        """
        return bool(self.upgrade_command)

    def get_product_with_version(self) -> str:
        """
        Returns product name with version formatted as 'Product==1.2.3.4'.
        Used in DependencyManager and ProductCollection.
        """
        return "{0}=={1}".format(self.name, self.version)