Git Product home page Git Product logo

Comments (5)

passsy avatar passsy commented on May 7, 2024
final script = Script.capture((_) async {
  await run('which someProgram');
});

final err = await script.stdout.text;
final code = await script.exitCode;
expect(code, 1);
expect(err, contains("someProgram not found"));

Reading stdout before reading the exitCode unblocks me but is unexpected

from dart_cli_script.

passsy avatar passsy commented on May 7, 2024

Still getting it in 0.2.3+1.

Even worse, the workaround doesn't work anymore. It just prints capture failed with exit code 1.. How can I capture the output of a non-zero exit code when Script.capture immediately fails?

from dart_cli_script.

nex3 avatar nex3 commented on May 7, 2024

Sorry for the late reply here!

The behavior you're seeing is because a Script determines what its default behavior should be based on what's done synchronously after it's created. If you synchronously access Script.stdout or Script.stderr, those streams won't be piped to the outer capture or the host process by default; if you synchronously catch an error from Script.done or access Script.exitCode, that future's error won't go unhandled. (That's behavior that's built into the Future API; it's not specific to cli_script.)

So if you want to access both at once, you should make sure to get references to them synchronously before you start awaiting anything:

final script = Script.capture((_) async {
  await run('which someProgram');
});
final codeFuture = script.exitCode;
final errFuture = script.stdout.text;
expect(await codeFuture, 1);
expect(await errFuture, contains("someProgram not found"));

or more concisely:

final script = Script.capture((_) async {
  await run('which someProgram');
});
expect(script.exitCode, completion(1));
expect(script.stdout.text, completion(contains("someProgram not found")));

from dart_cli_script.

passsy avatar passsy commented on May 7, 2024

Got it.
When I ran into it I spent like 6h figuring it out. TBH, if there would have been another package with a similar feature set I would have switched.

Could the API be more explicit, like telling beforehand what should be captured?

final script = Script.capture((_) async {
    await run('which someProgram');
  }, 
  stdout: true, 
  stderr: false, 
  exitCode: false
);

dclis Progress.capture does both: print to stdout and capture the stream for later processing. Why not do both?

from dart_cli_script.

nex3 avatar nex3 commented on May 7, 2024

Got it. When I ran into it I spent like 6h figuring it out. TBH, if there would have been another package with a similar feature set I would have switched.

Could the API be more explicit, like telling beforehand what should be captured?

final script = Script.capture((_) async {
    await run('which someProgram');
  }, 
  stdout: true, 
  stderr: false, 
  exitCode: false
);

As a reader of that code, it's not really clear to me what's going on. Even knowing the context of this issue, I'm not sure whether stdout: true means "emit stdout to the parent context" or "I intend to handle stdout".

I'll take another pass at the documentation to try to call this out more explicitly, though.

dclis Progress.capture does both: print to stdout and capture the stream for later processing. Why not do both?

A number of reasons:

  • It's a potential memory leak. Emitting the stream to both places requires storing a buffer of it internally which will go undrained any time a user accesses the data through the implicit output stream. This can cause a program to hold on to a lot of data that the user may not expect to be retained, especially if the process is long-running and expected to operate in a more "streaming" mode. Similarly, every nested Script.capture() adds another buffered copy of the data emitted.

  • It makes the usability worse in many cases. If you do want to access the stdio manually, you also have to make sure that the implicit stdio is handled appropriately for every single script.

  • It doesn't match the behavior of Future. It's baked into the language that Script.done will treat an error as unhandled if it's not listened to synchronously, and having Script.stdout treat its output as unhandled if it's not listened to synchronously rhymes with that API. These sorts of rhymes are important when dealing with asynchronous APIs, which are intrinsically difficult to understand.

  • It doesn't match the shell. One of my guiding design principles for cli_script is "when in doubt, do the same thing as sh" and in sh each process has exactly one output stream of each type that may go one place or may go another, but never goes both.

from dart_cli_script.

Related Issues (11)

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.