Changeset 214


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"

Files:
2 edited

Legend:

Unmodified
Added
Removed
  • test/pyregfi-smoketest.py

    r213 r214  
    3434                value_rawlens += len(v.name_raw)
    3535
    36     print("  Counts: keys=%d, values=%d\n" % (key_count, value_count))
    37     print("  Total name length: keys=%d, values=%d\n" % (key_lens, value_lens))
    38     print("  Total raw name lengths: keys=%d, values=%d\n" % (key_rawlens, value_rawlens))
     36    print("  Counts: keys=%d, values=%d" % (key_count, value_count))
     37    print("  Total name length: keys=%d, values=%d" % (key_lens, value_lens))
     38    print("  Total raw name lengths: keys=%d, values=%d" % (key_rawlens, value_rawlens))
    3939
    4040
     
    6060        print
    6161    hive = None
    62     gc.collect()
    6362
    6463files = None
    6564tests = None
    6665gc.collect()
    67 print gc.garbage
     66#print(gc.garbage)
  • 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.