home *** CD-ROM | disk | FTP | other *** search
/ Windows News 2005 November / WNnov2005.iso / Windows / Equipement / Blender / blender-2.37a-windows.exe / $_5_ / .blender / scripts / bpymodules / BPyRegistry.py < prev    next >
Text File  |  2005-04-30  |  8KB  |  255 lines

  1. # --------------------------------------------------------------------------
  2. # Module BPyRegistry version 0.1
  3. #   Helper functions to store / restore configuration data.
  4. # --------------------------------------------------------------------------
  5. # $Id: BPyRegistry.py,v 1.2 2005/04/21 19:44:52 ianwill Exp $
  6. #
  7. # ***** BEGIN GPL LICENSE BLOCK *****
  8. #
  9. # Copyright (C) 2004: Willian P. Germano, wgermano _at_ ig.com.br
  10. #
  11. # This program is free software; you can redistribute it and/or
  12. # modify it under the terms of the GNU General Public License
  13. # as published by the Free Software Foundation; either version 2
  14. # of the License, or (at your option) any later version.
  15. #
  16. # This program is distributed in the hope that it will be useful,
  17. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.    See the
  19. # GNU General Public License for more details.
  20. #
  21. # You should have received a copy of the GNU General Public License
  22. # along with this program; if not, write to the Free Software Foundation,
  23. # --------------------------------------------------------------------------
  24.  
  25. # The Registry is a Python dictionary that is kept in Blender for as long as
  26. # the program is running, where scripts can store / restore persistent data
  27. # (data that is not lost when the script exits).  This module provides
  28. # functions to save and restore Registry entries as config data in the
  29. # bpydata/config folder.  Scripts just need to give an extra parameter to
  30. # the Blender.Registry.Get/Set() functions to have their data automatically
  31. # saved and restored when needed.
  32. #
  33. # Note: entries starting with an underscore are not saved, so script authors
  34. # can use that fact to define data that is not meant to be stored in a
  35. # config file.  Example: data to be passed to another script and references to
  36. # invalid data, like Blender objects and any function or method.
  37. #
  38. # Check the Blender.Registry documentation for more information.
  39.  
  40. import Blender
  41. from Blender import Registry, sys as bsys
  42.  
  43. _EXT = '.cfg' # file extension for saved config data
  44.  
  45. # limits:
  46. MAX_ITEMS_NUM = 60 # max number of keys per dict and itens per list and tuple
  47. MAX_STR_LEN = 300 # max string length (remember this is just for config data)
  48.  
  49. _CFG_DIR = ''
  50. if Blender.Get('udatadir'):
  51.     _CFG_DIR = Blender.sys.join(Blender.Get('udatadir'), 'config')
  52. if not _CFG_DIR or not bsys.exists(_CFG_DIR):
  53.     _CFG_DIR = Blender.sys.join(Blender.Get('datadir'), 'config')
  54. if not bsys.exists(_CFG_DIR):
  55.     _CFG_DIR = ''
  56.  
  57. # to compare against, so we don't write to a cvs tree:
  58. _CVS_SUBPATH = 'release/scripts/bpydata/config/'
  59. if bsys.dirsep == '\\':
  60.     _CVS_SUBPATH = _CVS_SUBPATH.replace('/', '\\')
  61.  
  62. _KEYS = [k for k in Registry.Keys() if k[0] != '_']
  63.  
  64. _ITEMS_NUM = 0
  65.  
  66. def _sanitize(o):
  67.     "Check recursively that all objects are valid, set invalid ones to None"
  68.  
  69.     global MAX_ITEMS_NUM, MAX_STR_LEN, _ITEMS_NUM
  70.  
  71.     valid_types = [int, float, bool, long, type]
  72.     valid_checked_types = [str, unicode]
  73.     # Only very simple types are considered valid for configuration data,
  74.   # functions, methods and Blender objects (use their names instead) aren't.
  75.  
  76.     t = type(o)
  77.  
  78.     if t == dict:
  79.         keys = o.keys()
  80.         len_keys = len(keys)
  81.         _ITEMS_NUM += len_keys
  82.         if _ITEMS_NUM > MAX_ITEMS_NUM:
  83.             return None
  84.         for k in keys:
  85.             o[k] = _sanitize(o[k])
  86.     elif t in [list, tuple]:
  87.         len_seq = len(o)
  88.         _ITEMS_NUM += len_seq
  89.         if _ITEMS_NUM > MAX_ITEMS_NUM:
  90.             return None
  91.         result = []
  92.         for i in o: result.append(_sanitize(i))
  93.         return result
  94.     elif t in valid_types:
  95.         return o
  96.     elif t in valid_checked_types:
  97.         if len(o) > MAX_STR_LEN:
  98.             o = o[:MAX_STR_LEN]
  99.         return o
  100.     else: return None
  101.  
  102.     return o
  103.  
  104.  
  105. def _dict_to_str(name, d):
  106.     "Return a pretty-print version of the passed dictionary"
  107.  
  108.     if name: l = ['%s = {' % name]
  109.     else: l = ['{']
  110.     keys = d.keys()
  111.     for k in keys:
  112.         if type(d[k]) == dict:
  113.             l.append("'%s': %s" % (k, _dict_to_str(None, d[k])))
  114.         else:
  115.             l.append("'%s': %s," % (k, repr(d[k])))
  116.     if name: l.append('}')
  117.     else: l.append('},')
  118.     return "\n".join(l)
  119.  
  120. _HELP_MSG = """
  121. Please create a valid scripts config dir tree either by
  122. copying release/scripts/ tree to your <blenderhome> dir
  123. or by copying release/scripts/bpydata/ tree to a user
  124. defined scripts dir that you can set in the 
  125. User Preferences -> Paths tab -> Python path input box.
  126. """
  127.  
  128. def _check_dir():
  129.     global _CFG_DIR, _CVS_SUBPATH, _HELP_MSG
  130.  
  131.     if not _CFG_DIR:
  132.         errmsg = "scripts config dir not found!\n%s" % _HELP_MSG
  133.         raise IOError, errmsg
  134.     elif _CFG_DIR.find(_CVS_SUBPATH) > 0:
  135.         errmsg = """
  136. Your scripts config dir:\n%s
  137. seems to reside in your local Blender's cvs tree.\n%s""" % (_CFG_DIR, _HELP_MSG)
  138.         raise SystemError, errmsg
  139.     else: return
  140.  
  141.  
  142. # API:
  143.  
  144. BPY_KEY_MISSING = 0
  145. BPY_KEY_IN_REGISTRY = 1
  146. BPY_KEY_IN_FILE = 2
  147.  
  148. def HasConfigData (key):
  149.     """
  150.     Check if the given key exists, either already loaded in the Registry dict or
  151.     as a file in the script data config dir.
  152.     @type key: string
  153.     @param key: a given key name.
  154.     @returns:
  155.         - 0: key does not exist;
  156.         - 1: key exists in the Registry dict only;
  157.         - 2: key exists as a file only;
  158.         - 3: key exists in the Registry dict and also as a file.
  159.     @note: for readability it's better to check against the constant bitmasks
  160.         BPY_KEY_MISSING = 0, BPY_KEY_IN_REGISTRY = 1 and BPY_KEY_IN_FILE = 2.
  161.     """
  162.  
  163.     fname = bsys.join(_CFG_DIR, "%s%s" % (key, _EXT))
  164.  
  165.     result = BPY_KEY_MISSING
  166.     if key in Registry.Keys(): result |= BPY_KEY_IN_REGISTRY
  167.     if bsys.exists(fname): result |= BPY_KEY_IN_FILE
  168.  
  169.     return result
  170.  
  171.  
  172. def LoadConfigData (key = None):
  173.     """
  174.     Load config data from file(s) to the Registry dictionary.
  175.     @type key: string
  176.     @param key: a given key name.  If None (default), all available keys are
  177.         loaded.
  178.     @returns: None
  179.     """
  180.  
  181.     _check_dir()
  182.  
  183.     import os
  184.  
  185.     if not key:
  186.         files = \
  187.             [bsys.join(_CFG_DIR, f) for f in os.listdir(_CFG_DIR) if f[-4:] == _EXT]
  188.     else:
  189.         files = []
  190.         fname = bsys.join(_CFG_DIR, "%s%s" % (key, _EXT))
  191.         if bsys.exists(fname): files.append(fname)
  192.  
  193.     for p in files:
  194.         f = file(p, 'r')
  195.         lines = f.readlines()
  196.         f.close()
  197.         mainkey = lines[0].split('=')[0].strip()
  198.         pysrc = "\n".join(lines)
  199.         exec(pysrc)
  200.         exec("Registry.SetKey('%s', %s)" % (str(mainkey), mainkey))
  201.  
  202.  
  203. def RemoveConfigData (key = None):
  204.     """
  205.     Remove this key's config file from the <(u)datadir>/config/ folder.
  206.     @type key: string
  207.     @param key: the name of the key to be removed.  If None (default) all
  208.         available config files are deleted.
  209.     """
  210.  
  211.     _check_dir()
  212.  
  213.     if not key:
  214.         files = \
  215.             [bsys.join(_CFG_DIR, f) for f in os.listdir(_CFG_DIR) if f[-4:] == _EXT]
  216.     else:
  217.         files = []
  218.         fname = bsys.join(_CFG_DIR, "%s%s" % (key, _EXT))
  219.         if bsys.exists(fname): files.append(fname)
  220.  
  221.     import os
  222.  
  223.     for p in files:
  224.         os.remove(p) # remove the file(s)
  225.  
  226.  
  227. def SaveConfigData (key = None):
  228.     """
  229.     Save Registry key(s) as file(s) in the <(u)datadir>/config/ folder.
  230.     @type key: string
  231.     @param key: the name of the key to be saved.  If None (default) all
  232.         available keys are saved.
  233.     """
  234.  
  235.     global _KEYS, _CFG_DIR
  236.  
  237.     _check_dir()
  238.  
  239.     if key: keys = [key]
  240.     else: keys = _KEYS
  241.  
  242.     for mainkey in keys:
  243.         cfgdict = Registry.GetKey(mainkey).copy()
  244.         for k in cfgdict.keys():
  245.             if k[0] == '_': cfgdict.pop(k)
  246.  
  247.         if not cfgdict: continue
  248.  
  249.         filename = bsys.join(_CFG_DIR, "%s%s" % (mainkey, _EXT))
  250.         f = file(filename, 'w')
  251.         output = _dict_to_str(mainkey, _sanitize(cfgdict))
  252.         f.write(output)
  253.         f.close()
  254.  
  255.