def test_parser(): from pgtoolkit.conf import parse lines = dedent("""\ # - Connection Settings - listen_addresses = '*' # comma-separated list of addresses; # defaults to 'localhost'; use '*' for all # (change requires restart) port = 5432 bonjour 'without equals' shared.buffers = 248MB """).splitlines(True) # noqa conf = parse(lines) assert '*' == conf.listen_addresses assert 5432 == conf.port assert 'without equals' == conf.bonjour assert 248 * 1024 * 1024 == conf['shared.buffers'] dict_ = conf.as_dict() assert '*' == dict_['listen_addresses'] with pytest.raises(AttributeError): conf.inexistant with pytest.raises(KeyError): conf['inexistant'] with pytest.raises(ValueError): parse(['bad_line'])
def test_parser_includes_loop(tmp_path): from pgtoolkit.conf import parse pgconf = tmp_path / "postgres.conf" with pgconf.open("w") as f: f.write(f"include = '{pgconf.absolute()}'\n") with pytest.raises(RuntimeError, match="loop detected"): parse(str(pgconf))
def test_save(): from pgtoolkit.conf import parse conf = parse(['listen_addresses = *']) fo = StringIO() conf.save(fo) out = fo.getvalue() assert 'listen_addresses = *' in out
def test_parser_includes_notfound(tmp_path): from pgtoolkit.conf import parse pgconf = tmp_path / "postgres.conf" with pgconf.open("w") as f: f.write("include = 'missing.conf'\n") missing_conf = tmp_path / "missing.conf" msg = f"file '{missing_conf}', included from '{pgconf}', not found" with pytest.raises(FileNotFoundError, match=msg): parse(str(pgconf)) pgconf = tmp_path / "postgres.conf" with pgconf.open("w") as f: f.write("include_dir = 'conf.d'\n") missing_conf = tmp_path / "conf.d" msg = f"directory '{missing_conf}', included from '{pgconf}', not found" with pytest.raises(FileNotFoundError, match=msg): parse(str(pgconf))
def test_save(): from pgtoolkit.conf import parse conf = parse(["listen_addresses = *"]) conf["primary_conninfo"] = "user=repli password=pa'sw0'd" fo = StringIO() conf.save(fo) out = fo.getvalue() assert "listen_addresses = *" in out assert "primary_conninfo = 'user=repli password=pa''sw0''d'" in out
def test_parser_includes(): from pgtoolkit.conf import parse fpath = pathlib.Path(__file__).parent / "data" / "postgres.conf" conf = parse(str(fpath)) assert conf.as_dict() == { "authentication_timeout": timedelta(seconds=120), "autovacuum_work_mem": -1, "bonjour": False, "bonsoir": True, "checkpoint_completion_target": 0.9, "cluster_name": "pgtoolkit", "listen_addresses": "*", "log_line_prefix": "%m %q@%d", "log_rotation_age": timedelta(days=1), "max_connections": 100, "my": True, "mymy": False, "mymymy": True, "pg_stat_statements.max": 10000, "pg_stat_statements.track": "all", "port": 5432, "shared_buffers": "248MB", "shared_preload_libraries": "pg_stat_statements", "ssl": True, "unix_socket_permissions": 511, "wal_level": "hot_standby", } assert "include" not in conf assert "include_if_exists" not in conf assert "include_dir" not in conf # Make sure original file is preserved on save (i.e. includes do not # interfere). fo = StringIO() conf.save(fo) lines = fo.getvalue().strip().splitlines() assert lines[:8] == [ "include_dir = 'conf.d'", "#include_dir = 'conf.11.d'", "include = 'postgres-my.conf'", "#------------------------------------------------------------------------------", "# CONNECTIONS AND AUTHENTICATION", "#------------------------------------------------------------------------------", "# - Connection Settings -", "listen_addresses = '*' # comma-separated list of addresses;", ] assert lines[-3:] == [ "# Add settings for extensions here", "pg_stat_statements.max = 10000", "pg_stat_statements.track = all", ]
def test_parser(): from pgtoolkit.conf import parse lines = dedent( """\ # - Connection Settings - listen_addresses = '*' # comma-separated list of addresses; # defaults to 'localhost'; use '*' for all # (change requires restart) primary_conninfo = 'host=''example.com'' port=5432 dbname=mydb connect_timeout=10' port = 5432 bonjour 'without equals' # bonjour_name = '' # defaults to the computer name shared.buffers = 248MB #authentication_timeout = 2min # will be overwritten by the one below #authentication_timeout = 1min # 1s-600s # port = 5454 # commented value does not override previous (uncommented) one """ ).splitlines( True ) # noqa conf = parse(lines) assert "*" == conf.listen_addresses assert ( str(conf.entries["listen_addresses"]) == "listen_addresses = '*' # comma-separated list of addresses;" ) assert 5432 == conf.port assert ( conf.primary_conninfo == "host='example.com' port=5432 dbname=mydb connect_timeout=10" ) assert "without equals" == conf.bonjour assert "248MB" == conf["shared.buffers"] assert conf.entries["bonjour_name"].commented assert ( str(conf.entries["bonjour_name"]) == "#bonjour_name = '' # defaults to the computer name" ) assert conf.entries["authentication_timeout"].commented assert conf.entries["authentication_timeout"].value == timedelta(minutes=1) assert ( str(conf.entries["authentication_timeout"]) == "#authentication_timeout = '1 min' # 1s-600s" ) dict_ = conf.as_dict() assert "*" == dict_["listen_addresses"] with pytest.raises(AttributeError): conf.inexistant with pytest.raises(KeyError): conf["inexistant"] with pytest.raises(ValueError): parse(["bad_line"])
def test_parser_includes_require_a_file_path(): from pgtoolkit.conf import parse lines = ["include = 'foo.conf'\n"] with pytest.raises(ValueError, match="try passing a file path"): parse(lines)