Skip to content

Commit

Permalink
Merge pull request #40 from moggers87/16-tree-walkies
Browse files Browse the repository at this point in the history
Implement Node.get_from_path
  • Loading branch information
moggers87 committed Aug 25, 2018
2 parents 6f11401 + 886c8db commit 3970014
Show file tree
Hide file tree
Showing 3 changed files with 223 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ Unreleased
- Improved test coverage and fixed numerous bugs
- Implemented cache busting for static assets (images, CSS, and such). Use the
``cache-bust-glob`` option to control which files are cache busted.
- Implemented ``Node.get_from_path`` which can fetch a
:class:`exhibition.main.Node` specified by a path

.. _zero-zero-three:

Expand Down
35 changes: 35 additions & 0 deletions exhibition/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,9 @@ def __init__(self, path, parent, meta=None):

if self.parent:
self.parent.add_child(self)
self.root_node = self.parent.root_node
else:
self.root_node = self

@classmethod
def from_path(cls, path, parent=None, meta=None):
Expand Down Expand Up @@ -255,6 +258,38 @@ def from_path(cls, path, parent=None, meta=None):
def __repr__(self):
return "<%s: %s>" % (self.__class__.__name__, self.path_obj.name)

def get_from_path(self, path):
"""
Given a relative or absolute path, return the :class:`Node` that
represents that path.
:param path:
A :class:`str` or :class:`pathlib.Path`
"""
if not isinstance(path, pathlib.PurePath):
path = pathlib.PurePath(path)

if path.is_absolute():
found_node = self.root_node
parts = path.parts[1:]
else:
if self.is_leaf:
found_node = self.parent
else:
found_node = self
parts = path.parts

try:
for part in parts:
if part == "..":
found_node = found_node.parent
else:
found_node = found_node.children[part]
except KeyError as exp:
raise OSError("{} could not find {}".format(self, exp.args)) from exp

return found_node

@property
def full_path(self):
"""
Expand Down
186 changes: 186 additions & 0 deletions exhibition/tests/test_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -490,3 +490,189 @@ def test_cache_bust_text_file(self):
"bust-me.{}.jpg".format(JSON_DIGEST))))

self.assertEqual(child_node.full_url, "/bust-me.{}.jpg".format(JSON_DIGEST))

def test_get_from_path_relative_str_on_leaf(self):
parent_path = pathlib.Path(self.content_path.name)
pathlib.Path(self.content_path.name, "images").mkdir()
child1_path = pathlib.Path(self.content_path.name, "images", "bust-me.jpg")
child1_path.touch()
pathlib.Path(self.content_path.name, "pages").mkdir()
child2_path = pathlib.Path(self.content_path.name, "pages", "page.html")
child2_path.touch()

parent_node = Node.from_path(parent_path)

child_node = parent_node.children["images"].children["bust-me.jpg"]
target_node = parent_node.children["pages"].children["page.html"]

self.assertEqual(child_node.get_from_path("../pages/page.html"), target_node)

def test_get_from_path_relative_pathlib_on_leaf(self):
parent_path = pathlib.Path(self.content_path.name)
pathlib.Path(self.content_path.name, "images").mkdir()
child1_path = pathlib.Path(self.content_path.name, "images", "bust-me.jpg")
child1_path.touch()
pathlib.Path(self.content_path.name, "pages").mkdir()
child2_path = pathlib.Path(self.content_path.name, "pages", "page.html")
child2_path.touch()

parent_node = Node.from_path(parent_path)

child_node = parent_node.children["images"].children["bust-me.jpg"]
target_node = parent_node.children["pages"].children["page.html"]

self.assertEqual(child_node.get_from_path(pathlib.Path("..", "pages", "page.html")),
target_node)

def test_get_from_path_relative_str_on_dir(self):
parent_path = pathlib.Path(self.content_path.name)
pathlib.Path(self.content_path.name, "images").mkdir()
child1_path = pathlib.Path(self.content_path.name, "images", "bust-me.jpg")
child1_path.touch()
pathlib.Path(self.content_path.name, "pages").mkdir()
child2_path = pathlib.Path(self.content_path.name, "pages", "page.html")
child2_path.touch()

parent_node = Node.from_path(parent_path)

child_node = parent_node.children["images"]
target_node = parent_node.children["pages"].children["page.html"]

self.assertEqual(child_node.get_from_path("../pages/page.html"), target_node)

def test_get_from_path_relative_pathlib_on_dir(self):
parent_path = pathlib.Path(self.content_path.name)
pathlib.Path(self.content_path.name, "images").mkdir()
child1_path = pathlib.Path(self.content_path.name, "images", "bust-me.jpg")
child1_path.touch()
pathlib.Path(self.content_path.name, "pages").mkdir()
child2_path = pathlib.Path(self.content_path.name, "pages", "page.html")
child2_path.touch()

parent_node = Node.from_path(parent_path)

child_node = parent_node.children["images"]
target_node = parent_node.children["pages"].children["page.html"]

self.assertEqual(child_node.get_from_path(pathlib.Path("..", "pages", "page.html")),
target_node)

def test_get_from_path_relative_str_with_dot(self):
parent_path = pathlib.Path(self.content_path.name)
pathlib.Path(self.content_path.name, "images").mkdir()
child1_path = pathlib.Path(self.content_path.name, "images", "bust-me.jpg")
child1_path.touch()
pathlib.Path(self.content_path.name, "pages").mkdir()
child2_path = pathlib.Path(self.content_path.name, "pages", "page.html")
child2_path.touch()

parent_node = Node.from_path(parent_path)

child_node = parent_node.children["pages"]
target_node = parent_node.children["pages"].children["page.html"]

self.assertEqual(child_node.get_from_path("./page.html"), target_node)

def test_get_from_path_relative_pathlib_with_dot(self):
parent_path = pathlib.Path(self.content_path.name)
pathlib.Path(self.content_path.name, "images").mkdir()
child1_path = pathlib.Path(self.content_path.name, "images", "bust-me.jpg")
child1_path.touch()
pathlib.Path(self.content_path.name, "pages").mkdir()
child2_path = pathlib.Path(self.content_path.name, "pages", "page.html")
child2_path.touch()

parent_node = Node.from_path(parent_path)

child_node = parent_node.children["pages"]
target_node = parent_node.children["pages"].children["page.html"]

self.assertEqual(child_node.get_from_path(pathlib.Path(".", "page.html")),
target_node)

def test_get_from_path_absolute_str(self):
parent_path = pathlib.Path(self.content_path.name)
pathlib.Path(self.content_path.name, "images").mkdir()
child1_path = pathlib.Path(self.content_path.name, "images", "bust-me.jpg")
child1_path.touch()
pathlib.Path(self.content_path.name, "pages").mkdir()
child2_path = pathlib.Path(self.content_path.name, "pages", "page.html")
child2_path.touch()

parent_node = Node.from_path(parent_path)

child_node = parent_node.children["images"].children["bust-me.jpg"]
target_node = parent_node.children["pages"].children["page.html"]

self.assertEqual(child_node.get_from_path("/pages/page.html"), target_node)

def test_get_from_path_absolute_pathlib(self):
parent_path = pathlib.Path(self.content_path.name)
pathlib.Path(self.content_path.name, "images").mkdir()
child1_path = pathlib.Path(self.content_path.name, "images", "bust-me.jpg")
child1_path.touch()
pathlib.Path(self.content_path.name, "pages").mkdir()
child2_path = pathlib.Path(self.content_path.name, "pages", "page.html")
child2_path.touch()

parent_node = Node.from_path(parent_path)

child_node = parent_node.children["images"].children["bust-me.jpg"]
target_node = parent_node.children["pages"].children["page.html"]

self.assertEqual(child_node.get_from_path(pathlib.Path("/pages/page.html")), target_node)

def test_get_from_path_not_existing_from_str(self):
parent_path = pathlib.Path(self.content_path.name)
pathlib.Path(self.content_path.name, "images").mkdir()
child1_path = pathlib.Path(self.content_path.name, "images", "bust-me.jpg")
child1_path.touch()
pathlib.Path(self.content_path.name, "pages").mkdir()
child2_path = pathlib.Path(self.content_path.name, "pages", "page.html")
child2_path.touch()

parent_node = Node.from_path(parent_path)

child_node = parent_node.children["images"].children["bust-me.jpg"]

with self.assertRaises(OSError):
child_node.get_from_path("../not-a-page.html")

def test_get_from_path_not_existing_from_pathlib(self):
parent_path = pathlib.Path(self.content_path.name)
pathlib.Path(self.content_path.name, "images").mkdir()
child1_path = pathlib.Path(self.content_path.name, "images", "bust-me.jpg")
child1_path.touch()
pathlib.Path(self.content_path.name, "pages").mkdir()
child2_path = pathlib.Path(self.content_path.name, "pages", "page.html")
child2_path.touch()

parent_node = Node.from_path(parent_path)

child_node = parent_node.children["images"].children["bust-me.jpg"]

with self.assertRaises(OSError):
child_node.get_from_path(pathlib.Path("..", "not-a-page.html"))

def test_root_node_is_kept(self):
parent_path = pathlib.Path(self.content_path.name)
pathlib.Path(self.content_path.name, "images").mkdir()
pathlib.Path(self.content_path.name, "pages").mkdir()
child_path = pathlib.Path(self.content_path.name, "pages", "page.html")
child_path.touch()

parent_node = Node.from_path(parent_path)

self.assertEqual(parent_node.root_node, parent_node)
self.assertEqual(parent_node.children["pages"].root_node, parent_node)
self.assertEqual(parent_node.children["pages"].children["page.html"].root_node, parent_node)
self.assertEqual(parent_node.children["pages"].children["page.html"].parent.root_node,
parent_node)
self.assertEqual(
parent_node.children["pages"].children["page.html"].parent.parent.root_node,
parent_node
)
self.assertEqual(
parent_node.children["pages"].children["page.html"].parent.parent.root_node,
parent_node
)

0 comments on commit 3970014

Please sign in to comment.