Repository: timvink/mkdocs-table-reader-plugin

Issue:
Whitespace in csv path breaks mkDocs build process 
Given an abspath, it wmf if there is no whitespace in the path. With whitespace fails in MkDocs /serve build process.

Path is:  '/Users/username/Documents/1. Test
```
    'page_markdown', page.markdown, page=page, config=config, files=files
  File "/usr/local/lib/python3.7/site-packages/mkdocs/plugins.py", line 94, in run_event
    result = method(item, **kwargs)
  File "/Users/username/Library/Python/3.7/lib/python/site-packages/mkdocs_table_reader_plugin/plugin.py", line 94, in on_page_markdown
    pd_args, pd_kwargs = parse_argkwarg(result)
  File "/Users/username/Library/Python/3.7/lib/python/site-packages/mkdocs_table_reader_plugin/safe_eval.py", line 86, in parse_argkwarg
    args.append(literal_eval(i))
  File "/usr/local/Cellar/python/3.7.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py", line 46, in literal_eval
    node_or_string = parse(node_or_string, mode='eval')
  File "/usr/local/Cellar/python/3.7.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py", line 35, in parse
    return compile(source, filename, mode, PyCF_ONLY_AST)
  File "<unknown>", line 1
    '/Users/username/Documents/1.
```

Discussion:

Patch:
diff --git a/README.md b/README.md
index 6c9e52c..6a42448 100644
--- a/README.md
+++ b/README.md
@@ -71,9 +71,9 @@ plugins:
 
 ### `data_path`
 
-Default is `.`, which means you can specify the path to your table files relative to the location of your project's `mkdocs.yml` file. If you use a folder for all your table files you can shorten the path specification by setting `data_path`.
+Default is `.`, which means the path to look for the table files is relative to the location of your project's `mkdocs.yml` file. If you specify the location of your table folder you shorten the path.
 
-For example, if you set `data_path` to `docs/` in the project below, you will be able to use `{{ read_csv("basic_table.csv") }}` instead of `{{ read_csv("docs/basic_table.csv") }}` inside `index.md`.
+If you set `data_path` to `docs/` in the project below, you will be able to use `{{ read_csv("basic_table.csv") }}` instead of `{{ read_csv("docs/basic_table.csv") }}` inside `index.md`.
 
 ```nohighlight
 .
diff --git a/mkdocs_table_reader_plugin/safe_eval.py b/mkdocs_table_reader_plugin/safe_eval.py
index 092ee37..71f8959 100644
--- a/mkdocs_table_reader_plugin/safe_eval.py
+++ b/mkdocs_table_reader_plugin/safe_eval.py
@@ -57,7 +57,7 @@ def safe_eval(string):
 
 def parse_argkwarg(string: str):
     """
-    Parses a string to detech both args and kwargs.
+    Parses a string to detect both args and kwargs.
     
     Adapted code from 
     https://stackoverflow.com/questions/9305387/string-of-kwargs-to-kwargs
@@ -69,12 +69,13 @@ def parse_argkwarg(string: str):
         args[List], kwargs[Dict]
     """
 
-    argkwargs = re.split(r"(?<!\=)(?:,? )(?!\=)", string)
+    argkwargs = re.split(r"(?<!\=)(?:,{1} )(?!\=)", string)
 
     args = []
     kwargs = []
 
     for i in argkwargs:
+        i = i.strip()
         if "=" in i:
             kwargs.append(i)
         else:
diff --git a/setup.py b/setup.py
index 3e63940..da81650 100644
--- a/setup.py
+++ b/setup.py
@@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
 
 setup(
     name="mkdocs-table-reader-plugin",
-    version="0.4.0",
+    version="0.4.1",
     description="MkDocs plugin to directly insert tables from files into markdown.",
     long_description=long_description,
     long_description_content_type="text/markdown",


Test patch:
diff --git a/tests/fixtures/data_path_with_space/docs/folder with spaces/basic_table.csv b/tests/fixtures/data_path_with_space/docs/folder with spaces/basic_table.csv
new file mode 100644
index 0000000..6743b2e
--- /dev/null
+++ b/tests/fixtures/data_path_with_space/docs/folder with spaces/basic_table.csv
@@ -0,0 +1,5 @@
+"a","b"
+40,73
+50,52
+531456,80
+"name","table1"
\ No newline at end of file
diff --git a/tests/fixtures/data_path_with_space/docs/index.md b/tests/fixtures/data_path_with_space/docs/index.md
new file mode 100644
index 0000000..8f4f35c
--- /dev/null
+++ b/tests/fixtures/data_path_with_space/docs/index.md
@@ -0,0 +1,7 @@
+# Test page
+
+This is a table that we load from the docs folder, because we set `data_path` to `docs`:
+
+## inserted with positional argument
+
+{{ read_csv("basic_table.csv") }}
diff --git a/tests/fixtures/data_path_with_space/mkdocs.yml b/tests/fixtures/data_path_with_space/mkdocs.yml
new file mode 100644
index 0000000..cd69053
--- /dev/null
+++ b/tests/fixtures/data_path_with_space/mkdocs.yml
@@ -0,0 +1,7 @@
+site_name: test git_table_reader site
+use_directory_urls: true
+
+plugins:
+    - search
+    - table-reader:
+        data_path: "docs/folder with spaces"
diff --git a/tests/fixtures/table_path_with_space/docs/index.md b/tests/fixtures/table_path_with_space/docs/index.md
new file mode 100644
index 0000000..6edd75d
--- /dev/null
+++ b/tests/fixtures/table_path_with_space/docs/index.md
@@ -0,0 +1,7 @@
+# Test page
+
+This is a table that we load from the docs folder, because we set `data_path` to `docs`:
+
+## inserted with positional argument
+
+{{ read_csv("docs/table name with spaces.csv") }}
diff --git a/tests/fixtures/table_path_with_space/docs/table name with spaces.csv b/tests/fixtures/table_path_with_space/docs/table name with spaces.csv
new file mode 100644
index 0000000..6743b2e
--- /dev/null
+++ b/tests/fixtures/table_path_with_space/docs/table name with spaces.csv
@@ -0,0 +1,5 @@
+"a","b"
+40,73
+50,52
+531456,80
+"name","table1"
\ No newline at end of file
diff --git a/tests/fixtures/table_path_with_space/mkdocs.yml b/tests/fixtures/table_path_with_space/mkdocs.yml
new file mode 100644
index 0000000..1e47be9
--- /dev/null
+++ b/tests/fixtures/table_path_with_space/mkdocs.yml
@@ -0,0 +1,6 @@
+site_name: test git_table_reader site
+use_directory_urls: true
+
+plugins:
+    - search
+    - table-reader
diff --git a/tests/test_build.py b/tests/test_build.py
index 9ea90a9..6da893d 100644
--- a/tests/test_build.py
+++ b/tests/test_build.py
@@ -189,6 +189,36 @@ def test_datapath_trailing(tmp_path):
     assert re.search(r"539956", contents)
 
 
+def test_datapath_with_spaces(tmp_path):
+
+    tmp_proj = setup_clean_mkdocs_folder(
+        "tests/fixtures/data_path_with_space/mkdocs.yml", tmp_path
+    )
+
+    result = build_docs_setup(tmp_proj)
+    assert result.exit_code == 0, "'mkdocs build' command failed"
+
+    # Make sure the basic_table.csv is inserted
+    page_with_tag = tmp_proj / "site/index.html"
+    contents = page_with_tag.read_text()
+    assert re.search(r"531456", contents)
+
+
+def test_tablepath_with_spaces(tmp_path):
+
+    tmp_proj = setup_clean_mkdocs_folder(
+        "tests/fixtures/table_path_with_space/mkdocs.yml", tmp_path
+    )
+
+    result = build_docs_setup(tmp_proj)
+    assert result.exit_code == 0, "'mkdocs build' command failed"
+
+    # Make sure the basic_table.csv is inserted
+    page_with_tag = tmp_proj / "site/index.html"
+    contents = page_with_tag.read_text()
+    assert re.search(r"531456", contents)
+
+
 def test_wrong_path(tmp_path):
 
     tmp_proj = setup_clean_mkdocs_folder(
diff --git a/tests/test_safe_eval.py b/tests/test_safe_eval.py
index 172f4c2..15bcb09 100644
--- a/tests/test_safe_eval.py
+++ b/tests/test_safe_eval.py
@@ -33,7 +33,7 @@ def test_safe_eval5():
 
 
 def test_parseargkwarg_1():
-    s = "title='bah', name='john' purple='haze' none=None i=1"
+    s = "title='bah', name='john', purple='haze', none=None, i=1"
     args, kwargs = parse_argkwarg(s)
     assert args == []
     assert kwargs == {
@@ -73,6 +73,20 @@ def test_parseargkwarg_5():
     assert kwargs == {"sep": "\r\t"}
 
 
+def test_parseargkwarg_6():
+    s = "'assets/tables/table.csv' ,  sep = '\r\t'"
+    args, kwargs = parse_argkwarg(s)
+    assert args == ["assets/tables/table.csv"]
+    assert kwargs == {"sep": "\r\t"}
+
+
+def test_parseargkwarg_7():
+    s = "'table with space.csv', sep = '\r\t'"
+    args, kwargs = parse_argkwarg(s)
+    assert args == ["table with space.csv"]
+    assert kwargs == {"sep": "\r\t"}
+
+
 def test_parseargkwarg_error():
 
     with pytest.raises(AssertionError):