Changeset 214 for trunk


Ignore:
Timestamp:
03/25/11 18:31:16 (13 years ago)
Author:
tim
Message:

fixed pyregfi circular class references that caused garbage collection problems
renamed several pyregfi properties/methods as "private"

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/python/pyregfi/__init__.py

    r213 r214  
    66
    77import sys
     8import weakref
    89from pyregfi.structures import *
    910
     
    150151#  access to base structures 
    151152class _StructureWrapper(object):
    152     hive = None
    153     base = None
     153    _hive = None
     154    _base = None
    154155
    155156    def __init__(self, hive, base):
    156         self.hive = hive
     157        self._hive = hive
    157158        # XXX: check for NULL here, throw an exception if so.
    158         self.base = base
     159        self._base = base
    159160
    160161    def __del__(self):
    161         regfi.regfi_free_record(self.base)
     162        regfi.regfi_free_record(self._base)
    162163        hive = None
    163164
    164165    def __getattr__(self, name):
    165         return getattr(self.base.contents, name)
     166        return getattr(self._base.contents, name)
    166167
    167168    def __eq__(self, other):
     
    188189
    189190class _GenericList(object):
    190     hive = None
    191     key = None
    192     length = None
    193     current = None
    194 
    195     # implementation-specific functions
    196     fetch_num = None
    197     find_element = None
    198     get_element = None
    199     constructor = None
     191    _hive = None
     192    _key = None
     193    _length = None
     194    _current = None
     195
     196    # implementation-specific functions for _SubkeyList and _ValueList
     197    _fetch_num = None
     198    _find_element = None
     199    _get_element = None
     200    _constructor = None
    200201
    201202    def __init__(self, key):
    202         self.hive = key.hive
     203        self._hive = key._hive
     204
     205        # Normally it's good to avoid cyclic references like this
     206        # (key.list.key...) but in this case it makes ctypes memory
     207        # management easier to reference the Key instead of the base
     208        # structure.  We use a weak reference in order to allow for garbage
     209        # collection, since value/subkey lists should not be usable if their
     210        # parent Key is freed anyway.
     211
    203212        # XXX: check for NULL here, throw an exception if so.
    204         self.key = key
    205         self.length = self.fetch_num(key.base)
    206    
    207     def __del__(self):
    208         self.key = None
    209 
     213        self._key = weakref.proxy(key)
     214        self._length = self._fetch_num(key._base)
     215
     216   
    210217    def __len__(self):
    211         return self.length
     218        return self._length
    212219
    213220    def __getitem__(self, name):
     
    219226            name = create_string_buffer(bytes(name))
    220227
    221         if self.find_element(self.hive.file, self.key.base, name, byref(index)):
    222             return self.constructor(self.hive, self.get_element(self.hive.file,
    223                                                                 self.key.base,
    224                                                                 index))
     228        if self._find_element(self._hive.file, self._key.base, name, byref(index)):
     229            return self._constructor(self._hive,
     230                                     self._get_element(self._hive.file,
     231                                                       self._key.base,
     232                                                       index))
    225233        raise KeyError('')
    226234
     
    232240   
    233241    def __iter__(self):
    234         self.current = 0
     242        self._current = 0
    235243        return self
    236244   
    237245    def __next__(self):
    238         if self.current >= self.length:
     246        if self._current >= self._length:
    239247            raise StopIteration('')
    240248
    241         elem = self.get_element(self.hive.file, self.key.base,
    242                                 c_uint32(self.current))
    243         self.current += 1
    244         return self.constructor(self.hive, elem)
     249        elem = self._get_element(self._hive.file, self._key._base,
     250                                c_uint32(self._current))
     251        self._current += 1
     252        return self._constructor(self._hive, elem)
    245253   
    246254    # For Python 2.x
    247     def next(self):
    248         return self.__next__()
     255    next = __next__
    249256
    250257
    251258class _SubkeyList(_GenericList):
    252     fetch_num = regfi.regfi_fetch_num_subkeys
    253     find_element = regfi.regfi_find_subkey
    254     get_element = regfi.regfi_get_subkey
     259    _fetch_num = regfi.regfi_fetch_num_subkeys
     260    _find_element = regfi.regfi_find_subkey
     261    _get_element = regfi.regfi_get_subkey
    255262
    256263
    257264class _ValueList(_GenericList):
    258     fetch_num = regfi.regfi_fetch_num_values
    259     find_element = regfi.regfi_find_value
    260     get_element = regfi.regfi_get_value
     265    _fetch_num = regfi.regfi_fetch_num_values
     266    _find_element = regfi.regfi_find_value
     267    _get_element = regfi.regfi_get_value
    261268
    262269
     
    287294
    288295    def fetch_security(self):
    289         return Security(self.hive,
    290                         regfi.regfi_fetch_sk(self.hive.file, self.base))
     296        return Security(self._hive,
     297                        regfi.regfi_fetch_sk(self._hive.file, self.base))
    291298
    292299
     
    300307        ret_val = None
    301308        if name == "data":
    302             data_p = regfi.regfi_fetch_data(self.hive.file, self.base)
     309            data_p = regfi.regfi_fetch_data(self._hive.file, self.base)
    303310            try:
    304311                data_struct = data_p.contents
     
    330337        elif name == "data_raw":
    331338            # XXX: should we load the data without interpretation instead?
    332             data_p = regfi.regfi_fetch_data(self.hive.file, self.base)
     339            data_p = regfi.regfi_fetch_data(self._hive.file, self.base)
    333340            try:
    334341                data_struct = data_p.contents
     
    357364# Avoids chicken/egg class definitions.
    358365# Also makes for convenient code reuse in these lists' parent classes.
    359 _SubkeyList.constructor = Key
    360 _ValueList.constructor = Value
     366_SubkeyList._constructor = Key
     367_ValueList._constructor = Value
    361368
    362369
     
    427434            raise Exception("Could not create iterator.  Current log:\n"
    428435                            + GetLogMessages())
    429         self.hive = hive
     436        self._hive = hive
    430437       
    431438    def __getattr__(self, name):
     
    463470
    464471    # For Python 2.x
    465     def next(self):
    466         return self.__next__()
     472    next = __next__
    467473
    468474    def down(self):
     
    484490
    485491    def current_key(self):
    486         return Key(self.hive, regfi.regfi_iterator_cur_key(self.iter))
     492        return Key(self._hive, regfi.regfi_iterator_cur_key(self.iter))
    487493
    488494    #XXX Add subkey/value search accessor functions (?)
Note: See TracChangeset for help on using the changeset viewer.