diff --git a/apps/installation/classes.py b/apps/installation/classes.py index bbc0df076f..603bcd28b0 100644 --- a/apps/installation/classes.py +++ b/apps/installation/classes.py @@ -1,6 +1,25 @@ +from __future__ import absolute_import + +from collections import namedtuple +import os +import sys + +import pbs + +try: + from pbs import pip + PIP = True +except pbs.CommandNotFound: + PIP = False + +from django.conf import settings from django.utils.simplejson import dumps +class PIPNotFound(Exception): + pass + + class PropertyNamespace(object): _registry = {} @@ -73,3 +92,75 @@ class Property(object): def __str__(self): return str(self.value) + + +Dependency = namedtuple('Dependency', 'name, version, standard') + + +class VirtualEnv(object): + def extract_dependency(self, string): + string = str(string.strip()) + + try: + package, version = string.split('==') + except ValueError: + # item is not installed from package, svn/git maybe + try: + version, package = string.split('=') + except: + # has no version number + return Dependency(string, version=None, standard=True) + else: + version = version.split('#')[0].split(' ')[1] # Get rid of '#egg' and '-e' + return Dependency(package, version, standard=False) + else: + return Dependency(package, version, standard=True) + + + def get_packages_info(self, requirements_file=None): + if requirements_file: + with open(requirements_file) as file_in: + for line in file_in.readlines(): + yield self.extract_dependency(line) + else: + for item in pip('freeze').splitlines(): + yield self.extract_dependency(item) + + + def __init__(self): + self.requirements_file_path = os.path.join(settings.PROJECT_ROOT, 'requirements', 'production.txt') + if not PIP: + raise PIPNotFound + + + def get_results(self): + requirements = {} + installed_packages = {} + + for item in self.get_packages_info(self.requirements_file_path): + requirements[item.name] = item + + for item in self.get_packages_info(): + installed_packages[item.name] = item + + for name, item in requirements.items(): + try: + if item.standard: + if item.version: + if item.version == installed_packages[name].version: + status = item.version + else: + status = installed_packages[name].version + else: + status = None + else: + # Non standard version number, check SVN or GIT path + if item.version == installed_packages['%s-dev' % name.replace('-', '_')].version: + status = item.version + else: + status = installed_packages['%s-dev' % name.replace('-', '_')].version + except KeyError: + # Not installed package found matching with name matchin requirement + status = False + + yield name, item.version, status diff --git a/apps/installation/models.py b/apps/installation/models.py index 1779b83c14..d05f698eed 100644 --- a/apps/installation/models.py +++ b/apps/installation/models.py @@ -30,7 +30,7 @@ from main import __version__ as mayan_version from lock_manager import Lock, LockError from ocr.conf.settings import TESSERACT_PATH, UNPAPER_PATH, PDFTOTEXT_PATH -from .classes import Property, PropertyNamespace +from .classes import Property, PropertyNamespace, VirtualEnv, PIPNotFound FORM_SUBMIT_URL = 'https://docs.google.com/spreadsheet/formResponse' FORM_KEY = 'dGZrYkw3SDl5OENMTG15emp1UFFEUWc6MQ' @@ -129,12 +129,23 @@ class Installation(Singleton): namespace.add_property('headcommit_committed_date', _(u'HEAD commit committed date'), time.asctime(time.gmtime(headcommit.committed_date)), report=True) namespace.add_property('headcommit_message', _(u'HEAD commit message'), headcommit.message, report=True) + def virtualenv_properties(self): + namespace = PropertyNamespace('venv', _(u'VirtuanEnv')) + try: + venv = VirtualEnv() + except PIPNotFound: + namespace.add_property('pip', 'pip', _(u'pip not found.'), report=True) + else: + for item, version, result in venv.get_results(): + namespace.add_property(item, '%s (%s)' % (item, version), result, report=True) + def set_properties(self): self._properties = SortedDict() self.os_properties() self.binary_dependencies() self.mayan_properties() self.git_properties() + self.virtualenv_properties() def __getattr__(self, name): self.set_properties()