Kozea / Kozea/CairoSVG

Error converting local file on Windows

Open
#194 5 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
Python
Stars
951
Forks
166
PR merge metrics
No merged PRs in 30d

Description

Environment:
* *OS: Windows*
* *Python: 3.4*

It appears that since version 2.0, I'm unable to convert local files using `cairosvg` CLI command *on Windows*:
```
$ cairosvg -o test.png input.svg

Traceback (most recent call last):
File "c:\users\rasse\anaconda3\envs\gelutils-py34\lib\urllib\request.py", line 1345, in open_local_file
stats = os.stat(localfile)
FileNotFoundError: [WinError 3] The system cannot find the path specified: ''

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "c:\users\rasse\anaconda3\envs\gelutils-py34\lib\runpy.py", line 170, in _run_module_as_main
"__main__", mod_spec)
File "c:\users\rasse\anaconda3\envs\gelutils-py34\lib\runpy.py", line 85, in _run_code
exec(code, run_globals)
File "C:\Users\rasse\Anaconda3\envs\gelutils-py34\Scripts\cairosvg.exe\__main__.py", line 9, in
File "c:\users\rasse\anaconda3\envs\gelutils-py34\lib\site-packages\cairosvg\__init__.py", line 96, in main
SURFACES[output_format.upper()].convert(**kwargs)
File "c:\users\rasse\anaconda3\envs\gelutils-py34\lib\site-packages\cairosvg\surface.py", line 135, in convert
tree = Tree(**kwargs)
File "c:\users\rasse\anaconda3\envs\gelutils-py34\lib\site-packages\cairosvg\parser.py", line 382, in __init__
parse_url(self.url), 'image/svg+xml')
File "c:\users\rasse\anaconda3\envs\gelutils-py34\lib\site-packages\cairosvg\parser.py", line 258, in fetch_url
return read_url(url, self.url_fetcher, resource_type)
File "c:\users\rasse\anaconda3\envs\gelutils-py34\lib\site-packages\cairosvg\url.py", line 96, in read_url
return url_fetcher(url, resource_type)
File "c:\users\rasse\anaconda3\envs\gelutils-py34\lib\site-packages\cairosvg\url.py", line 42, in fetch
return urlopen(Request(url, headers=HTTP_HEADERS)).read()
File "c:\users\rasse\anaconda3\envs\gelutils-py34\lib\urllib\request.py", line 161, in urlopen
return opener.open(url, data, timeout)
File "c:\users\rasse\anaconda3\envs\gelutils-py34\lib\urllib\request.py", line 466, in open
response = self._open(req, data)
File "c:\users\rasse\anaconda3\envs\gelutils-py34\lib\urllib\request.py", line 484, in _open
'_open', req)
File "c:\users\rasse\anaconda3\envs\gelutils-py34\lib\urllib\request.py", line 443, in _call_chain
result = func(*args)
File "c:\users\rasse\anaconda3\envs\gelutils-py34\lib\urllib\request.py", line 1319, in file_open
return self.open_local_file(req)
File "c:\users\rasse\anaconda3\envs\gelutils-py34\lib\urllib\request.py", line 1363, in open_local_file
raise URLError(exp)
urllib.error.URLError:
```

The error happens with CairoSVG 2.0.0 and 2.1.3 (and, I assume, versions in between).

It did not happen with CairoSVG 1.0.22.

Adding `file:///` in front of the filename *does* work:

```
cairosvg -o test.png file:///D:/temp/input.svg
cairosvg -o test.png file:///D:\temp\input.svg
# This does not work:
cairosvg -o test.png "file://D:\temp\input.svg"

```

Notice the *three* slashes after `file:`.

The reason this works is because urllib interprets the string between `file://` (the scheme) and the third slash as the request host.

On Windows, this means that when `cairosvg.url.read_url()/fetch()` passes the url argument to `urllib.request.Request` *the filename is interpreted as the host*, leaving the `selector` part of the request empty.

When the file is opened by `urllib.request.FileHandler.open_local_file()` it uses the empty `req.selector` as the local filename. When it then tries to `os.stat(localfile)` with an empty filename, it raises an exception.

On Mac/Linux, absolute filepaths starts with `/`, which effectively adds the third slash in `file:///`. So this, I expect, is only an issue on Windows, where absolute filepaths starts with the drive letter (and we also use backslash as path separator). Relative paths are converted to absolute paths in `cairosvg.url.read_url()`.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start in cairosvg.url.read_url() and fetch(), then reproduce the reported cairosvg CLI command with a Windows absolute path. Ensure local Windows filenames are passed in a form urllib can open without requiring a file:/// prefix; done means the documented commands convert successfully, including paths with backslashes.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
cli, operating-systems
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
50/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.