~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/_dirstate_helpers_pyx.pyx

Add bzrlib.pyutils, which has get_named_object, a wrapper around __import__.

This is used to replace various ad hoc implementations of the same logic,
notably the version used in registry's _LazyObjectGetter which had a bug when
getting a module without also getting a member.  And of course, this new
function has unit tests, unlike the replaced code.

This also adds a KnownHooksRegistry subclass to provide a more natural home for
some other logic.

I'm not thrilled about the name of the new module or the new functions, but it's
hard to think of good names for such generic functionality.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2007, 2008, 2010 Canonical Ltd
 
1
# Copyright (C) 2007-2010 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
118
118
    # ??? memrchr is a GNU extension :(
119
119
    # void *memrchr(void *s, int c, size_t len)
120
120
 
 
121
# cimport all of the definitions we will need to access
 
122
from _static_tuple_c cimport import_static_tuple_c, StaticTuple, \
 
123
    StaticTuple_New, StaticTuple_SET_ITEM
 
124
 
 
125
import_static_tuple_c()
121
126
 
122
127
cdef void* _my_memrchr(void *s, int c, size_t n): # cannot_raise
123
128
    # memrchr seems to be a GNU extension, so we have to implement it ourselves
610
615
        :param new_block: This is to let the caller know that it needs to
611
616
            create a new directory block to store the next entry.
612
617
        """
613
 
        cdef object path_name_file_id_key
 
618
        cdef StaticTuple path_name_file_id_key
 
619
        cdef StaticTuple tmp
614
620
        cdef char *entry_size_cstr
615
621
        cdef unsigned long int entry_size
616
622
        cdef char* executable_cstr
650
656
        # Build up the key that will be used.
651
657
        # By using <object>(void *) Pyrex will automatically handle the
652
658
        # Py_INCREF that we need.
653
 
        path_name_file_id_key = (<object>p_current_dirname[0],
654
 
                                 self.get_next_str(),
655
 
                                 self.get_next_str(),
656
 
                                )
 
659
        cur_dirname = <object>p_current_dirname[0]
 
660
        # Use StaticTuple_New to pre-allocate, rather than creating a regular
 
661
        # tuple and passing it to the StaticTuple constructor.
 
662
        # path_name_file_id_key = StaticTuple(<object>p_current_dirname[0],
 
663
        #                          self.get_next_str(),
 
664
        #                          self.get_next_str(),
 
665
        #                         )
 
666
        tmp = StaticTuple_New(3)
 
667
        Py_INCREF(cur_dirname); StaticTuple_SET_ITEM(tmp, 0, cur_dirname)
 
668
        cur_basename = self.get_next_str()
 
669
        cur_file_id = self.get_next_str()
 
670
        Py_INCREF(cur_basename); StaticTuple_SET_ITEM(tmp, 1, cur_basename)
 
671
        Py_INCREF(cur_file_id); StaticTuple_SET_ITEM(tmp, 2, cur_file_id)
 
672
        path_name_file_id_key = tmp
657
673
 
658
674
        # Parse all of the per-tree information. current has the information in
659
675
        # the same location as parent trees. The only difference is that 'info'
677
693
            executable_cstr = self.get_next(&cur_size)
678
694
            is_executable = (executable_cstr[0] == c'y')
679
695
            info = self.get_next_str()
680
 
            PyList_Append(trees, (
 
696
            # TODO: If we want to use StaticTuple_New here we need to be pretty
 
697
            #       careful. We are relying on a bit of Pyrex
 
698
            #       automatic-conversion from 'int' to PyInt, and that doesn't
 
699
            #       play well with the StaticTuple_SET_ITEM macro.
 
700
            #       Timing doesn't (yet) show a worthwile improvement in speed
 
701
            #       versus complexity and maintainability.
 
702
            # tmp = StaticTuple_New(5)
 
703
            # Py_INCREF(minikind); StaticTuple_SET_ITEM(tmp, 0, minikind)
 
704
            # Py_INCREF(fingerprint); StaticTuple_SET_ITEM(tmp, 1, fingerprint)
 
705
            # Py_INCREF(entry_size); StaticTuple_SET_ITEM(tmp, 2, entry_size)
 
706
            # Py_INCREF(is_executable); StaticTuple_SET_ITEM(tmp, 3, is_executable)
 
707
            # Py_INCREF(info); StaticTuple_SET_ITEM(tmp, 4, info)
 
708
            # PyList_Append(trees, tmp)
 
709
            PyList_Append(trees, StaticTuple(
681
710
                minikind,     # minikind
682
711
                fingerprint,  # fingerprint
683
712
                entry_size,   # size
1219
1248
            else:
1220
1249
                try:
1221
1250
                    source_parent_id = self.old_dirname_to_file_id[old_dirname]
1222
 
                except KeyError:
 
1251
                except KeyError, _:
1223
1252
                    source_parent_entry = self.state._get_entry(self.source_index,
1224
1253
                                                           path_utf8=old_dirname)
1225
1254
                    source_parent_id = source_parent_entry[0][2]
1236
1265
            else:
1237
1266
                try:
1238
1267
                    target_parent_id = self.new_dirname_to_file_id[new_dirname]
1239
 
                except KeyError:
 
1268
                except KeyError, _:
1240
1269
                    # TODO: We don't always need to do the lookup, because the
1241
1270
                    #       parent entry will be the same as the source entry.
1242
1271
                    target_parent_entry = self.state._get_entry(self.target_index,
1478
1507
            # interface doesn't require it.
1479
1508
            try:
1480
1509
                self.current_root = self.search_specific_files.pop()
1481
 
            except KeyError:
 
1510
            except KeyError, _:
1482
1511
                raise StopIteration()
1483
1512
            self.searched_specific_files.add(self.current_root)
1484
1513
            # process the entries for this containing directory: the rest will be
1567
1596
                        #            and e.winerror == ERROR_DIRECTORY
1568
1597
                        try:
1569
1598
                            e_winerror = e.winerror
1570
 
                        except AttributeError:
 
1599
                        except AttributeError, _:
1571
1600
                            e_winerror = None
1572
1601
                        win_errors = (ERROR_DIRECTORY, ERROR_PATH_NOT_FOUND)
1573
1602
                        if (e.errno in win_errors or e_winerror in win_errors):
1656
1685
                    try:
1657
1686
                        self.current_dir_info = self.dir_iterator.next()
1658
1687
                        self.current_dir_list = self.current_dir_info[1]
1659
 
                    except StopIteration:
 
1688
                    except StopIteration, _:
1660
1689
                        self.current_dir_info = None
1661
1690
                else: #(dircmp > 0)
1662
1691
                    # We have a dirblock entry for this location, but there
1803
1832
                                and stat.S_IEXEC & current_path_info[3].st_mode)
1804
1833
                            try:
1805
1834
                                relpath_unicode = self.utf8_decode(current_path_info[0])[0]
1806
 
                            except UnicodeDecodeError:
 
1835
                            except UnicodeDecodeError, _:
1807
1836
                                raise errors.BadFilenameEncoding(
1808
1837
                                    current_path_info[0], osutils._fs_enc)
1809
1838
                            if changed is not None:
1851
1880
                try:
1852
1881
                    self.current_dir_info = self.dir_iterator.next()
1853
1882
                    self.current_dir_list = self.current_dir_info[1]
1854
 
                except StopIteration:
 
1883
                except StopIteration, _:
1855
1884
                    self.current_dir_info = None
1856
1885
 
1857
1886
    cdef object _next_consistent_entries(self):