def test_upgrade_step_variavel_hidden_profiles_deps_brasil_gov_portal(self): # NOQA """ Testa se todos os upgradeSteps de brasil.gov.portal que possuem profile estão nas variáveis HIDDEN_PROFILES e DEPS. Outros pacotes podem ser adicionados em outros testes. """ upgradeSteps = listUpgradeSteps(self.st, self.profile, '') upgrades = [upgrade[0]['dest'][0] for upgrade in upgradeSteps] upgrades_hidden_profiles = [] upgrades_deps = [] prefix = 'brasil.gov.portal.upgrades.v%s' profile = self.profile.split(':')[-1] installable_profiles = self.qi.listInstallableProfiles() for upgrade in upgrades: upgrade_profile = prefix % upgrade # Verifica somente upgrades que possuem profiles if upgrade_profile in installable_profiles: upgrades_deps.append(upgrade_profile) upgrades_hidden_profiles.append( '{0}:{1}'.format(upgrade_profile, profile)) self.assertTrue(all(upgrade in HIDDEN_PROFILES for upgrade in upgrades_hidden_profiles)) self.assertTrue(all(upgrade in DEPS for upgrade in upgrades_deps))
def doUpgrades(context): ''' If exists, run migrations ''' if context.readDataFile('collective.cdn.core.txt') is None: return logger = logging.getLogger(_PROJECT) site = context.getSite() setup_tool = getToolByName(site, 'portal_setup') cache = getToolByName(context, 'portal_cache_settings', None) enable_cache = False version = setup_tool.getLastVersionForProfile(_PROFILE_ID) upgradeSteps = listUpgradeSteps(setup_tool, _PROFILE_ID, version) sorted(upgradeSteps, key=lambda step: int(step['sortkey'])) if cache and cache.getEnabled(): # In case we have a cache fu, disable it to avoid a # tsunami of purges cache.setEnabled(False) enable_cache = True for step in upgradeSteps: oStep = step.get('step') if oStep is not None: oStep.doStep(setup_tool) msg = "Ran upgrade step %s for profile %s" % (oStep.title, _PROFILE_ID) setup_tool.setLastVersionForProfile(_PROFILE_ID, oStep.dest) logger.info(msg) if cache and enable_cache: # Now, turn cachefu back to normal cache.setEnabled(True)
def run_upgrade_steps(context): """ Run Upgrade steps """ if context.readDataFile('%s_various.txt' % PROJECTNAME) is None: return logger = logging.getLogger(PROJECTNAME) site = context.getSite() setup_tool = getToolByName(site, 'portal_setup') version = setup_tool.getLastVersionForProfile(_PROFILE_ID) upgradeSteps = listUpgradeSteps(setup_tool, _PROFILE_ID, version) flatten_steps = [] for step in upgradeSteps: if isinstance(step, list): for inner_step in step: flatten_steps.append(inner_step) else: flatten_steps.append(step) for step in flatten_steps: oStep = step.get('step') if oStep is not None: oStep.doStep(setup_tool) msg = "Ran upgrade step %s for profile %s" % (oStep.title, _PROFILE_ID) setup_tool.setLastVersionForProfile(_PROFILE_ID, oStep.dest) logger.info(msg)
def doUpgrades(context): ''' If exists, run migrations ''' if context.readDataFile('collective.portlet.calendar.txt') is None: return logger = logging.getLogger(_PROJECT) site = context.getSite() setup_tool = getToolByName(site,'portal_setup') cache = CACHEFU and getToolByName(context,'portal_cache_settings',None) version = setup_tool.getLastVersionForProfile(_PROFILE_ID) upgradeSteps = listUpgradeSteps(setup_tool,_PROFILE_ID, version) sorted(upgradeSteps,key=lambda step:step['sortkey']) if cache: # Desabilitamos o cache fu para nao termos uma enxurrada # de purges cache.setEnabled(False) for step in upgradeSteps: oStep = step.get('step') if oStep is not None: oStep.doStep(setup_tool) msg = "Ran upgrade step %s for profile %s" % (oStep.title, _PROFILE_ID) setup_tool.setLastVersionForProfile(_PROFILE_ID, oStep.dest) logger.info(msg) if cache: # Novamente habilitamos o cache fu para nao termos uma enxurrada # de purges cache.setEnabled(True)
def doUpgrades(context): """ If exists, run migrations """ if context.readDataFile("collective.cdn.core.txt") is None: return logger = logging.getLogger(_PROJECT) site = context.getSite() setup_tool = getToolByName(site, "portal_setup") cache = getToolByName(context, "portal_cache_settings", None) enable_cache = False version = setup_tool.getLastVersionForProfile(_PROFILE_ID) upgradeSteps = listUpgradeSteps(setup_tool, _PROFILE_ID, version) sorted(upgradeSteps, key=lambda step: int(step["sortkey"])) if cache and cache.getEnabled(): # In case we have a cache fu, disable it to avoid a # tsunami of purges cache.setEnabled(False) enable_cache = True for step in upgradeSteps: oStep = step.get("step") if oStep is not None: oStep.doStep(setup_tool) msg = "Ran upgrade step %s for profile %s" % (oStep.title, _PROFILE_ID) setup_tool.setLastVersionForProfile(_PROFILE_ID, oStep.dest) logger.info(msg) if cache and enable_cache: # Now, turn cachefu back to normal cache.setEnabled(True)
def test_to1020_available(self): upgradeSteps = listUpgradeSteps(self.st, self.profile, '1000') step = [step for step in upgradeSteps if (step[0]['dest'] in (('1010',), ('1020',))) and (step[0]['source'] in (('1000',), ('1010',)))] self.assertEqual(len(step), 2)
def test_registered(self): # Manually call grok machinery gs_module = 'collective.grok.tests.gs.upgrade' grokcore.component.testing.grok(gs_module) # Now we should have a upgrade step for this profile steps = listUpgradeSteps(self.st, 'collective.grok:fake', '0.0') self.assertTrue(len(steps), 'Upgrade step should be registered')
def test_to2000_available(self): upgradeSteps = listUpgradeSteps(self.st, self.profile, '1000') step = [ step for step in upgradeSteps if (step[0]['dest'] == ( '2000', )) and (step[0]['source'] == ('1000', )) ] self.assertEqual(len(step), 1)
def executa_upgrade(self, source, dest): # Setamos o profile para versao source self.st.setLastVersionForProfile(self.profile, source) # Pegamos os upgrade steps upgradeSteps = listUpgradeSteps(self.st, self.profile, source) steps = [step for step in upgradeSteps if (step[0]["dest"] == (dest,)) and (step[0]["source"] == (source,))][0] # Os executamos for step in steps: step["step"].doStep(self.st)
def list_upgrades(self, source, destination): upgradeSteps = listUpgradeSteps(self.st, self.profile, source) if source == "0": source = (source, "0") else: source = (source,) step = [step for step in upgradeSteps if (step[0]["dest"] == (destination,)) and (step[0]["source"] == source)] return step
def test_to4002_available(self): upgradeSteps = listUpgradeSteps(self.st, self.profile, '4001') step = [step for step in upgradeSteps if (step[0]['dest'] == ('4002',)) and (step[0]['source'] == ('4001',))] self.assertEqual(len(step), 1)
def runUpgradeStep(self, source, dest): usd = listUpgradeSteps(self.ps, 'Products.FacultyStaffDirectory:default', None) ourstepdict = [ step for step in usd if source in step['source'] and dest in step['dest'] ][0] ourstep = ourstepdict['step'] ourstep.doStep(self.ps)
def test_to2000_available(self): upgradeSteps = listUpgradeSteps(self.st, self.profile, '1000') step = [step for step in upgradeSteps if (step[0]['dest'] == ('2000',)) and (step[0]['source'] == ('1000',))] self.assertEquals(len(step), 1)
def test_to1010_available(self): upgradeSteps = listUpgradeSteps(self.st, self.profile, '1000') step = [step for step in upgradeSteps if (step[0]['dest'] == ('1010',)) and (step[0]['source'] == ('1000',))] # upgrade step registration is being skiped for now self.assertEqual(len(step), 0)
def test_to1000_from0(self): upgradeSteps = listUpgradeSteps(self.st, self.profile, '0.0') step = [ step for step in upgradeSteps if (step['dest'] == ('1000', )) and (step['source'] == ('0', '0')) ] step[0].get('step').doStep(self.st) # Testamos a versao do profile self.assertEquals(self.st.getLastVersionForProfile(self.profile), (u'1000', ))
def test_run_upgrade(self): gs_module = 'collective.grok.tests.gs.upgrade' grokcore.component.testing.grok(gs_module) # Get the steps steps = listUpgradeSteps(self.st, 'collective.grok:fake', '0.0') # Get the step oStep = steps[0].get('step') # Execute it oStep.doStep(self.st) self.assertTrue(self.portal.title == 'Changed Title', 'Upgrade step was not executed')
def _executa_atualizacao(self, source, dest): upgradeSteps = listUpgradeSteps(self.st, self.profile, source) if source == '0.0': source = ('0', '0') else: source = (source, ) step = [step for step in upgradeSteps[0] if (step['dest'] == (dest,)) and (step['source'] == source)][0] step.get('step').doStep(self.st)
def test_to0003(self): pt = api.portal.get_tool("portal_types") pt["Workspace"].behaviors = ("foo", IWorkspace.__identifier__, "bar") ps = api.portal.get_tool("portal_setup") upgrade_steps = listUpgradeSteps(ps, "collective.workspace:default", "0002") for upgrade_step in upgrade_steps: upgrade_step["step"].doStep(ps) self.assertTupleEqual( pt["Workspace"].behaviors, ("foo", "collective.workspace.team_workspace", "bar"), )
def list_upgrades(self, source, destination): upgradeSteps = listUpgradeSteps(self.st, self.profile, source) if source == '0': source = (source, '0') else: source = (source, ) step = [ step for step in upgradeSteps if (step[0]['dest'] == ( destination, )) and (step[0]['source'] == source) ] return step
def test_to1000_from0(self): upgradeSteps = listUpgradeSteps(self.st, self.profile, '0.0') step = [step for step in upgradeSteps if (step['dest'] == ('1000',)) and (step['source'] == ('0', '0'))] step[0].get('step').doStep(self.st) # Testamos a versao do profile self.assertEquals(self.st.getLastVersionForProfile(self.profile), (u'1000',))
def test_upgrade(self): from Products.GenericSetup.upgrade import listUpgradeSteps setup = self.portal.portal_setup steps = listUpgradeSteps(setup, PROFILE, None) step_id = steps[0]['id'] request = self.portal.REQUEST request.form['upgrades'] = [step_id] request.form['profile_id'] = PROFILE setup.manage_doUpgrades() jsregistry = self.portal.portal_javascripts sarissa = jsregistry.getResource('sarissa.js') self.failUnless(sarissa is None)
def list_upgrades(self, source, destination): upgradeSteps = listUpgradeSteps(self.st, self.profile, source) if source == '0': source = (source, '0') else: source = (source, ) step = [ step for step in upgradeSteps if (step[0]['dest'] == (destination,)) and (step[0]['source'] == source) ] return step
def executa_upgrade(self, source, dest): # Setamos o profile para versao source self.st.setLastVersionForProfile(self.profile, source) # Pegamos os upgrade steps upgradeSteps = listUpgradeSteps(self.st, self.profile, source) steps = [step for step in upgradeSteps if (step[0]['dest'] == (dest,)) and (step[0]['source'] == (source,))][0] # Os executamos for step in steps: step['step'].doStep(self.st)
def __call__(self, product, sourceversion): context = aq_inner(self.context) request = self.request for plonesite in listPloneSites(context): setup = getattr(plonesite, 'portal_setup', None) profile_id = '%s:default' % product request.form['profile_id'] = profile_id steps = listUpgradeSteps(setup, profile_id, tuple(sourceversion)) #import pdb; pdb.set_trace() step_id = steps[0][0]['id'] request.form['upgrades'] = [step_id] upgrade = setup.manage_doUpgrades() return upgrade
def test_ultimo_upgrade_igual_metadata_xml_filesystem(self): """Testa se o número do último upgradeStep disponível é o mesmo do metadata.xml do profile. É também útil para garantir que para toda alteração feita no version do metadata.xml tenha um upgradeStep associado. """ from Products.GenericSetup.upgrade import listUpgradeSteps profile_id = PROJECTNAME + ':default' upgrade_info = self.qi.upgradeInfo(PROJECTNAME) upgradeSteps = listUpgradeSteps(self.st, profile_id, '') upgrades = [upgrade[0]['dest'][0] for upgrade in upgradeSteps] last_upgrade = sorted(upgrades, key=int)[-1] self.assertEqual(upgrade_info['installedVersion'], last_upgrade)
def test_ultimo_upgrade_igual_metadata_xml_filesystem(self): """ Testa se o número do último upgradeStep disponível é o mesmo do metadata.xml do profile. É também útil para garantir que para toda alteração feita no version do metadata.xml tenha um upgradeStep associado. Esse teste parte da premissa que o número dos upgradeSteps é sempre sequencial. """ upgrade_info = self.qi.upgradeInfo(PROJECTNAME) upgradeSteps = listUpgradeSteps(self.st, self.profile, '') upgrades = [upgrade[0]['dest'][0] for upgrade in upgradeSteps] last_upgrade = sorted(upgrades, key=int)[-1] self.assertEqual(upgrade_info['installedVersion'], last_upgrade)
def testAddDefaultPlonePasswordPolicy(self): # this add the 'Default Plone Password Policy' to Plone's acl_users portal = self.portal # make sure the 'Default Plone Password Policy' does not exist in acl_users portal.acl_users.manage_delObjects(ids=['password_policy', ]) self.assertFalse('password_policy' in portal.acl_users.objectIds()) # find the relevant upgrade step and execute it from Products.GenericSetup.upgrade import listUpgradeSteps relevantStep = [step for step in listUpgradeSteps( portal.portal_setup, 'Products.CMFPlone:plone', '4307')[0] if step['title'] == u'Add default Plone password policy'][0] # execute the step relevantStep['step'].handler(portal) # now it has been added... self.assertTrue('password_policy' in portal.acl_users.objectIds())
def test_profileVersioning(self): site = self._makeSite() site.setup_tool = self._makeOne('setup_tool') tool = site.setup_tool profile_id = 'dummy_profile' product_name = 'GenericSetup' directory = os.path.split(__file__)[0] path = os.path.join(directory, 'versioned_profile') # register profile orig_profile_reg = (profile_registry._profile_info.copy(), profile_registry._profile_ids[:]) profile_registry.registerProfile(profile_id, 'Dummy Profile', 'This is a dummy profile', path, product=product_name) # register upgrade step from Products.GenericSetup.upgrade import _upgrade_registry orig_upgrade_registry = copy.copy(_upgrade_registry._registry) step = UpgradeStep("Upgrade", "GenericSetup:dummy_profile", '*', '1.1', '', dummy_upgrade_handler, None, "1") _registerUpgradeStep(step) # test initial states profile_id = ':'.join((product_name, profile_id)) self.assertEqual(tool.getVersionForProfile(profile_id), '1.1') self.assertEqual(tool.getLastVersionForProfile(profile_id), 'unknown') # run upgrade steps request = site.REQUEST request.form['profile_id'] = profile_id steps = listUpgradeSteps(tool, profile_id, '1.0') step_id = steps[0]['id'] request.form['upgrades'] = [step_id] tool.manage_doUpgrades() self.assertEqual(tool.getLastVersionForProfile(profile_id), ('1', '1')) # reset ugprade registry _upgrade_registry._registry = orig_upgrade_registry # reset profile registry (profile_registry._profile_info, profile_registry._profile_ids) = orig_profile_reg
def testAddDefaultPlonePasswordPolicy(self): # this add the 'Default Plone Password Policy' to Plone's acl_users portal = self.portal # make sure the 'Default Plone Password Policy' does not exist in # acl_users portal.acl_users.manage_delObjects(ids=['password_policy', ]) self.assertFalse('password_policy' in portal.acl_users.objectIds()) # find the relevant upgrade step and execute it from Products.GenericSetup.upgrade import listUpgradeSteps relevantStep = [step for step in listUpgradeSteps( portal.portal_setup, 'Products.CMFPlone:plone', '4307')[0] if step['title'] == u'Add default Plone password policy'][0] # execute the step relevantStep['step'].handler(portal) # now it has been added... self.assertTrue('password_policy' in portal.acl_users.objectIds())
def execute_upgrade(self, source, destination): # Setamos o profile para versao source self.st.setLastVersionForProfile(self.profile, source) # Pegamos os upgrade steps upgradeSteps = listUpgradeSteps(self.st, self.profile, source) if source == '0': source = (source, '0') else: source = (source, ) steps = [step for step in upgradeSteps if (step[0]['dest'] == (destination,)) and (step[0]['source'] == source)][0] # Os executamos for step in steps: step['step'].doStep(self.st)
def run_upgrades_for_profile(profile_id, context, logger=None): """ Run all upgrade steps for given profile_id """ site = context.getSite() setup_tool = getToolByName(site, "portal_setup") version = setup_tool.getLastVersionForProfile(profile_id) upgradeSteps = listUpgradeSteps(setup_tool, profile_id, version) sorted(upgradeSteps, key=lambda step: step["sortkey"]) for step in upgradeSteps: oStep = step.get("step") if oStep is not None: oStep.doStep(setup_tool) setup_tool.setLastVersionForProfile(profile_id, oStep.dest) if logger: msg = "Ran upgrade step %s for profile %s" % (oStep.title, profile_id) logger.info(msg)
def listUpgrades(self, profile_id, show_old=False): """Get the list of available upgrades. """ if show_old: source = None else: source = self.getLastVersionForProfile(profile_id) upgrades = listUpgradeSteps(self, profile_id, source) res = [] for info in upgrades: if type(info) == list: subset = [] for subinfo in info: subset.append(self._massageUpgradeInfo(subinfo)) res.append(subset) else: res.append(self._massageUpgradeInfo(info)) return res
def doUpgrades(context): """ If exists, run migrations """ if context.readDataFile("sc.s17.client.txt") is None: return logger = logging.getLogger(_PROJECT) site = context.getSite() setup_tool = getToolByName(site, "portal_setup") version = setup_tool.getLastVersionForProfile(_PROFILE_ID) upgradeSteps = listUpgradeSteps(setup_tool, _PROFILE_ID, version) sorted(upgradeSteps, key=lambda step: step["sortkey"]) for step in upgradeSteps: oStep = step.get("step") if oStep is not None: oStep.doStep(setup_tool) msg = "Ran upgrade step %s for profile %s" % (oStep.title, _PROFILE_ID) setup_tool.setLastVersionForProfile(_PROFILE_ID, oStep.dest) logger.info(msg)
def test_handler_step_provides_interfaces_implemented_by_upgrade_step_class( self): code = '\n'.join(( 'from ftw.upgrade import UpgradeStep', 'from ftw.upgrade.tests.test_directory_meta_directive import IFoo', 'from zope.interface import implementer', '', '@implementer(IFoo)', 'class Foo(UpgradeStep):', ' pass')) self.profile.with_upgrade( Builder('ftw upgrade step').to(datetime(2011, 1, 1, 1)).with_code(code)) with self.package_created(): portal_setup = getToolByName(self.portal, 'portal_setup') steps = listUpgradeSteps(portal_setup, 'the.package:default', '10000000000000') self.assertEquals(1, len(steps)) self.assertItemsEqual((IRecordableHandler, IUpgradeStep, IFoo), tuple(providedBy(steps[0]['step'].handler))) self.assertTrue(steps[0]['step'].handler.handler)
def run_upgrades(context): """ Run Upgrade steps """ if context.readDataFile('plonesymposium.southamerica-default.txt') is None: return logger = logging.getLogger(_PROJECT) site = context.getSite() setup_tool = getToolByName(site, 'portal_setup') version = setup_tool.getLastVersionForProfile(_PROFILE_ID) upgradeSteps = listUpgradeSteps(setup_tool, _PROFILE_ID, version) sorted(upgradeSteps, key=lambda step: step['sortkey']) for step in upgradeSteps: oStep = step.get('step') if oStep is not None: oStep.doStep(setup_tool) msg = "Ran upgrade step %s for profile %s" % (oStep.title, _PROFILE_ID) setup_tool.setLastVersionForProfile(_PROFILE_ID, oStep.dest) logger.info(msg)
def doUpgrades(context): ''' If exists, run migrations ''' if context.readDataFile('sc.contentrules.groupbydate.txt') is None: return logger = logging.getLogger(_PROJECT) site = context.getSite() setup_tool = getToolByName(site,'portal_setup') version = setup_tool.getLastVersionForProfile(_PROFILE_ID) upgradeSteps = listUpgradeSteps(setup_tool,_PROFILE_ID, version) sorted(upgradeSteps,key=lambda step:step['sortkey']) for step in upgradeSteps: oStep = step.get('step') if oStep is not None: oStep.doStep(setup_tool) msg = "Ran upgrade step %s for profile %s" % (oStep.title, _PROFILE_ID) setup_tool.setLastVersionForProfile(_PROFILE_ID, oStep.dest) logger.info(msg)
def run_upgrades(context): ''' Run Upgrade steps ''' if context.readDataFile('trt13.embed-default.txt') is None: return logger = logging.getLogger(_PROJECT) site = context.getSite() setup_tool = getToolByName(site, 'portal_setup') version = setup_tool.getLastVersionForProfile(_PROFILE_ID) upgradeSteps = listUpgradeSteps(setup_tool, _PROFILE_ID, version) sorted(upgradeSteps, key=lambda step: step['sortkey']) for step in upgradeSteps: oStep = step.get('step') if oStep is not None: oStep.doStep(setup_tool) msg = "Ran upgrade step %s for profile %s" % (oStep.title, _PROFILE_ID) setup_tool.setLastVersionForProfile(_PROFILE_ID, oStep.dest) logger.info(msg)
def test_upgrade_step_variavel_hidden_profiles_deps_brasil_gov_portal(self): # NOQA """ Testa se todos os upgradeSteps de brasil.gov.portal estão nas variáveis HIDDEN_PROFILES e DEPS. Outros pacotes podem ser adicionados em outros testes. """ upgradeSteps = listUpgradeSteps(self.st, self.profile, '') upgrades = [upgrade[0]['dest'][0] for upgrade in upgradeSteps] upgrades_hidden_profiles = [] upgrades_deps = [] prefix = 'brasil.gov.portal.upgrades.v%s' profile = self.profile.split(':')[-1] for upgrade in upgrades: upgrades_deps.append(prefix % upgrade) upgrades_hidden_profiles.append(prefix % upgrade + ':' + profile) self.assertTrue(all(upgrade in HIDDEN_PROFILES for upgrade in upgrades_hidden_profiles)) self.assertTrue(all(upgrade in DEPS for upgrade in upgrades_deps))
def test_5000_corrige_pastas(self): # Ajustamos as pastas para nao estarem ordenadas pastas = ['assuntos', 'imagens', 'sobre'] for pasta_id in pastas: pasta_id = self.portal.invokeFactory('Folder', pasta_id) pasta = self.portal[pasta_id] pasta.setOrdering('unordered') # Setamos o profile para versao 4000 self.st.setLastVersionForProfile(self.profile, u'4000') # Pegamos os upgrade steps upgradeSteps = listUpgradeSteps(self.st, self.profile, '4000') steps = [step for step in upgradeSteps if (step[0]['dest'] == ('5000',)) and (step[0]['source'] == ('4000',))][0] # Os executamos for step in steps: step['step'].doStep(self.st) for pasta_id in pastas: pasta = self.portal[pasta_id] ordering = pasta.getOrdering() self.assertTrue(hasattr(ordering, 'ORDER_KEY'))
def test_handler_step_provides_interfaces_implemented_by_upgrade_step_class(self): code = '\n'.join(( 'from ftw.upgrade import UpgradeStep', 'from ftw.upgrade.tests.test_directory_meta_directive import IFoo', 'from zope.interface import implementer', '', '@implementer(IFoo)', 'class Foo(UpgradeStep):', ' pass')) self.profile.with_upgrade(Builder('ftw upgrade step') .to(datetime(2011, 1, 1, 1)) .with_code(code)) with self.package_created(): portal_setup = getToolByName(self.portal, 'portal_setup') steps = listUpgradeSteps(portal_setup, 'the.package:default', '10000000000000') self.assertEquals(1, len(steps)) self.assertItemsEqual( (IRecordableHandler, IUpgradeStep, IFoo), tuple(providedBy(steps[0]['step'].handler))) self.assertTrue(steps[0]['step'].handler.handler)
def test_to1010_available(self): steps = listUpgradeSteps(self.setup, self.profile, '1000') steps = [s for s in steps if self._match(s[0], '1000', '1010')] self.assertEqual(len(steps), 1)
def get_upgrade_steps(self, source, dest): upgradeSteps = listUpgradeSteps(self.setup, self.profile, source) steps = [s for s in upgradeSteps if (s[0]['dest'] == (dest,)) and (s[0]['source'] == (source,))] return steps