Exemple #1
0
    def test_region_CI_monkey_patch(self):
        """Test if the  patch is apply on the good version of the lib
        And test some phonenumbers"""
        if not phonenumbers:
            self.skipTest('Cannot test without phonenumbers module installed.')
        # MONKEY PATCHING phonemetadata of Ivory Coast if phonenumbers is too old
        if parse_version('7.6.1') <= parse_version(
                phonenumbers.__version__) < parse_version('8.12.32'):
            # check that _local_load_region is set to `odoo.addons.phone_validation.lib.phonenumbers_patch._local_load_region`
            # check that you can load a new ivory coast phone number without error
            parsed_phonenumber_1 = phonenumbers.parse("20 25/35-51 ",
                                                      region="CI",
                                                      keep_raw_input=True)
            self.assertEqual(
                parsed_phonenumber_1.national_number, 20253551,
                "The national part of the phonenumber should be 22522586")
            self.assertEqual(parsed_phonenumber_1.country_code, 225,
                             "The country code of Ivory Coast is 225")

            parsed_phonenumber_2 = phonenumbers.parse("+225 22 52 25 86 ",
                                                      region="CI",
                                                      keep_raw_input=True)
            self.assertEqual(
                parsed_phonenumber_2.national_number, 22522586,
                "The national part of the phonenumber should be 22522586")
            self.assertEqual(parsed_phonenumber_2.country_code, 225,
                             "The country code of Ivory Coast is 225")
        else:
            self.assertFalse(
                hasattr(phonenumbers_patch, '_local_load_region'),
                "The code should not be monkey patched with phonenumbers > 8.12.32."
            )
Exemple #2
0
 def parse(self, incoming):
     if isinstance(incoming, OdooVersion):
         self.vstring = incoming.vstring
         self.components = incoming.components
     else:
         self.vstring = incoming
         self.components = parse_version(incoming)
Exemple #3
0
 def _get_migration_versions(pkg):
     versions = sorted({
         ver
         for lv in self.migrations[pkg.name].values()
         for ver, lf in lv.items()
         if lf
     }, key=lambda k: parse_version(convert_version(k)))
     return versions
Exemple #4
0
    def update_list(self):
        res = [0, 0]  # [update, add]

        default_version = modules.adapt_version('1.0')
        known_mods = self.search([])
        known_mods_names = {mod.name: mod for mod in known_mods}

        # iterate through detected modules and update/create them in db
        for mod_name in modules.get_modules():
            mod = known_mods_names.get(mod_name)
            terp = self.get_module_info(mod_name)
            values = self.get_values_from_terp(terp)

            if mod:
                updated_values = {}
                for key in values:
                    old = getattr(mod, key)
                    updated = tools.ustr(values[key]) if isinstance(
                        values[key], basestring) else values[key]
                    if (old or updated) and updated != old:
                        updated_values[key] = values[key]
                if terp.get('installable',
                            True) and mod.state == 'uninstallable':
                    updated_values['state'] = 'uninstalled'
                if parse_version(terp.get(
                        'version', default_version)) > parse_version(
                            mod.latest_version or default_version):
                    res[0] += 1
                if updated_values:
                    mod.write(updated_values)
            else:
                mod_path = modules.get_module_path(mod_name)
                if not mod_path:
                    continue
                if not terp or not terp.get('installable', True):
                    continue
                mod = self.create(
                    dict(name=mod_name, state='uninstalled', **values))
                res[1] += 1

            mod._update_dependencies(terp.get('depends', []))
            mod._update_exclusions(terp.get('excludes', []))
            mod._update_category(terp.get('category', 'Uncategorized'))

        return res
Exemple #5
0
 def _get_migration_versions(pkg):
     versions = list(set(
         ver
         for lv in self.migrations[pkg.name].values()
         for ver, lf in lv.items()
         if lf
     ))
     versions.sort(key=lambda k: parse_version(convert_version(k)))
     return versions
Exemple #6
0
        def _get_migration_versions(pkg):
            def __get_dir(tree):
                return [d for d in tree if tree[d] is not None]

            versions = list(set(
                __get_dir(self.migrations[pkg.name]['module']) +
                __get_dir(self.migrations[pkg.name]['maintenance'])
            ))
            versions.sort(key=lambda k: parse_version(convert_version(k)))
            return versions
Exemple #7
0
    def update_list(self):
        res = [0, 0]    # [update, add]

        default_version = modules.adapt_version('1.0')
        known_mods = self.with_context(lang=None).search([])
        known_mods_names = {mod.name: mod for mod in known_mods}

        # iterate through detected modules and update/create them in db
        for mod_name in modules.get_modules():
            mod = known_mods_names.get(mod_name)
            terp = self.get_module_info(mod_name)
            values = self.get_values_from_terp(terp)

            if mod:
                updated_values = {}
                for key in values:
                    old = getattr(mod, key)
                    updated = tools.ustr(values[key]) if isinstance(values[key], pycompat.string_types) else values[key]
                    if (old or updated) and updated != old:
                        updated_values[key] = values[key]
                if terp.get('installable', True) and mod.state == 'uninstallable':
                    updated_values['state'] = 'uninstalled'
                if parse_version(terp.get('version', default_version)) > parse_version(mod.latest_version or default_version):
                    res[0] += 1
                if updated_values:
                    mod.write(updated_values)
            else:
                mod_path = modules.get_module_path(mod_name)
                if not mod_path:
                    continue
                if not terp or not terp.get('installable', True):
                    continue
                mod = self.create(dict(name=mod_name, state='uninstalled', **values))
                res[1] += 1

            mod._update_dependencies(terp.get('depends', []))
            mod._update_exclusions(terp.get('excludes', []))
            mod._update_category(terp.get('category', 'Uncategorized'))

        return res
Exemple #8
0
 def _get_migration_versions(pkg, stage):
     versions = list(
         set(ver for lv in self.migrations[pkg.name].values()
             for ver, lf in lv.items() if lf))
     versions.sort(key=lambda k: parse_version(convert_version(k)))
     if "0.0.0" in versions:
         # reorder versions
         versions.remove("0.0.0")
         if stage == "pre":
             versions.insert(0, "0.0.0")
         else:
             versions.append("0.0.0")
     return versions
Exemple #9
0
 def _get_migration_versions(pkg):
     versions = list(
         set(ver for lv in self.migrations[pkg.name].values()
             for ver, lf in lv.items() if lf))
     versions.sort(key=lambda k: parse_version(convert_version(k)))
     return versions
Exemple #10
0
    def migrate_module(self, pkg, stage):
        assert stage in ('pre', 'post', 'end')
        stageformat = {
            'pre': '[>%s]',
            'post': '[%s>]',
            'end': '[$%s]',
        }
        state = pkg.state if stage in ('pre', 'post') else getattr(
            pkg, 'load_state', None)

        if not (hasattr(pkg, 'update')
                or state == 'to upgrade') or state == 'to install':
            return

        def convert_version(version):
            if version.count('.') >= 2:
                return version  # the version number already containt the server version
            return "%s.%s" % (release.major_version, version)

        def _get_migration_versions(pkg):
            versions = list(
                set(ver for lv in self.migrations[pkg.name].values()
                    for ver, lf in lv.items() if lf))
            versions.sort(key=lambda k: parse_version(convert_version(k)))
            return versions

        def _get_migration_files(pkg, version, stage):
            """ return a list of migration script files
            """
            m = self.migrations[pkg.name]
            lst = []

            mapping = {
                'module': opj(pkg.name, 'migrations'),
                'maintenance': opj('base', 'maintenance', 'migrations',
                                   pkg.name),
            }

            for x in mapping.keys():
                if version in m.get(x):
                    for f in m[x][version]:
                        if not f.startswith(stage + '-'):
                            continue
                        lst.append(opj(mapping[x], version, f))
            lst.sort()
            return lst

        parsed_installed_version = parse_version(
            getattr(pkg, 'load_version', pkg.installed_version) or '')
        current_version = parse_version(convert_version(pkg.data['version']))

        versions = _get_migration_versions(pkg)

        for version in versions:
            if parsed_installed_version < parse_version(
                    convert_version(version)) <= current_version:

                strfmt = {
                    'addon': pkg.name,
                    'stage': stage,
                    'version': stageformat[stage] % version,
                }

                for pyfile in _get_migration_files(pkg, version, stage):
                    name, ext = os.path.splitext(os.path.basename(pyfile))
                    if ext.lower() != '.py':
                        continue
                    mod = fp = fp2 = None
                    try:
                        fp, fname = tools.file_open(pyfile, pathinfo=True)

                        # FIXME: imp.load_source removed in P3, and so is the ``file`` object...
                        if not isinstance(fp, file):  # pylint: disable=file-builtin
                            # imp.load_source need a real file object, so we create
                            # one from the file-like object we get from file_open
                            fp2 = os.tmpfile()
                            fp2.write(fp.read())
                            fp2.seek(0)
                        try:
                            mod = imp.load_source(name, fname, fp2 or fp)
                            _logger.info(
                                'module %(addon)s: Running migration %(version)s %(name)s'
                                % dict(strfmt, name=mod.__name__))
                            migrate = mod.migrate
                        except ImportError:
                            _logger.exception(
                                'module %(addon)s: Unable to load %(stage)s-migration file %(file)s'
                                % dict(strfmt, file=pyfile))
                            raise
                        except AttributeError:
                            _logger.error(
                                'module %(addon)s: Each %(stage)s-migration file must have a "migrate(cr, installed_version)" function'
                                % strfmt)
                        else:
                            migrate(self.cr, pkg.installed_version)
                    finally:
                        if fp:
                            fp.close()
                        if fp2:
                            fp2.close()
                        if mod:
                            del mod
Exemple #11
0
    def migrate_module(self, pkg, stage):
        assert stage in ('pre', 'post', 'end')
        stageformat = {
            'pre': '[>%s]',
            'post': '[%s>]',
            'end': '[$%s]',
        }
        state = pkg.state if stage in ('pre', 'post') else getattr(
            pkg, 'load_state', None)

        # In openupgrade, also run migration scripts upon installation.
        # We want to always pass in pre and post migration files and use a new
        # argument in the migrate decorator (explained in the docstring)
        # to decide if we want to do something if a new module is installed
        # during the migration.
        if not (hasattr(pkg, 'update')
                or state in ('to upgrade', 'to install')):
            return

        def convert_version(version):
            if version.count('.') >= 2:
                return version  # the version number already containt the server version
            return "%s.%s" % (release.major_version, version)

        def _get_migration_versions(pkg, stage):
            versions = sorted(
                {
                    ver
                    for lv in self.migrations[pkg.name].values()
                    for ver, lf in lv.items() if lf
                },
                key=lambda k: parse_version(convert_version(k)))
            if "0.0.0" in versions:
                # reorder versions
                versions.remove("0.0.0")
                if stage == "pre":
                    versions.insert(0, "0.0.0")
                else:
                    versions.append("0.0.0")
            return versions

        def _get_migration_files(pkg, version, stage):
            """ return a list of migration script files
            """
            m = self.migrations[pkg.name]
            lst = []

            mapping = {
                'module': opj(pkg.name, 'migrations'),
                'module_upgrades': opj(pkg.name, 'upgrades'),
            }

            for path in odoo.upgrade.__path__:
                if os.path.exists(opj(path, pkg.name)):
                    mapping['upgrade'] = opj(path, pkg.name)
                    break

            for x in mapping:
                if version in m.get(x):
                    for f in m[x][version]:
                        if not f.startswith(stage + '-'):
                            continue
                        lst.append(opj(mapping[x], version, f))
            lst.sort()
            return lst

        installed_version = getattr(pkg, 'load_version',
                                    pkg.installed_version) or ''
        parsed_installed_version = parse_version(installed_version)
        current_version = parse_version(convert_version(pkg.data['version']))

        versions = _get_migration_versions(pkg, stage)

        for version in versions:
            if ((version == "0.0.0"
                 and parsed_installed_version < current_version)
                    or parsed_installed_version < parse_version(
                        convert_version(version)) <= current_version):

                strfmt = {
                    'addon': pkg.name,
                    'stage': stage,
                    'version': stageformat[stage] % version,
                }

                for pyfile in _get_migration_files(pkg, version, stage):
                    name, ext = os.path.splitext(os.path.basename(pyfile))
                    if ext.lower() != '.py':
                        continue
                    mod = None
                    try:
                        mod = load_script(pyfile, name)
                        _logger.info(
                            'module %(addon)s: Running migration %(version)s %(name)s'
                            % dict(strfmt, name=mod.__name__))
                        migrate = mod.migrate
                    except ImportError:
                        _logger.exception(
                            'module %(addon)s: Unable to load %(stage)s-migration file %(file)s'
                            % dict(strfmt, file=pyfile))
                        raise
                    except AttributeError:
                        _logger.error(
                            'module %(addon)s: Each %(stage)s-migration file must have a "migrate(cr, installed_version)" function'
                            % strfmt)
                    else:
                        migrate(self.cr, installed_version)
                    finally:
                        if mod:
                            del mod
Exemple #12
0
    def migrate_module(self, pkg, stage):
        assert stage in ('pre', 'post')
        stageformat = {
            'pre': '[>%s]',
            'post': '[%s>]',
        }

        if not (hasattr(pkg, 'update') or pkg.state == 'to upgrade') or pkg.state == 'to install':
            return

        def convert_version(version):
            if version.count('.') >= 2:
                return version  # the version number already containt the server version
            return "%s.%s" % (release.major_version, version)

        def _get_migration_versions(pkg):
            def __get_dir(tree):
                return [d for d in tree if tree[d] is not None]

            versions = list(set(
                __get_dir(self.migrations[pkg.name]['module']) +
                __get_dir(self.migrations[pkg.name]['maintenance'])
            ))
            versions.sort(key=lambda k: parse_version(convert_version(k)))
            return versions

        def _get_migration_files(pkg, version, stage):
            """ return a list of tuple (module, file)
            """
            m = self.migrations[pkg.name]
            lst = []

            mapping = {
                'module': opj(pkg.name, 'migrations'),
                'maintenance': opj('base', 'maintenance', 'migrations', pkg.name),
            }

            for x in mapping.keys():
                if version in m[x]:
                    for f in m[x][version]:
                        if m[x][version][f] is not None:
                            continue
                        if not f.startswith(stage + '-'):
                            continue
                        lst.append(opj(mapping[x], version, f))
            lst.sort()
            return lst

        parsed_installed_version = parse_version(pkg.installed_version or '')
        current_version = parse_version(convert_version(pkg.data['version']))

        versions = _get_migration_versions(pkg)

        for version in versions:
            if parsed_installed_version < parse_version(convert_version(version)) <= current_version:

                strfmt = {'addon': pkg.name,
                          'stage': stage,
                          'version': stageformat[stage] % version,
                          }

                for pyfile in _get_migration_files(pkg, version, stage):
                    name, ext = os.path.splitext(os.path.basename(pyfile))
                    if ext.lower() != '.py':
                        continue
                    mod = fp = fp2 = None
                    try:
                        fp, fname = tools.file_open(pyfile, pathinfo=True)

                        if not isinstance(fp, file):
                            # imp.load_source need a real file object, so we create
                            # one from the file-like object we get from file_open
                            fp2 = os.tmpfile()
                            fp2.write(fp.read())
                            fp2.seek(0)
                        try:
                            mod = imp.load_source(name, fname, fp2 or fp)
                            _logger.info('module %(addon)s: Running migration %(version)s %(name)s' % dict(strfmt, name=mod.__name__))
                            migrate = mod.migrate
                        except ImportError:
                            _logger.exception('module %(addon)s: Unable to load %(stage)s-migration file %(file)s' % dict(strfmt, file=pyfile))
                            raise
                        except AttributeError:
                            _logger.error('module %(addon)s: Each %(stage)s-migration file must have a "migrate(cr, installed_version)" function' % strfmt)
                        else:
                            migrate(self.cr, pkg.installed_version)
                    finally:
                        if fp:
                            fp.close()
                        if fp2:
                            fp2.close()
                        if mod:
                            del mod
Exemple #13
0
# http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# https://github.com/google/libphonenumber

from odoo.tools.parse_version import parse_version

try:
    import phonenumbers
    # MONKEY PATCHING phonemetadata of Ivory Coast if phonenumbers is too old
    if parse_version('7.6.1') <= parse_version(
            phonenumbers.__version__) < parse_version('8.12.32'):

        def _local_load_region(code):
            __import__("region_%s" % code,
                       globals(),
                       locals(),
                       fromlist=["PHONE_METADATA_%s" % code],
                       level=1)

        # loading updated region_CI.py from current directory
        # https://github.com/daviddrysdale/python-phonenumbers/blob/v8.12.32/python/phonenumbers/data/region_CI.py
        phonenumbers.phonemetadata.PhoneMetadata.register_region_loader(
            'CI', _local_load_region)
except ImportError:
    pass
Exemple #14
0
    def migrate_module(self, pkg, stage):
        assert stage in ('pre', 'post', 'end')
        stageformat = {
            'pre': '[>%s]',
            'post': '[%s>]',
            'end': '[$%s]',
        }
        state = pkg.state if stage in ('pre', 'post') else getattr(pkg, 'load_state', None)

        if not (hasattr(pkg, 'update') or state == 'to upgrade') or state == 'to install':
            return

        def convert_version(version):
            if version.count('.') >= 2:
                return version  # the version number already containt the server version
            return "%s.%s" % (release.major_version, version)

        def _get_migration_versions(pkg):
            versions = sorted({
                ver
                for lv in self.migrations[pkg.name].values()
                for ver, lf in lv.items()
                if lf
            }, key=lambda k: parse_version(convert_version(k)))
            return versions

        def _get_migration_files(pkg, version, stage):
            """ return a list of migration script files
            """
            m = self.migrations[pkg.name]
            lst = []

            mapping = {
                'module': opj(pkg.name, 'migrations'),
                'maintenance': opj('base', 'maintenance', 'migrations', pkg.name),
            }

            for x in mapping:
                if version in m.get(x):
                    for f in m[x][version]:
                        if not f.startswith(stage + '-'):
                            continue
                        lst.append(opj(mapping[x], version, f))
            lst.sort()
            return lst

        installed_version = getattr(pkg, 'load_version', pkg.installed_version) or ''
        parsed_installed_version = parse_version(installed_version)
        current_version = parse_version(convert_version(pkg.data['version']))

        versions = _get_migration_versions(pkg)

        for version in versions:
            if parsed_installed_version < parse_version(convert_version(version)) <= current_version:

                strfmt = {'addon': pkg.name,
                          'stage': stage,
                          'version': stageformat[stage] % version,
                          }

                for pyfile in _get_migration_files(pkg, version, stage):
                    name, ext = os.path.splitext(os.path.basename(pyfile))
                    if ext.lower() != '.py':
                        continue
                    mod = None
                    try:
                        mod = load_script(pyfile, name)
                        _logger.info('module %(addon)s: Running migration %(version)s %(name)s' % dict(strfmt, name=mod.__name__))
                        migrate = mod.migrate
                    except ImportError:
                        _logger.exception('module %(addon)s: Unable to load %(stage)s-migration file %(file)s' % dict(strfmt, file=pyfile))
                        raise
                    except AttributeError:
                        _logger.error('module %(addon)s: Each %(stage)s-migration file must have a "migrate(cr, installed_version)" function' % strfmt)
                    else:
                        migrate(self.cr, installed_version)
                    finally:
                        if mod:
                            del mod
Exemple #15
0
    def migrate_module(self, pkg, stage):
        assert stage in ('pre', 'post', 'end')
        stageformat = {
            'pre': '[>%s]',
            'post': '[%s>]',
            'end': '[$%s]',
        }
        state = pkg.state if stage in ('pre', 'post') else getattr(pkg, 'load_state', None)

        if not (hasattr(pkg, 'update') or state == 'to upgrade') or state == 'to install':
            return

        def convert_version(version):
            if version.count('.') >= 2:
                return version  # the version number already containt the server version
            return "%s.%s" % (release.major_version, version)

        def _get_migration_versions(pkg):
            versions = sorted({
                ver
                for lv in pycompat.values(self.migrations[pkg.name])
                for ver, lf in pycompat.items(lv)
                if lf
            }, key=lambda k: parse_version(convert_version(k)))
            return versions

        def _get_migration_files(pkg, version, stage):
            """ return a list of migration script files
            """
            m = self.migrations[pkg.name]
            lst = []

            mapping = {
                'module': opj(pkg.name, 'migrations'),
                'maintenance': opj('base', 'maintenance', 'migrations', pkg.name),
            }

            for x in mapping:
                if version in m.get(x):
                    for f in m[x][version]:
                        if not f.startswith(stage + '-'):
                            continue
                        lst.append(opj(mapping[x], version, f))
            lst.sort()
            return lst

        parsed_installed_version = parse_version(getattr(pkg, 'load_version', pkg.installed_version) or '')
        current_version = parse_version(convert_version(pkg.data['version']))

        versions = _get_migration_versions(pkg)

        for version in versions:
            if parsed_installed_version < parse_version(convert_version(version)) <= current_version:

                strfmt = {'addon': pkg.name,
                          'stage': stage,
                          'version': stageformat[stage] % version,
                          }

                for pyfile in _get_migration_files(pkg, version, stage):
                    name, ext = os.path.splitext(os.path.basename(pyfile))
                    if ext.lower() != '.py':
                        continue
                    mod = fp = fp2 = None
                    try:
                        fp, fname = tools.file_open(pyfile, pathinfo=True)

                        # FIXME: imp.load_source removed in P3, and so is the ``file`` object...
                        if not isinstance(fp, file):# pylint: disable=file-builtin
                            # imp.load_source need a real file object, so we create
                            # one from the file-like object we get from file_open
                            fp2 = os.tmpfile()
                            fp2.write(fp.read())
                            fp2.seek(0)
                        try:
                            mod = imp.load_source(name, fname, fp2 or fp)
                            _logger.info('module %(addon)s: Running migration %(version)s %(name)s' % dict(strfmt, name=mod.__name__))
                            migrate = mod.migrate
                        except ImportError:
                            _logger.exception('module %(addon)s: Unable to load %(stage)s-migration file %(file)s' % dict(strfmt, file=pyfile))
                            raise
                        except AttributeError:
                            _logger.error('module %(addon)s: Each %(stage)s-migration file must have a "migrate(cr, installed_version)" function' % strfmt)
                        else:
                            migrate(self.cr, pkg.installed_version)
                    finally:
                        if fp:
                            fp.close()
                        if fp2:
                            fp2.close()
                        if mod:
                            del mod
Exemple #16
0
    def migrate_module(self, pkg, stage):
        assert stage in ('pre', 'post', 'end')
        stageformat = {
            'pre': '[>%s]',
            'post': '[%s>]',
            'end': '[$%s]',
        }
        state = pkg.state if stage in ('pre', 'post') else getattr(
            pkg, 'load_state', None)

        # In openupgrade, also run migration scripts upon installation.
        # We want to always pass in pre and post migration files and use a new
        # argument in the migrate decorator (explained in the docstring)
        # to decide if we want to do something if a new module is installed
        # during the migration.
        if not (hasattr(pkg, 'update')
                or state in ('to upgrade', 'to install')):
            return

        def convert_version(version):
            if version.count('.') >= 2:
                return version  # the version number already containt the server version
            return "%s.%s" % (release.major_version, version)

        def _get_migration_versions(pkg):
            versions = list(
                set(ver for lv in self.migrations[pkg.name].values()
                    for ver, lf in lv.items() if lf))
            versions.sort(key=lambda k: parse_version(convert_version(k)))
            return versions

        def _get_migration_files(pkg, version, stage):
            """ return a list of migration script files
            """
            m = self.migrations[pkg.name]
            lst = []

            mapping = {
                'module': opj(pkg.name, 'migrations'),
                'maintenance': opj('base', 'maintenance', 'migrations',
                                   pkg.name),
            }

            for x in mapping.keys():
                if version in m.get(x):
                    for f in m[x][version]:
                        if not f.startswith(stage + '-'):
                            continue
                        lst.append(opj(mapping[x], version, f))
            lst.sort()
            return lst

        def mergedict(a, b):
            a = a.copy()
            a.update(b)
            return a

        parsed_installed_version = parse_version(
            getattr(pkg, 'load_version', pkg.installed_version) or '')
        current_version = parse_version(convert_version(pkg.data['version']))

        versions = _get_migration_versions(pkg)

        for version in versions:
            if parsed_installed_version < parse_version(
                    convert_version(version)) <= current_version:

                strfmt = {
                    'addon': pkg.name,
                    'stage': stage,
                    'version': stageformat[stage] % version,
                }

                for pyfile in _get_migration_files(pkg, version, stage):
                    name, ext = os.path.splitext(os.path.basename(pyfile))
                    if ext.lower() != '.py':
                        continue
                    # OpenUpgrade edit start:
                    # Removed a copy of migration script to temp directory
                    # Replaced call to load_source with load_module so frame isn't lost and breakpoints can be set
                    mod = fp = None
                    try:
                        fp, pathname = tools.file_open(pyfile, pathinfo=True)
                        try:
                            mod = imp.load_module(name, fp, pathname,
                                                  ('.py', 'r', imp.PY_SOURCE))
                            _logger.info(
                                'module %(addon)s: Running migration %(version)s %(name)s',
                                mergedict({'name': mod.__name__}, strfmt))
                        except ImportError:
                            _logger.exception(
                                'module %(addon)s: Unable to load %(stage)s-migration file %(file)s',
                                mergedict({'file': pyfile}, strfmt))
                            raise

                        _logger.info(
                            'module %(addon)s: Running migration %(version)s %(name)s',
                            mergedict({'name': mod.__name__}, strfmt))

                        if hasattr(mod, 'migrate'):
                            mod.migrate(self.cr, pkg.installed_version)
                        else:
                            _logger.error(
                                'module %(addon)s: Each %(stage)s-migration file must have a "migrate(cr, installed_version)" function',
                                strfmt)
                    finally:
                        if fp:
                            fp.close()
                        if mod:
                            del mod