def test_init_file_doesnt_exist(self): def access_(path, mode): if "generic" in path: return True else: return False template_dir = self.cfg.get_template_directory() with mock.patch( "alembic.command.os.access", side_effect=access_ ) as access, mock.patch( "alembic.command.os.makedirs" ) as makedirs, mock.patch( "alembic.command.ScriptDirectory" ): command.init(self.cfg, directory="foobar") eq_( access.mock_calls, [ mock.call("foobar", os.F_OK), mock.call(os.path.join(template_dir, "generic"), os.F_OK), mock.call("foobar", os.F_OK), mock.call( os.path.abspath("./scratch/test_alembic.ini"), os.F_OK ), ], ) eq_( makedirs.mock_calls, [mock.call("foobar"), mock.call("foobar/versions")], )
def test_init_file_exists_and_is_empty(self): def access_(path, mode): if "generic" in path or path == "foobar": return True else: return False def listdir_(path): if path == "foobar": return [] else: return ["file1", "file2", "alembic.ini.mako"] with mock.patch( "alembic.command.os.access", side_effect=access_ ), mock.patch("alembic.command.os.makedirs") as makedirs, mock.patch( "alembic.command.os.listdir", side_effect=listdir_ ), mock.patch( "alembic.command.ScriptDirectory" ): command.init(self.cfg, directory="foobar") eq_( makedirs.mock_calls, [mock.call(os.path.normpath("foobar/versions"))], )
def _run_black_with_config(self, input_config, expected_additional_arguments_fn, cwd=None): self.cfg = _no_sql_testing_config(directives=input_config) class MocksCantName: name = "black" attr = "bar" module = "black_module.foo" importlib_metadata_get = mock.Mock(return_value=iter([MocksCantName])) with mock.patch( "alembic.util.compat.importlib_metadata_get", importlib_metadata_get, ), mock.patch( "alembic.script.write_hooks.subprocess") as mock_subprocess: rev = command.revision(self.cfg, message="x") eq_(importlib_metadata_get.mock_calls, [mock.call("console_scripts")]) eq_( mock_subprocess.mock_calls, [ mock.call.run( [ sys.executable, "-c", "import black_module.foo; black_module.foo.bar()", ] + expected_additional_arguments_fn(rev.path), cwd=cwd, ) ], )
def test_console_scripts(self): self.cfg = _no_sql_testing_config( directives=("\n[post_write_hooks]\n" "hooks=black\n" "black.type=console_scripts\n" "black.entrypoint=black\n" "black.options=-l 79\n")) impl = mock.Mock(attrs=("foo", "bar"), module_name="black_module") entrypoints = mock.Mock(return_value=iter([impl])) with mock.patch("pkg_resources.iter_entry_points", entrypoints), mock.patch( "alembic.script.write_hooks.subprocess" ) as mock_subprocess: rev = command.revision(self.cfg, message="x") eq_(entrypoints.mock_calls, [mock.call("console_scripts", "black")]) eq_( mock_subprocess.mock_calls, [ mock.call.run([ sys.executable, "-c", "import black_module; black_module.foo.bar()", rev.path, "-l", "79", ]) ], )
def _run_black_with_config(self, input_config, expected_additional_arguments_fn, cwd=None): self.cfg = _no_sql_testing_config(directives=input_config) impl = mock.Mock(attrs=("foo", "bar"), module_name="black_module") entrypoints = mock.Mock(return_value=iter([impl])) with mock.patch("pkg_resources.iter_entry_points", entrypoints), mock.patch( "alembic.script.write_hooks.subprocess" ) as mock_subprocess: rev = command.revision(self.cfg, message="x") eq_(entrypoints.mock_calls, [mock.call("console_scripts", "black")]) eq_( mock_subprocess.mock_calls, [ mock.call.run( [ sys.executable, "-c", "import black_module; black_module.foo.bar()", ] + expected_additional_arguments_fn(rev.path), cwd=cwd, ) ], )
def test_init_file_exists_and_is_not_empty(self): with mock.patch( "alembic.command.os.listdir", return_value=["file1", "file2"] ), mock.patch("alembic.command.os.access", return_value=True): directory = "alembic" assert_raises_message( util.CommandError, "Directory %s already exists and is not empty" % directory, command.init, self.cfg, directory=directory, )
def test_cant_change_computed_warning(self, test_case): arg_before, arg_after = testing.resolve_lambda(test_case, **locals()) m1 = MetaData() m2 = MetaData() arg_before = [] if arg_before is None else [arg_before] arg_after = [] if arg_after is None else [arg_after] Table( "user", m1, Column("id", Integer, primary_key=True), Column("bar", Integer), Column("foo", Integer, *arg_before), ) Table( "user", m2, Column("id", Integer, primary_key=True), Column("bar", Integer), Column("foo", Integer, *arg_after), ) with mock.patch("alembic.util.warn") as mock_warn: diffs = self._fixture(m1, m2) eq_( mock_warn.mock_calls, [mock.call("Computed default on user.foo cannot be modified")], ) eq_(list(diffs), [])
def test_add_foreign_key_dialect_kw(self): op_fixture() with mock.patch("sqlalchemy.schema.ForeignKeyConstraint") as fkc: op.create_foreign_key("fk_test", "t1", "t2", ["foo", "bar"], ["bat", "hoho"], foobar_arg="xyz") if config.requirements.foreign_key_match.enabled: eq_( fkc.mock_calls[0], mock.call( ["foo", "bar"], ["t2.bat", "t2.hoho"], onupdate=None, ondelete=None, name="fk_test", foobar_arg="xyz", deferrable=None, initially=None, match=None, ), ) else: eq_( fkc.mock_calls[0], mock.call( ["foo", "bar"], ["t2.bat", "t2.hoho"], onupdate=None, ondelete=None, name="fk_test", foobar_arg="xyz", deferrable=None, initially=None, ), )
def test_script_location_muliple(self): config = _multi_dir_testing_config() script = ScriptDirectory.from_config(config) def normpath(path): return path.replace("/", ":NORM:") normpath = mock.Mock(side_effect=normpath) with mock.patch("os.path.normpath", normpath): eq_( script._version_locations, [ os.path.abspath( os.path.join(_get_staging_directory(), "model1/")).replace("/", ":NORM:"), os.path.abspath( os.path.join(_get_staging_directory(), "model2/")).replace("/", ":NORM:"), os.path.abspath( os.path.join(_get_staging_directory(), "model3/")).replace("/", ":NORM:"), ], )
def test_add_foreign_key_dialect_kw(self): op_fixture() with mock.patch("sqlalchemy.schema.ForeignKeyConstraint") as fkc: op.create_foreign_key('fk_test', 't1', 't2', ['foo', 'bar'], ['bat', 'hoho'], foobar_arg='xyz') if config.requirements.foreign_key_match.enabled: eq_( fkc.mock_calls[0], mock.call(['foo', 'bar'], ['t2.bat', 't2.hoho'], onupdate=None, ondelete=None, name='fk_test', foobar_arg='xyz', deferrable=None, initially=None, match=None)) else: eq_( fkc.mock_calls[0], mock.call(['foo', 'bar'], ['t2.bat', 't2.hoho'], onupdate=None, ondelete=None, name='fk_test', foobar_arg='xyz', deferrable=None, initially=None))
def test_edit_b(self): expected_call_arg = '%s/scripts/versions/%s_revision_b.py' % ( EditTest.cfg.config_args['here'], EditTest.b) with mock.patch('alembic.util.edit') as edit: command.edit(self.cfg, self.b[0:3]) edit.assert_called_with(expected_call_arg)
def test_script_location(self): config = _no_sql_testing_config() script = ScriptDirectory.from_config(config) def normpath(path): return path.replace("/", ":NORM:") normpath = mock.Mock(side_effect=normpath) with mock.patch("os.path.normpath", normpath): eq_( script._version_locations, ( os.path.abspath( os.path.join( _get_staging_directory(), "scripts", "versions" ) ).replace("/", ":NORM:"), ), ) eq_( script.versions, os.path.abspath( os.path.join( _get_staging_directory(), "scripts", "versions" ) ).replace("/", ":NORM:"), )
def test_steps(self): import alembic alembic.mock_event_listener = None self._env_file_fixture() with mock.patch('alembic.mock_event_listener', mock.Mock()) as mymock: super(CallbackEnvironmentTest, self).test_steps() calls = mymock.call_args_list assert calls for call in calls: args, kw = call assert not args assert set(kw.keys()) >= self.exp_kwargs assert kw['run_args'] == {} assert hasattr(kw['ctx'], 'get_current_revision') step = kw['step'] assert isinstance(step.is_upgrade, bool) assert isinstance(step.is_stamp, bool) assert isinstance(step.is_migration, bool) assert isinstance(step.up_revision_id, compat.string_types) assert isinstance(step.up_revision, Script) for revtype in 'up', 'down', 'source', 'destination': revs = getattr(step, '%s_revisions' % revtype) assert isinstance(revs, tuple) for rev in revs: assert isinstance(rev, Script) revids = getattr(step, '%s_revision_ids' % revtype) for revid in revids: assert isinstance(revid, compat.string_types) heads = kw['heads'] assert hasattr(heads, '__iter__') for h in heads: assert h is None or isinstance(h, compat.string_types)
def test_filename_interpolation(self, posix): input_config = """ [post_write_hooks] hooks = black black.type = console_scripts black.entrypoint = black black.options = arg1 REVISION_SCRIPT_FILENAME 'multi-word arg' \ --flag1='REVISION_SCRIPT_FILENAME' """ def expected_additional_arguments_fn(rev_path): if compat.is_posix: return [ "arg1", rev_path, "multi-word arg", "--flag1=" + rev_path, ] else: return [ "arg1", rev_path, "'multi-word arg'", "--flag1='%s'" % rev_path, ] with mock.patch("alembic.util.compat.is_posix", posix): self._run_black_with_config( input_config, expected_additional_arguments_fn )
def test_edit_b(self): expected_call_arg = os.path.normpath( "%s/scripts/versions/%s_revision_b.py" % (EditTest.cfg.config_args["here"], EditTest.b)) with mock.patch("alembic.util.open_in_editor") as edit: command.edit(self.cfg, self.b[0:3]) edit.assert_called_with(expected_call_arg)
def test_init_file_doesnt_exist(self): def access_(path, mode): if "generic" in path: return True else: return False with mock.patch( "alembic.command.os.access", side_effect=access_), mock.patch( "alembic.command.os.makedirs") as makedirs, mock.patch( "alembic.command.ScriptDirectory"): command.init(self.cfg, directory="foobar") eq_( makedirs.mock_calls, [mock.call("foobar"), mock.call("foobar/versions")], )
def test_edit_with_missing_editor(self): with mock.patch('editor.edit') as edit_mock: edit_mock.side_effect = OSError("file not found") assert_raises_message( util.CommandError, 'file not found', util.edit, "/not/a/file.txt")
def test_edit_head(self): expected_call_arg = os.path.normpath( "%s/scripts/versions/%s_revision_c.py" % (EditTest.cfg.config_args["here"], EditTest.c)) with mock.patch("alembic.util.edit") as edit: command.edit(self.cfg, "head") edit.assert_called_with(expected_call_arg)
def _fixture(self): migration_context = mock.Mock(opts={}) op = Operations(migration_context) batch = op.batch_alter_table('tname', recreate='never').__enter__() with mock.patch("alembic.operations.sa_schema") as mock_schema: yield batch batch.impl.flush() self.mock_schema = mock_schema
def test_edit_head(self): expected_call_arg = "%s/scripts/versions/%s_revision_c.py" % ( EditTest.cfg.config_args["here"], EditTest.c, ) with mock.patch("alembic.util.edit") as edit: command.edit(self.cfg, "head") edit.assert_called_with(expected_call_arg)
def test_edit_b(self): expected_call_arg = '%s/scripts/versions/%s_revision_b.py' % ( EditTest.cfg.config_args['here'], EditTest.b ) with mock.patch('alembic.util.edit') as edit: command.edit(self.cfg, self.b[0:3]) edit.assert_called_with(expected_call_arg)
def test_init_file_exists_and_is_empty(self): def access_(path, mode): if "generic" in path or path == "foobar": return True else: return False def listdir_(path): if path == "foobar": return [] else: return ["file1", "file2", "alembic.ini.mako"] template_dir = self.cfg.get_template_directory() with mock.patch( "alembic.command.os.access", side_effect=access_ ) as access, mock.patch( "alembic.command.os.makedirs" ) as makedirs, mock.patch( "alembic.command.os.listdir", side_effect=listdir_ ) as listdir, mock.patch( "alembic.command.ScriptDirectory" ): command.init(self.cfg, directory="foobar") eq_( access.mock_calls, [ mock.call("foobar", os.F_OK), mock.call(os.path.join(template_dir, "generic"), os.F_OK), mock.call("foobar", os.F_OK), mock.call( os.path.abspath("./scratch/test_alembic.ini"), os.F_OK ), ], ) eq_( listdir.mock_calls, [ mock.call("foobar"), mock.call(os.path.join(template_dir, "generic")), ], ) eq_(makedirs.mock_calls, [mock.call("foobar/versions")])
def test_edit_current(self): expected_call_arg = "%s/scripts/versions/%s_revision_b.py" % ( EditTest.cfg.config_args["here"], EditTest.b, ) command.stamp(self.cfg, self.b) with mock.patch("alembic.util.edit") as edit: command.edit(self.cfg, "current") edit.assert_called_with(expected_call_arg)
def _run_black_with_config( self, input_config, expected_additional_arguments_fn, cwd=None ): self.cfg = _no_sql_testing_config(directives=input_config) retVal = [ compat.EntryPoint( name="black", value="black.foo:patched_main", group="console_scripts", ), compat.EntryPoint( name="alembic", value="alembic.config:main", group="console_scripts", ), ] importlib_metadata_get = mock.Mock(return_value=retVal) with mock.patch( "alembic.util.compat.importlib_metadata_get", importlib_metadata_get, ), mock.patch( "alembic.script.write_hooks.subprocess" ) as mock_subprocess: rev = command.revision(self.cfg, message="x") eq_(importlib_metadata_get.mock_calls, [mock.call("console_scripts")]) eq_( mock_subprocess.mock_calls, [ mock.call.run( [ sys.executable, "-c", "import black.foo; black.foo.patched_main()", ] + expected_additional_arguments_fn(rev.path), cwd=cwd, ) ], )
def _fixture(self, schema=None): migration_context = mock.Mock( opts={}, impl=mock.MagicMock(__dialect__='sqlite')) op = Operations(migration_context) batch = op.batch_alter_table( 'tname', recreate='never', schema=schema).__enter__() mock_schema = mock.MagicMock() with mock.patch("alembic.operations.schemaobj.sa_schema", mock_schema): yield batch batch.impl.flush() self.mock_schema = mock_schema
def _fixture(self, schema=None): migration_context = mock.Mock( opts={}, impl=mock.MagicMock(__dialect__='sqlite')) op = Operations(migration_context) batch = op.batch_alter_table('tname', recreate='never', schema=schema).__enter__() mock_schema = mock.MagicMock() with mock.patch("alembic.operations.schemaobj.sa_schema", mock_schema): yield batch batch.impl.flush() self.mock_schema = mock_schema
def test_version_text(self): buf = compat.StringIO() to_mock = "sys.stdout" if util.compat.py3k else "sys.stderr" with mock.patch(to_mock, buf): try: config.CommandLine(prog="test_prog").main(argv=["--version"]) assert False except SystemExit: pass is_true("test_prog" in str(buf.getvalue())) is_true(__version__ in str(buf.getvalue()))
def _env_fixture(self, target_metadata): self.engine = engine = _sqlite_file_db() def run_env(self): from alembic import context with engine.connect() as connection: context.configure(connection=connection, target_metadata=target_metadata) with context.begin_transaction(): context.run_migrations() return mock.patch("alembic.script.base.ScriptDirectory.run_env", run_env)
def _test_tz(self, timezone_arg, given, expected): script = ScriptDirectory(_get_staging_directory(), file_template="%(rev)s_%(slug)s_" "%(year)s_%(month)s_" "%(day)s_%(hour)s_" "%(minute)s_%(second)s", timezone=timezone_arg) with mock.patch( "alembic.script.base.datetime", mock.Mock(datetime=mock.Mock(utcnow=lambda: given, now=lambda: given))): create_date = script._generate_create_date() eq_(create_date, expected)
def _env_fixture(self, target_metadata): self.engine = engine = _sqlite_file_db() def run_env(self): from alembic import context with engine.connect() as connection: context.configure( connection=connection, target_metadata=target_metadata) with context.begin_transaction(): context.run_migrations() return mock.patch( "alembic.script.base.ScriptDirectory.run_env", run_env )
def test_add_foreign_key_dialect_kw(self): op_fixture() with mock.patch( "alembic.operations.sa_schema.ForeignKeyConstraint") as fkc: op.create_foreign_key('fk_test', 't1', 't2', ['foo', 'bar'], ['bat', 'hoho'], foobar_arg='xyz') if config.requirements.foreign_key_match.enabled: eq_(fkc.mock_calls[0], mock.call(['foo', 'bar'], ['t2.bat', 't2.hoho'], onupdate=None, ondelete=None, name='fk_test', foobar_arg='xyz', deferrable=None, initially=None, match=None)) else: eq_(fkc.mock_calls[0], mock.call(['foo', 'bar'], ['t2.bat', 't2.hoho'], onupdate=None, ondelete=None, name='fk_test', foobar_arg='xyz', deferrable=None, initially=None))
def test_init_w_package(self): path = os.path.join(_get_staging_directory(), "foobar") with mock.patch("alembic.command.open") as open_: command.init(self.cfg, directory=path, package=True) eq_( open_.mock_calls, [ mock.call( os.path.abspath(os.path.join(path, "__init__.py")), "w"), mock.call().close(), mock.call( os.path.abspath( os.path.join(path, "versions", "__init__.py")), "w", ), mock.call().close(), ], )
def test_add_foreign_key_dialect_kw(self): op_fixture() with mock.patch("sqlalchemy.schema.ForeignKeyConstraint") as fkc: op.create_foreign_key( "fk_test", "t1", "t2", ["foo", "bar"], ["bat", "hoho"], foobar_arg="xyz", ) if config.requirements.foreign_key_match.enabled: eq_( fkc.mock_calls[0], mock.call( ["foo", "bar"], ["t2.bat", "t2.hoho"], onupdate=None, ondelete=None, name="fk_test", foobar_arg="xyz", deferrable=None, initially=None, match=None, ), ) else: eq_( fkc.mock_calls[0], mock.call( ["foo", "bar"], ["t2.bat", "t2.hoho"], onupdate=None, ondelete=None, name="fk_test", foobar_arg="xyz", deferrable=None, initially=None, ), )
def test_help_text(self): commands = { fn.__name__ for fn in [getattr(command, n) for n in dir(command)] if inspect.isfunction(fn) and fn.__name__[0] != "_" and fn.__module__ == "alembic.command" } # make sure we found them assert commands.intersection( {"upgrade", "downgrade", "merge", "revision"} ) # catch help text coming intersection with mock.patch("alembic.config.ArgumentParser") as argparse: config.CommandLine() for kall in argparse().add_subparsers().mock_calls: for sub_kall in kall.call_list(): if sub_kall[0] == "add_parser": cmdname = sub_kall[1][0] help_text = sub_kall[2]["help"] if help_text: commands.remove(cmdname) # more than two spaces assert not re.search(r" ", help_text) # no markup stuff assert ":" not in help_text # no newlines assert "\n" not in help_text # ends with a period assert help_text.endswith(".") # not too long assert len(help_text) < 80 assert not commands, "Commands without help text: %s" % commands
def _test_tz(self, timezone_arg, given, expected): script = ScriptDirectory( _get_staging_directory(), file_template="%(rev)s_%(slug)s_" "%(year)s_%(month)s_" "%(day)s_%(hour)s_" "%(minute)s_%(second)s", timezone=timezone_arg ) with mock.patch( "alembic.script.base.datetime", mock.Mock( datetime=mock.Mock( utcnow=lambda: given, now=lambda: given ) ) ): create_date = script._generate_create_date() eq_( create_date, expected )
def test_steps(self): import alembic alembic.mock_event_listener = None self._env_file_fixture() with mock.patch("alembic.mock_event_listener", mock.Mock()) as mymock: super(CallbackEnvironmentTest, self).test_steps() calls = mymock.call_args_list assert calls for call in calls: args, kw = call assert not args assert set(kw.keys()) >= self.exp_kwargs assert kw["run_args"] == {} assert hasattr(kw["ctx"], "get_current_revision") step = kw["step"] assert isinstance(step.is_upgrade, bool) assert isinstance(step.is_stamp, bool) assert isinstance(step.is_migration, bool) assert isinstance(step.up_revision_id, compat.string_types) assert isinstance(step.up_revision, Script) for revtype in "up", "down", "source", "destination": revs = getattr(step, "%s_revisions" % revtype) assert isinstance(revs, tuple) for rev in revs: assert isinstance(rev, Script) revids = getattr(step, "%s_revision_ids" % revtype) for revid in revids: assert isinstance(revid, compat.string_types) heads = kw["heads"] assert hasattr(heads, "__iter__") for h in heads: assert h is None or isinstance(h, compat.string_types)