source: sasview/src/sas/sasgui/guiframe/CategoryInstaller.py @ f5f8553

Last change on this file since f5f8553 was cb64d86, checked in by Paul Kienzle <pkienzle@…>, 6 years ago

src/sas/sasgui/guiframe/CategoryInstaller.py

consistent python 2/3 handling of json dump

  • Property mode set to 100644
File size: 6.4 KB
Line 
1"""
2Class for making sure all category stuff is installed
3and works fine.
4
5Copyright (c) Institut Laue-Langevin 2012
6
7@author kieranrcampbell@gmail.com
8@modified by NIST/MD sasview team
9"""
10
11import os
12import sys
13import json
14import logging
15from collections import defaultdict, OrderedDict
16
17from sas import get_user_dir
18
19USER_FILE = 'categories.json'
20
21logger = logging.getLogger(__name__)
22
23if sys.version_info[0] > 2:
24    def json_dump(obj, filename):
25        with open(filename, 'w', newline='\n') as fd:
26            json.dump(obj, fd)
27else: # CRUFT: python 2.7 support
28    def json_dump(obj, filename):
29        with open(filename, 'wb') as fd:
30            json.dump(obj, fd)
31
32class CategoryInstaller(object):
33    """
34    Class for making sure all category stuff is installed
35
36    Note - class is entirely static!
37    """
38
39    @staticmethod
40    def _get_installed_model_dir():
41        """
42        returns the dir where installed_models.txt should be
43        """
44        from sas.sascalc.dataloader.readers import get_data_path
45        return get_data_path()
46
47    @staticmethod
48    def _get_default_cat_file_dir():
49        """
50        returns the dir where default_cat.j should be
51        """
52        # The default categories file is usually found with the code, except
53        # when deploying using py2app (it will be in Contents/Resources), or
54        # py2exe (it will be in the exec dir).
55        import sas.sasview
56        cat_file = "default_categories.json"
57
58        possible_cat_file_paths = [
59            os.path.join(os.path.split(sas.sasview.__file__)[0], cat_file),           # Source
60            os.path.join(os.path.dirname(sys.executable), '..', 'Resources', cat_file), # Mac
61            os.path.join(os.path.dirname(sys.executable), cat_file)                     # Windows
62        ]
63
64        for path in possible_cat_file_paths:
65            if os.path.isfile(path):
66                return os.path.dirname(path)
67
68        raise RuntimeError('CategoryInstaller: Could not find folder containing default categories')
69
70    @staticmethod
71    def _get_home_dir():
72        """
73        returns the users sasview config dir
74        """
75        return os.path.join(os.path.expanduser("~"), ".sasview")
76
77    @staticmethod
78    def _regenerate_model_dict(master_category_dict):
79        """
80        regenerates self.by_model_dict which has each model name as the key
81        and the list of categories belonging to that model
82        along with the enabled mapping
83        returns tuplet (by_model_dict, model_enabled_dict)
84        """
85        by_model_dict = defaultdict(list)
86        model_enabled_dict = defaultdict(bool)
87
88        for category in master_category_dict:
89            for (model, enabled) in master_category_dict[category]:
90                by_model_dict[model].append(category)
91                model_enabled_dict[model] = enabled
92
93        return (by_model_dict, model_enabled_dict)
94
95    @staticmethod
96    def _regenerate_master_dict(by_model_dict, model_enabled_dict):
97        """
98        regenerates master_category_dict from by_model_dict
99        and model_enabled_dict
100        returns the master category dictionary
101        """
102        master_category_dict = defaultdict(list)
103        for model in by_model_dict:
104            for category in by_model_dict[model]:
105                master_category_dict[category].append(\
106                    (model, model_enabled_dict[model]))
107        return OrderedDict(sorted(master_category_dict.items(), key=lambda t: t[0]))
108
109    @staticmethod
110    def get_user_file():
111        """
112        returns the user data file, eg .sasview/categories.json.json
113        """
114        return os.path.join(get_user_dir(), USER_FILE)
115
116    @staticmethod
117    def get_default_file():
118        logger.warning("CategoryInstaller.get_default_file is deprecated.")
119
120    @staticmethod
121    def check_install(homedir = None, model_list=None):
122        """
123        Makes sure categories.json exists and if not compile it and install.
124
125        This is the main method of this class.
126
127        :param homefile: Override the default home directory
128        :param model_list: List of model names except those in
129            Plugin Models which are user supplied.
130        """
131        _model_dict = {model.name: model for model in model_list}
132        _model_list = list(_model_dict.keys())
133
134        serialized_file = None
135        if homedir is None:
136            serialized_file = CategoryInstaller.get_user_file()
137        else:
138            serialized_file = os.path.join(homedir, USER_FILE)
139        if os.path.isfile(serialized_file):
140            with open(serialized_file, 'rb') as f:
141                master_category_dict = json.load(f)
142        else:
143            master_category_dict = defaultdict(list)
144
145        (by_model_dict, model_enabled_dict) = \
146                CategoryInstaller._regenerate_model_dict(master_category_dict)
147        add_list = _model_list
148        del_name = False
149        for cat in master_category_dict.keys():
150            for ind in range(len(master_category_dict[cat])):
151                model_name, enabled = master_category_dict[cat][ind]
152                if model_name not in _model_list:
153                    del_name = True
154                    try:
155                        by_model_dict.pop(model_name)
156                        model_enabled_dict.pop(model_name)
157                    except Exception as exc:
158                        logger.error("CategoryInstaller: %s", exc)
159                else:
160                    add_list.remove(model_name)
161        if del_name or (len(add_list) > 0):
162            for model in add_list:
163                model_enabled_dict[model] = True
164                # TODO: should be:  not _model_dict[model].category
165                if (_model_dict[model].category is None
166                        or len(str(_model_dict[model].category.capitalize())) == 0):
167                    by_model_dict[model].append('Uncategorized')
168                else:
169                    category = _model_dict[model].category
170                    toks = category.split(':')
171                    category = toks[-1]
172                    toks = category.split('-')
173                    capitalized_words = [t.capitalize() for t in toks]
174                    category = ' '.join(capitalized_words)
175
176                    by_model_dict[model].append(category)
177
178            master_category_dict = \
179                CategoryInstaller._regenerate_master_dict(by_model_dict,
180                                                          model_enabled_dict)
181
182            json_dump(master_category_dict, serialized_file)
Note: See TracBrowser for help on using the repository browser.