1
0
Fork 0
forked from github/pelican

Fix Windows tests

* Unskip passable tests
* Fix broken tests
This commit is contained in:
Deniz Turgut 2020-04-28 23:29:44 +03:00
commit 2e482b207b
No known key found for this signature in database
GPG key ID: 87B7168D7AB3ED2F
10 changed files with 58 additions and 41 deletions

View file

@ -696,7 +696,7 @@ def path_metadata(full_path, source_path, settings=None):
# Enforce a trailing slash when checking for parent directories.
# This prevents false positives when one file or directory's name
# is a prefix of another's.
dirpath = os.path.join(path, '')
dirpath = posixize_path(os.path.join(path, ''))
if source_path == path or source_path.startswith(dirpath):
metadata.update(meta)

View file

@ -160,6 +160,19 @@ def locale_available(locale_):
return True
def can_symlink():
res = True
try:
with temporary_folder() as f:
os.symlink(
f,
os.path.join(f, 'symlink')
)
except OSError:
res = False
return res
def get_settings(**kwargs):
"""Provide tweaked setting dictionaries for testing

View file

@ -1,5 +1,6 @@
import locale
import os
import sys
from shutil import copy, rmtree
from tempfile import mkdtemp
from unittest.mock import MagicMock
@ -7,7 +8,8 @@ from unittest.mock import MagicMock
from pelican.generators import (ArticlesGenerator, Generator, PagesGenerator,
PelicanTemplateNotFound, StaticGenerator,
TemplatePagesGenerator)
from pelican.tests.support import get_context, get_settings, unittest
from pelican.tests.support import (can_symlink, get_context, get_settings,
unittest)
from pelican.writers import Writer
@ -1081,6 +1083,7 @@ class TestStaticGenerator(unittest.TestCase):
self.generator.generate_output(None)
self.assertTrue(os.path.samefile(self.startfile, self.endfile))
@unittest.skipUnless(can_symlink(), 'No symlink privilege')
def test_can_symlink_when_hardlink_not_possible(self):
self.settings['STATIC_CREATE_LINKS'] = True
with open(self.startfile, "w") as f:
@ -1088,40 +1091,29 @@ class TestStaticGenerator(unittest.TestCase):
os.mkdir(os.path.join(self.temp_output, "static"))
self.generator.fallback_to_symlinks = True
self.generator.generate_context()
try:
self.generator.generate_output(None)
except OSError as e:
# On Windows, possibly others, due to not holding symbolic link
# privilege
self.skipTest(e)
self.generator.generate_output(None)
self.assertTrue(os.path.islink(self.endfile))
@unittest.skipUnless(can_symlink(), 'No symlink privilege')
def test_existing_symlink_is_considered_up_to_date(self):
self.settings['STATIC_CREATE_LINKS'] = True
with open(self.startfile, "w") as f:
f.write("staticcontent")
os.mkdir(os.path.join(self.temp_output, "static"))
try:
os.symlink(self.startfile, self.endfile)
except OSError as e:
# On Windows, possibly others
self.skipTest(e)
os.symlink(self.startfile, self.endfile)
staticfile = MagicMock()
staticfile.source_path = self.startfile
staticfile.save_as = self.endfile
requires_update = self.generator._file_update_required(staticfile)
self.assertFalse(requires_update)
@unittest.skipUnless(can_symlink(), 'No symlink privilege')
def test_invalid_symlink_is_overwritten(self):
self.settings['STATIC_CREATE_LINKS'] = True
with open(self.startfile, "w") as f:
f.write("staticcontent")
os.mkdir(os.path.join(self.temp_output, "static"))
try:
os.symlink("invalid", self.endfile)
except OSError as e:
# On Windows, possibly others
self.skipTest(e)
os.symlink("invalid", self.endfile)
staticfile = MagicMock()
staticfile.source_path = self.startfile
staticfile.save_as = self.endfile
@ -1131,8 +1123,18 @@ class TestStaticGenerator(unittest.TestCase):
self.generator.generate_context()
self.generator.generate_output(None)
self.assertTrue(os.path.islink(self.endfile))
self.assertEqual(os.path.realpath(self.endfile),
os.path.realpath(self.startfile))
# os.path.realpath is broken on Windows before python3.8 for symlinks.
# This is a (ugly) workaround.
# see: https://bugs.python.org/issue9949
if os.name == 'nt' and sys.version_info < (3, 8):
def get_real_path(path):
return os.readlink(path) if os.path.islink(path) else path
else:
get_real_path = os.path.realpath
self.assertEqual(get_real_path(self.endfile),
get_real_path(self.startfile))
def test_delete_existing_file_before_mkdir(self):
with open(self.startfile, "w") as f:

View file

@ -1,6 +1,7 @@
import locale
import os
import re
from posixpath import join as posix_join
from pelican.settings import DEFAULT_CONFIG
from pelican.tests.support import (mute, skipIfNoExecutable, temporary_folder,
@ -448,5 +449,5 @@ class TestWordpressXMLAttachements(unittest.TestCase):
self.assertEqual(1, len(locations))
directory = locations[0]
self.assertTrue(
directory.endswith(os.path.join('content', 'article.rst')),
directory.endswith(posix_join('content', 'article.rst')),
directory)

View file

@ -25,11 +25,10 @@ class TestServer(unittest.TestCase):
os.chdir(self.temp_output)
def tearDown(self):
rmtree(self.temp_output)
os.chdir(self.old_cwd)
rmtree(self.temp_output)
def test_get_path_that_exists(self):
handler = ComplexHTTPRequestHandler(MockRequest(), ('0.0.0.0', 8888),
self.server)
handler.base_path = self.temp_output

View file

@ -136,6 +136,8 @@ class TestSettingsConfiguration(unittest.TestCase):
settings['ARTICLE_DIR']
settings['PAGE_DIR']
# locale.getdefaultlocale() is broken on Windows
# See: https://bugs.python.org/issue37945
@unittest.skipIf(platform == 'win32', "Doesn't work on Windows")
def test_default_encoding(self):
# Test that the default locale is set if not specified in settings

View file

@ -757,35 +757,32 @@ class TestDateFormatter(unittest.TestCase):
class TestSanitisedJoin(unittest.TestCase):
@unittest.skipIf(platform == 'win32',
"Different filesystem root on Windows")
def test_detect_parent_breakout(self):
with self.assertRaisesRegex(
RuntimeError,
"Attempted to break out of output directory to /foo/test"):
"Attempted to break out of output directory to "
"(.*?:)?/foo/test"): # (.*?:)? accounts for Windows root
utils.sanitised_join(
"/foo/bar",
"../test"
)
@unittest.skipIf(platform == 'win32',
"Different filesystem root on Windows")
def test_detect_root_breakout(self):
with self.assertRaisesRegex(
RuntimeError,
"Attempted to break out of output directory to /test"):
"Attempted to break out of output directory to "
"(.*?:)?/test"): # (.*?:)? accounts for Windows root
utils.sanitised_join(
"/foo/bar",
"/test"
)
@unittest.skipIf(platform == 'win32',
"Different filesystem root on Windows")
def test_pass_deep_subpaths(self):
self.assertEqual(
utils.sanitised_join(
"/foo/bar",
"test"
),
os.path.join("/foo/bar", "test")
utils.posixize_path(
os.path.abspath(os.path.join("/foo/bar", "test")))
)

View file

@ -728,8 +728,9 @@ def download_attachments(output_path, urls):
# Generate percent-encoded URL
scheme, netloc, path, query, fragment = urlsplit(url)
path = quote(path)
url = urlunsplit((scheme, netloc, path, query, fragment))
if scheme != 'file':
path = quote(path)
url = urlunsplit((scheme, netloc, path, query, fragment))
if not os.path.exists(full_path):
os.makedirs(full_path)

View file

@ -27,8 +27,10 @@ logger = logging.getLogger(__name__)
def sanitised_join(base_directory, *parts):
joined = os.path.abspath(os.path.join(base_directory, *parts))
if not joined.startswith(os.path.abspath(base_directory)):
joined = posixize_path(
os.path.abspath(os.path.join(base_directory, *parts)))
base = posixize_path(os.path.abspath(base_directory))
if not joined.startswith(base):
raise RuntimeError(
"Attempted to break out of output directory to {}".format(
joined
@ -391,10 +393,9 @@ def get_relative_path(path):
def path_to_url(path):
"""Return the URL corresponding to a given path."""
if os.sep == '/':
return path
else:
return '/'.join(split_all(path))
if path is not None:
path = posixize_path(path)
return path
def posixize_path(rel_path):

View file

@ -1,5 +1,6 @@
import logging
import os
from posixpath import join as posix_join
from urllib.parse import urljoin
from feedgenerator import Atom1Feed, Rss201rev2Feed, get_tag_uri
@ -25,7 +26,7 @@ class Writer:
# See Content._link_replacer for details
if self.settings['RELATIVE_URLS']:
self.urljoiner = os.path.join
self.urljoiner = posix_join
else:
self.urljoiner = lambda base, url: urljoin(
base if base.endswith('/') else base + '/', url)