Coder Social home page Coder Social logo

Comments (7)

lrhn avatar lrhn commented on July 21, 2024
  • a Path type in the standard library that makes sure no forbidden characters are used

Which characters are forbidden depends on the file system, or at least the operating system. It's not just characters, Windows disallows some file names too ("con", "nul", etc.).
If it can also depend on the file system, then there is no way to validate a Path object without actually trying to resolve the path and see if it works. (Which it doesn't if it's for a file or directory that hasn't been created yet.)

But probably doable to some degree, there are just limits on what can be validated up-front.
Which is why using a String has been working well so far.
(Actually, a file path is not a Dart string, it's more like a C-string, defined as a sequence of bytes, not Unicode characters.)

The package:path API also uses strings as file paths. It originally tried something else, and using strings was found to be much more convenient.

  • A Linter rule that forbade the creation of FileSystemEntityType directly and his sub-types.

The FileSystemEntityType is a final class with no public constructor, basically an enum without the exhaustiveness, so you can't create instances directly, and there are no subtypes.

  • A function that makes the gap between Path and FileSystemEntityType in the standard library, like the following

That would be something like

  FileSystemEntity fromPath(String path) =>
     switch (FileStat.statSync(path).type) {
         FileSystemEntityType.file => File(path),
         FileSystemEntityType.directory => Directory(path),
         FileSystemEntityType.link => Link(path),
         FileSystemEntityType.notFound => throw ArgumentError.value(path, "path", "Not found"),
         _ => throw UnsupportedError("Unknown type"),
    };

from sdk.

stephane-archer avatar stephane-archer commented on July 21, 2024

@lrhn I'm curious what package:path tried in the past and how close it was to what I proposed, and why they finally moved to String, could you clarify?

Regarding the linter, I wasn't clear about what I meant.
I would like to force in the codebase the use of fromPath and not use Directory(path), File(path), and Link(path) directly because it's error-prone.

Is there any reason why fromPath is not something you wouldn't add to the standard library?

from sdk.

AkashKeote avatar AkashKeote commented on July 21, 2024
import 'dart:io';

class Path {
  final String value;

  Path(this.value);
}

class PathNotFoundException implements Exception {
  final String path;
  final OSError osError;

  PathNotFoundException(this.path, this.osError);

  @override
  String toString() => 'PathNotFoundException: Path "$path" not found (${osError.message})';
}

FileSystemEntity pathToFileSystemEntity(Path path) {
  FileSystemEntityType type = FileSystemEntity.typeSync(path.value);

  if (type == FileSystemEntityType.notFound) {
    throw PathNotFoundException(path.value, const OSError());
  }

  switch (type) {
    case FileSystemEntityType.directory:
      return Directory(path.value);
    case FileSystemEntityType.file:
      return File(path.value);
    case FileSystemEntityType.link:
      return Link(path.value);
    default:
      throw StateError("Unknown type of FileSystemEntity");
  }
}

from sdk.

AkashKeote avatar AkashKeote commented on July 21, 2024

as i am the beginner i dont know much used of the github but i can help you with this
We may implement this by using linter rule
we define the path
then use linter rule
convert that code

example:

void main() {
  try {
    Path myPath = Path('/valid/path/to/something');
    FileSystemEntity entity = pathToFileSystemEntity(myPath);
    print('Entity type: ${entity.runtimeType}');
  } catch (e) {
    print('Error: $e');
  }
}

from sdk.

lrhn avatar lrhn commented on July 21, 2024

While fromPath can work, it works equally well from a String, and equally badly in that it cannot represent a non-existing file.
If you want to create a new file, you do var file = File(path); file.createSync(); or similar. The fromPath function would throw for a non-existing file, so it can't be used here, which means you still need to use the File and Directory constructors, which makes a lint prohibiting those untenable.

The problem with file systems is that they are the source of truth about what exists and what does not, and it can change at any time while a program is running. Creating a Path object that, somehow, validates that its context is syntactically valid, could potentially end up becoming invalid if another process mounts another file system with different valid symbols (say, someone mounts an ISO-9660 CD-ROM), or maybe it was rejected too soon if someone mounts an Ext3 file system on Windows. (I have no idea how the OSes actually handle that, maybe it will work fine.)

(Heck, creating a File object, or getting a File object back from Directory.list, doesn't guarantee that that path actually still represents a file. It's more of a query/response object than representing the actual state of the file system.)

If the Path validation allows any possibly valid (on any file system, anywhere), then it won't reject much of anything.

The trade-offs are generally always such that using strings is good enough, and any advantage you can get by introducing a Path class is so minuscule that it doesn't carry its own weight.
A string being a path is more of a role than a type, and you can't know whether it will work any easier than just trying to use it as a path.

from sdk.

stephane-archer avatar stephane-archer commented on July 21, 2024

@lrhn I see what you mean when you say that File and Directory are query objects, they are not like file descriptors. I wasn't seeing them in that way.
I'm not sure why you would want to represent a non-existing file. If it is for checking its nonexistence, you will get the result with the exception, that it's like a fail open in other languages.

A string being a path is more of a role than a type

Do you think it's a bad design decision to create a type for a "role" ?

typedef Path = String;

(Obviously, Path can become much more complex and offer more guarantees and convenient member function)

from sdk.

lrhn avatar lrhn commented on July 21, 2024

The reason to represent a non-existing file would be to create it.

It's definitely a possibility to create a Path type, probably an extension type on a String value, with the operations of package:path, and maybe more.
If the type implements String, it can be used where a string is allowed, so it can be defined in any package, without changing existing APIs.

from sdk.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.