From 49106b020c47d3352dc40ed6b295bd59a962b308 Mon Sep 17 00:00:00 2001 From: Allison Thackston Date: Thu, 24 Aug 2023 23:32:31 -0700 Subject: [PATCH] Return ignore_hidden functionality (#573) Will be deprecated in the next major release. --- mkdocs_simple_plugin/plugin.py | 2 +- mkdocs_simple_plugin/simple.py | 30 +++++++++++++++++++++++++++++- tests/test_simple.py | 26 ++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 2 deletions(-) diff --git a/mkdocs_simple_plugin/plugin.py b/mkdocs_simple_plugin/plugin.py index b4af582b..d65444a1 100644 --- a/mkdocs_simple_plugin/plugin.py +++ b/mkdocs_simple_plugin/plugin.py @@ -148,7 +148,7 @@ class SimplePlugin(BasePlugin): ('ignore_hidden', config_options.Deprecated( moved_to=None, message="Common ignore files have been added to 'ignore' instead", - removed=True)), + removed=False)), # # ### merge_docs_dir # diff --git a/mkdocs_simple_plugin/simple.py b/mkdocs_simple_plugin/simple.py index de49a157..d680e099 100644 --- a/mkdocs_simple_plugin/simple.py +++ b/mkdocs_simple_plugin/simple.py @@ -2,6 +2,7 @@ import fnmatch import os import pathlib +import stat from shutil import copy2 as copy from dataclasses import dataclass @@ -29,6 +30,7 @@ def __init__( folders: list, include: list, ignore: list, + ignore_hidden: bool, ignore_paths: list, semiliterate: list, **kwargs): @@ -39,6 +41,7 @@ def __init__( folders (list): Glob of folders to search for files include (list): Glob of filenames to copy directly to output ignore (list): Glob of paths to exclude + ignore_hidden (bool): Whether to ignore hidden files for processing ignore_paths (list): Absolute filepaths to exclude semiliterate (list): Settings for processing file content in Semiliterate @@ -48,6 +51,8 @@ def __init__( self.folders = set(folders) self.doc_glob = set(include) self.ignore_glob = set(ignore) + self.ignore_hidden = ignore_hidden # to be deprecated + self.hidden_prefix = set([".", "__"]) # to be deprecated self.ignore_paths = set(ignore_paths) self.semiliterate = [] for item in semiliterate: @@ -118,14 +123,37 @@ def match_pattern(name, pattern): def should_extract_file(self, name: str): """Check if file should be extracted.""" + def has_hidden_attribute(filepath): + """Returns true if hidden attribute is set.""" + try: + return bool(os.stat(filepath).st_file_attributes & + stat.FILE_ATTRIBUTE_HIDDEN) + except (AttributeError, AssertionError): + return False + + def has_hidden_prefix(filepath): + """Returns true if the file starts with a hidden prefix.""" + parts = filepath.split(os.path.sep) + + def hidden_prefix(name): + if name == ".": + return False + return any(name.startswith(pattern) + for pattern in self.hidden_prefix) + return any(hidden_prefix(part) for part in parts) # Check if file is text based try: with open(name, 'r', encoding='utf-8') as f: _ = f.read() - return True except UnicodeDecodeError: return False + # Check if file is hidden and should ignore + if self.ignore_hidden: + is_hidden = has_hidden_prefix(name) or has_hidden_attribute(name) + return not is_hidden + return True + def merge_docs(self, from_dir, dirty=False): """Merge docs directory""" if not os.path.exists(from_dir): diff --git a/tests/test_simple.py b/tests/test_simple.py index c3cd2f71..d6dd9758 100644 --- a/tests/test_simple.py +++ b/tests/test_simple.py @@ -1,6 +1,8 @@ #!/usr/bin/env python """Test mkdocs_simple_plugin.simple""" import unittest +from unittest.mock import patch +import stat import os from pyfakefs.fake_filesystem_unittest import TestCase @@ -18,6 +20,7 @@ def setUp(self) -> None: "folders": ["*"], "ignore": [], "include": ["*.md"], + "ignore_hidden": True, "ignore_paths": [], "semiliterate": {} } @@ -36,6 +39,29 @@ def test_should_extract_file(self): # Test text file self.assertTrue(simple_test.should_extract_file("example.md")) + @patch("os.stat") + def test_ignore_hidden(self, os_stat): + """Test should_extract_file for correctness.""" + simple_test = simple.Simple(**self.default_settings) + # Check ignore_hidden + simple_test.ignore_hidden = True + os_stat.return_value.st_file_attributes = 0 + self.fs.create_file("test.md", contents="Hello_word") + self.assertTrue(simple_test.should_extract_file('test.md')) + self.fs.create_file("folder/test.md", contents="Hello_word") + self.assertTrue(simple_test.should_extract_file('./folder/test.md')) + self.fs.create_file("__pycache__") + self.assertFalse(simple_test.should_extract_file('__pycache__')) + self.fs.create_file(".mkdocsignore") + self.assertFalse(simple_test.should_extract_file('.mkdocsignore')) + self.fs.create_file(".git/objects/34/49807110bdc8") + self.assertFalse(simple_test.should_extract_file( + ".git/objects/34/49807110bdc8")) + # Check hidden file attribute + self.fs.create_file("/test/file") + os_stat.return_value.st_file_attributes = stat.FILE_ATTRIBUTE_HIDDEN + self.assertFalse(simple_test.should_extract_file('/test/file')) + def test_ignored_default(self): """Test ignored files.""" simple_test = simple.Simple(**self.default_settings)