TruePath icon indicating copy to clipboard operation
TruePath copied to clipboard

#18 implement behavior to calculate parents from exclusively-relative paths

Open Kataane opened this issue 7 months ago • 1 comments

Closes #18.

Pull Request: Define Parent for LocalPath(".") and Relative Paths

Problem Description: Currently, new LocalPath(".").Parent (similarly for paths like .. or ../..) is not defined. This creates ambiguity and inconsistency in the behavior of the library.

Proposed Solution: After researching how other libraries handle the parent of paths such as ".", "..", and "../..", we propose that these should return null. This approach aligns with the general expectations and behavior seen in other path-handling libraries.

Changes Made:

  • Implemented logic to return null for the parent of LocalPath("."), LocalPath(".."), and other relative paths.
  • Added corresponding unit tests to ensure consistent behavior and to prevent regressions in the future. These tests cover the mentioned cases as well as any arbitrary exclusively-relative path.

Rationale: It's important to note that the decision to return null is debatable. Here are some examples of how different languages handle these cases:

Python:

from pathlib import Path
import os

# Pathlib
path = Path(".")
print(f"For the . parent is {path.parent}")  # For the . parent is .
path = Path("..")
print(f"For the .. parent is {path.parent}")  # For the .. parent is .
path = Path("../..")
print(f"For the ../.. parent is {path.parent}")  # For the ../.. parent is ..

# os.path
path = os.path.dirname(".")
print(f"For the . parent is {path}")  # For the . parent is 
path = os.path.dirname("..")
print(f"For the .. parent is {path}")  # For the .. parent is 
path = os.path.dirname("../..")
print(f"For the ../.. parent is {path}")  # For the ../.. parent is ..

Go:

package main

import (
    "fmt"
    "path"
)

func main() {
    // .
    // .
    // ..
    parent := path.Dir(".")
    fmt.Println(parent)
    parent2 := path.Dir("..")
    fmt.Println(parent2)
    parent3 := path.Dir("../..")
    fmt.Println(parent3)
}

Java:

import java.nio.file.Path;
import java.nio.file.Paths;

public class Main {
    public static void main(String[] args) {
        // Parent of current directory: null
        // Parent of parent directory: null
        // Parent directory of the file: ..
        Path currentDir = Paths.get(".");
        Path parentDir = currentDir.getParent();
        System.out.println("Parent of current directory: " + parentDir);

        Path parentPath = Paths.get("..");
        Path parentOfParent = parentPath.getParent();
        System.out.println("Parent of parent directory: " + parentOfParent);

        Path filePath = Paths.get("../..");
        Path fileParent = filePath.getParent();
        System.out.println("Parent directory of the file: " + fileParent);
    }
}

C#:

using System;
using System.IO;

public class Program
{
    public static void Main()
    {
        // All returns the current working folder

        DirectoryInfo dirInfo = new DirectoryInfo(".");
        var parentDir = dirInfo.Parent;
        Console.WriteLine(parentDir);

        DirectoryInfo dirInfo2 = new DirectoryInfo("..");
        var parentDir2 = dirInfo2.Parent;
        Console.WriteLine(parentDir2);

        DirectoryInfo dirInfo3 = new DirectoryInfo("../..");
        var parentDir3 = dirInfo3.Parent;
        Console.WriteLine(parentDir3);
    }
}

Rust:

use std::path::Path;

fn main() {
    let path = Path::new(".");
    println!("{:?}", path.parent()); // Some("")

    let path = Path::new("..");
    println!("{:?}", path.parent()); // Some("")

    let path = Path::new("../..");
    println!("{:?}", path.parent()); // Some("..")
}

If you look behind the trends, you can see that modern, trendy languages try to reclaim the solved path or treat it fairly with this kind of behaviour.

Bottom line, I definitely can't claim that returning null is a good idea

Kataane avatar Jul 20 '24 13:07 Kataane