Pregunta

Is there any way to access some of the attributes listed in a pubspec.yaml file in that files Dart application?

In particular, the version and description attributes may be quite useful to see in a version info dialog, or even a '--version' when using a console app. I haven't been able to find a way to access in the API. I'm not sure if Mirrors would have anything appropriate, but if a web app is compiled to JS, then I don't see the description anywhere in the output JS.

Thanks.

EDIT
feature request: https://code.google.com/p/dart/issues/detail?id=18769

¿Fue útil?

Solución 2

you can install the "dart_config" package and use this code to parse a pubspec.yaml file:

import 'package:dart_config/default_server.dart';
import 'dart:async';

void main() {
  Future<Map> conf = loadConfig("../pubspec.yaml");
  conf.then((Map config) {
    print(config['name']);
    print(config['description']);
    print(config['version']);
    print(config['author']);
    print(config['homepage']);
    print(config['dependencies']);
  });
}

The output looks similar to this:

test_cli
A sample command-line application
0.0.1
Robert Hartung
URL
{dart_config: any}

EDIT

You can do it with the Yaml package itself:

*NOTE: this will not work on Flutter Web

import 'package:yaml/yaml.dart';
import 'dart:io'; // *** NOTE *** This will not work on Flutter Web

void main() {      
    File f = new File("../pubspec.yaml");
    f.readAsString().then((String text) {
      Map yaml = loadYaml(text);
      print(yaml['name']);
      print(yaml['description']);
      print(yaml['version']);
      print(yaml['author']);
      print(yaml['homepage']);
      print(yaml['dependencies']);
    });
}

Regards Robert

Otros consejos

FOR FLUTTER ONLY

Please use this new package package_info_plus from flutter community.

import 'package:package_info_plus/package_info_plus.dart';

PackageInfo packageInfo = await PackageInfo.fromPlatform();

String appName = packageInfo.appName;
String packageName = packageInfo.packageName;
String version = packageInfo.version;
String buildNumber = packageInfo.buildNumber;

BELOW SOLUTION IS DEPRICATED.

I know the OP wants to read YAML but for flutter dev's you guys can read the version and other info of the application using package_info.

This is the sample to fetch details from Android/iOS application.

import 'package:package_info/package_info.dart';

PackageInfo packageInfo = await PackageInfo.fromPlatform();

String appName = packageInfo.appName;
String packageName = packageInfo.packageName;
String version = packageInfo.version;
String buildNumber = packageInfo.buildNumber;

None of the above answers worked for me, but here's a working solution for a Flutter app:

In your pubspec.yaml add the "pubspec.yaml" to assets:

assets:
  - assets/
  - pubspec.yaml

If you have a widget where you need to show the app version like this:

...
Container(
  child: Text('Version: 1.0.0+1'),
),
...

Wrap your widget with a FutureBuilder like this:

import 'package:flutter/services.dart';
import 'package:yaml/yaml.dart';

...
        FutureBuilder(
            future: rootBundle.loadString("pubspec.yaml"),
            builder: (context, snapshot) {
              String version = "Unknown";
              if (snapshot.hasData) {
                var yaml = loadYaml(snapshot.data);
                version = yaml["version"];
              }

              return Container(
                child: Text(
                  'Version: $version'
                ),
              );
            }),
...

The services rootBundle property contains the resources that were packaged with the application when it was built.

If you want to show the version without the build number, you can split the string like so:

'Version: ${version.split("+")[0]}'

UPDATE: As mentioned by @wildsurfer, this approach has a potential security risk in web development because the pubspec.yaml is shared with the browser!

So assuming that this is for a dart cli application then the @Robert suggestion won't work.

dart_config isn't available for dart 2.x and your pubspec.yaml isn't going to be relative to your cwd except when you are in your development environment

So you need to get the pubspec.yaml relative to the libraries executable path.

This example uses the 'paths' package but it isn't required.

This can be obtained by:

import 'package:path/path.dart'; 

String pathToYaml =  join(dirname(Platform.script.toFilePath()), '../pubspec.yaml');

You can now read the yaml:

import 'package:path/path.dart'; 
import 'package:yaml/yaml.dart';

String pathToYaml = join(dirname(Platform.script.toFilePath()), '../pubspec.yaml');

File f = new File(pathToYaml);
String yamlText =   f.readAsStringSync();
      Map yaml = loadYaml(yamlText);
      print(yaml['name']);
      print(yaml['description']);
      print(yaml['version']);
      print(yaml['author']);
      print(yaml['homepage']);
      print(yaml['dependencies']);
    });                                       

You can access pubspec.yaml properties with the official pubspec_parse package from the Dart team.

dart pub add pubspec_parse
import 'dart:io';
import 'package:pubspec_parse/pubspec_parse.dart';

final pubspec = File('pubspec.yaml').readAsStringSync();
final parsed = Pubspec.parse(pubspec);

You can then access typed properties on the parsed object.

You can find supported properties here: https://pub.dev/documentation/pubspec_parse/latest/pubspec_parse/Pubspec-class.html.

For Flutter only (Web, Android and IOS)... since October 2020

If you want your app working on Web, Android and IOS use "Package info_plus" instead.

How to Incorporate Automated Version Information into A Dart Command Line App

To update version information in your code without having to package a resource file to be parsed during run time, you can have the information hard coded into an automatically generated dart source file which gets compiled into your binary. The following example hard codes the version, name, and description information into the Map object "meta" in a meta.dart file. The meta.dart file is recreated and overwritten every time the test suite is run in development. To verify the source code has the correct version information, the app's code verifies the version and other meta information against the attributes in the pubspec.yaml file (but only when run as interpreted code in development). If there is a difference from pubspec.yaml, it throws an exception. Once compiled into a binary, it will skip that check as it won't find the pubspec.yaml file, so no error is thrown from the binary. Even if a pubspec.yaml file happens to be around and is found, it only throws an exception and does not create a "meta.dart" source file.

1. Create a MetaUpdate class and save it as "meta_update.dart":

import 'dart:io';
import 'package:yaml/yaml.dart';
import 'meta.dart';

class MetaUpdate {
  String pathToYaml = "";
  String metaDartFileContents = "";
  MetaUpdate(this.pathToYaml);

  void writeMetaDartFile(String metaDartFilePath) {
    File metaDartFile = File(metaDartFilePath);

    String metaDartFileContents = """
/// DO NOT EDIT THIS FILE EXCEPT TO ENTER INITIAL VERSION AND OTHER META INFO 
/// THIS FILE IS AUTOMATICALLY OVER WRITTEN BY MetaUpdate 

Map<String, String> meta = <String, String>{
  "name": "${getPubSpec('name')}",
  "description":
      // ignore: lines_longer_than_80_chars
      "${getPubSpec('description')}",  
  "version":"${getPubSpec('version')}",
};
  """;

    metaDartFile.writeAsStringSync(metaDartFileContents);
  }

  String getPubSpec(String pubSpecParam) {
    File f = File(pathToYaml);

    String yamlText = f.readAsStringSync();
    // ignore: always_specify_types
    Map yaml = loadYaml(yamlText);

    return yaml[pubSpecParam];
  }

  void verifyLatestVersionFromPubSpec() {
    try {
      File f = File(pathToYaml);
      //exit if no pubspec found so no warning in production
      if (!f.existsSync()) return;
      //compare meta.dart with pubspec meta and give warning if difference
      if (meta.keys
          .where((dynamic e) => (meta[e] != getPubSpec(e)))
          .isNotEmpty) {
        throw Exception(
            """Version number and other meta attributes in code are different from pubspec.yaml.  Please check pubspec.yaml and then run test so that MetaUpdate can update meta information in code, then recompile""");
      }
    } on Exception {
      rethrow;
    }
  }
}


2. Create a "meta.dart" file:

/// DO NOT EDIT THIS FILE EXCEPT TO ENTER INITIAL VERSION AND OTHER META INFO 
/// THIS FILE IS AUTOMATICALLY OVER WRITTEN BY MetaUpdate 

Map<String, String> meta = <String, String>{
  "name": "Acme Transmogrifier",
  "description":      
      "The best dart application ever.",  
  "version":"2021.09.001",
};

When you initially create the meta.dart file, copy your specific info from pubspec.yaml. This will later be overwritten each time your MetaUpdate.writeMetaDartFile() is run, changing the contents whenever the info in pubspec.yaml is changed.

3. Implement The Version Update In Your Test Code

Add the following in the first line of Main() in your test code (not the source of the main program, we don't want it to be compiled into the binary), changing the path to meta.dart as appropriate:

MetaUpdate("pubspec.yaml").writeMetaDartFile("lib/src/meta.dart");

4. Add A Meta Check To Your Main Code

Put this in your app's code so it is one of the first methods executed when your app is run - it will generate an exception if there is a difference between the attributes shown in the meta.dart and pubspec.yaml:

    MetaUpdate("pubspec.yaml").verifyLatestVersionFromPubSpec();

5. Using

  • Make sure the Name, Version, and Description information in pubspec.yaml contains the latest information you want reflected in your code.
  • Import "meta.dart" and insert meta['name'], meta['version'], etc. where you need them to be shown (e.g., in --help or --version messages to be printed to the console).
  • As long as you run your tests before compiling your code the meta information will be accurately reflected in your code.
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top