Help language development. Donate to The Perl Foundation

Trait::Env cpan:SCIMON last updated on 2021-04-29

Trait::Env - Trait to set an attribute from an environment variable.


    use Trait::Env;
    class Test {
        # Sets from %*ENV{HOME}. Undef if the var doesn't exist
        has $.home is env;

        # Sets from %*ENV{TMPDIR}. Defaults to '/tmp'
        has $.tmpdir is env is default "/tmp";

        # Sets from %*ENV{EXTRA_DIR}. Defaults to '/tmp'
        has $.extra-dir is env( :default</tmp> );

        # Set from %*ENV{WORKDIR}. Dies if not set.
        has $.workdir is env(:required);

        # Set from %*ENV{READ_DIRS.+} ordered lexically
        has is env;

        # Set from %*ENV{PATH} split on ':'
        # has @.path is env(:sep<:>);
        # Or default to the $*DISTRO.path-sep value
        has @.path is env;      
        # Set from %*ENV{NAME_MAP} data split on ';' pairs split on ':'
        # EG a:b;c:d => { "a" => "b", "c" => "d" }
        has is env( :sep<;>, :kvsep<:> );

        # Get all pairs where the key ends with '_POST'
        has is env( :post_match<_POST> );

        # Get all pairs where the Key starts with 'PRE_'
        has %.pre-map is env( :pre_match<PRE_> );

        # Get all pairs where the Key starts with 'PRE_' and ends with '_POST'
        has %.both-map is env( :pre_match<PRE_>, :post_match<_POST> );

        # Parses JSON data
        has $.json-data is env( :json );

    # Sets from %*ENV{HOME}. Undef if the var doesn't exist
    has $home is env;

    # Sets from %*ENV{PATH}. Uses default path seperator
    has @path is env;


Trait::Env is exports the new trait `is env`.

Note the the variable name will be uppercased and any dashes changed to underscores before matching against the environment. This functionality may be modifiable in the future.

For Booleans the standard Empty String == `False` other String == `True` works but the string "True" and "False" (any capitalization) will also map to True and False respectively.

If a required attribute is not set the code will raise a `X::Trait::Env::Required::Not::Set` Exception.

Defaults can be set using the standard `is default` trait or the `:default` key. Note that for Positional attributes only the `:default` key works.

Positional attributes will use the attribute name (after coercing) as the prefix to scan %*ENV for. Any keys starting with that prefix will be ordered by the key name lexically and their values put into the attribute.

Alternatively you can use the `:sep` key to specify a seperator, in which case the single value will be read based on the name and the list then created by spliting on this seperator.

If there is a single matching environment variable and no `:sep` key is set then the system will fall back to splitting on the `$*DISTRO.path-sep` value as a seperator.

Hashes can be single value with a `:sep` key to specify the seperator between pairs and a `:kvsep` to specifiy the seperator in each pair between key and value.

Hashes can also be defined by giving a `:post_match` or `:pre_match` arguments (or both). Any Environment variable starting with `:pre_match` is defined or ending with `:post-match` if defined will be included.

Scalars, Positionals and Associative attributes can all be typed.

Variables can also be defined with `is env` following the same rules. 

Attribute or Variable only `is env` traits can be loaded individually with `Trait::Env::Attribute` and `Trait::Env::Variable`.

Scalar Attributes and Variables can use `is env(:json)` which will parse the ENV string as a JSON string using `JSON::Tiny`. You can combine this with the `:default` and `:required` options but be aware that the `:default` value should be a data store NOT a JSON value.


Simon Proctor <[email protected]>

Thanks to Jonathan Worthington and Elizabeth Mattijsen for giving me the framework to build this on. Any mistakes are mine. 


Copyright 2018 Simon Proctor

This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.