SQL filename misinterpreted as Python function path
What action do you want to perform
I am trying to create a fixture DB with a particular schema, specified in a file (e.g. setup_db.sql).
Sample code:
SCHEMA_PATH = "setup_db.sql"
new_postgresql = factories.postgresql_proc()
database = factories.postgresql("new_postgresql", dbname="test_db", load=[SCHEMA_PATH])
What are the results
I get an error which I think means that the janitor is trying to load the SQL file as Python code:
../[snip]/lib/python3.8/site-packages/pytest_postgresql/factories/client.py:83:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <pytest_postgresql.janitor.DatabaseJanitor object at 0x7ff9770080a0>, load = 'setup_db.sql'
def load(self, load: Union[Callable, str]) -> None:
"""
Loads data into a database.
Either runs a passed loader if it's callback,
or runs predefined loader if it's sql file.
"""
if isinstance(load, str):
if "/" in load:
_loader: Callable = partial(loader, load)
else:
loader_parts = re.split("[.:]", load, 2)
import_path = ".".join(loader_parts[:-1])
loader_name = loader_parts[-1]
> _temp_import = __import__(import_path, globals(), locals(), fromlist=[loader_name])
E ModuleNotFoundError: No module named 'setup_db'
../[snip]/lib/python3.8/site-packages/pytest_postgresql/janitor.py:120: ModuleNotFoundError
============================================================================= short test summary info =============================================================================
ERROR test_weather_migration.py::test_write_data - ModuleNotFoundError: No module named 'setup_db'
What are the expected results
I would expect the database to be created using the specified schema, like in the examples in the README:
postgresql_my_with_schema = factories.postgresql(
'postgresql_my_proc',
load=["schemafile.sql", "otherschema.sql", "import.path.to.function", "import.path.to:otherfunction", load_this]
)
After experimenting, I found that the loading works if I pass the full path instead of just the filename, i.e.:
SCHEMA_PATH = os.path.join(os.path.dirname(__file__), "setup_db.sql")
From what I can see, the Janitor distinguishes between SQL files and Python functions by the existence or not of / in the string. If it's intentional that you need to pass the full path to SQL files, then I think the docs should be updated - unless I'm misunderstanding something!
Or would it make sense to suggest that users give paths to SQL files as pathlib.Path objects instead of filenames, to avoid the confusion with import paths? (otherwise, an argument load=["myfile.sql"] could mean two things: load the schema from myfile.sql, or use the function sql from myfile.py)
EDIT: I tried this with
pytest==7.1.2
pytest-postgresql==4.1.1
although it also happens with earlier versions (at least 3.1.3).
That would be a mistake on my part, when moving from SQL file paths to both SQL file path and func-based :/