Skip to content

Commit

Permalink
Add support for setting environment variables.
Browse files Browse the repository at this point in the history
Specified as a list of NAME=VALUE lines in the pgfutils.environment
configuration option.
  • Loading branch information
bcbnz committed Nov 22, 2020
1 parent f8115a7 commit f46da0d
Show file tree
Hide file tree
Showing 16 changed files with 240 additions and 7 deletions.
42 changes: 42 additions & 0 deletions doc/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,48 @@ This is a comma-separated list of extra libraries to install file tracking on.
See the [file tracking](file_tracking.md) documentation for more details.


### Environment variables

Environment variables to set can be specified using the multi-line option
``environment``. Each line represents one environment variable in the format
``name = value``:

```INI
[pgfutils]
environment =
name1 = value1
name2 = value2
```

All names and values are processed and set as strings; any leading or trailing
spaces around the names or values will be stripped. Existing environment
variables of the same name will be overwritten. This means that if you specify
the same variable multiple times the last value will be used. For example, the
configuration

```INI
[pgfutils]
environment =
name1 = value1
name2 = value2
name1 = value3
```

will result in ``name1`` being set to ``value3``. The variables are set during
the call to ``setup_figure()``, so any libraries that read the environment
variables must be imported after this call.

Note that the ``PGFUTILS_TRACK_FILES`` variable described in the [file tracking
documentation](file_tracking.md) can be configured through this option, for
example to output tracked files to stdout:

```INI
[pgfutils]
environment =
PGFUTILS_TRACK_FILES = 1
```


Path settings
-------------

Expand Down
7 changes: 7 additions & 0 deletions extras/pgfutils.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,13 @@ preamble_substitute = false
# Extra library-specific file trackers to install.
extra_tracking =

# Environment variables to set. This should be a multi-line value; place one or
# more spaces between each subsequenct line (these spaces will be removed when
# parsing the configuration). Each line should be in the format name = value,
# with the value being read as a string, and leading and trailing spaces being
# removed from both the name and the value.
environment =



# Path setup.
Expand Down
30 changes: 23 additions & 7 deletions pgfutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"""

__version__ = "1.4.0"
__version__ = "1.5.0"

# We don't import Matplotlib here as this brings in NumPy. In turn, NumPy
# caches a reference to the io.open() method as part of its data loading
Expand Down Expand Up @@ -410,6 +410,7 @@ def _config_reset():
'figure_background': '',
'axes_background': 'white',
'extra_tracking': '',
'environment': '',
},

'paths': {
Expand Down Expand Up @@ -705,24 +706,39 @@ def setup_figure(width=1.0, height=1.0, columns=None, margin=False,
"""
global _config, _interactive

# Need to install our file trackers (if desired)
# before we import Matplotlib.
if 'PGFUTILS_TRACK_FILES' in os.environ:
_install_standard_file_trackers()

# Reset the configuration.
_config_reset()

# Load configuration from a local file if one exists.
if os.path.exists('pgfutils.cfg'):
_config.read('pgfutils.cfg')
_file_tracker.filenames.add(("r", "pgfutils.cfg"))

# And anything given in the function call.
if kwargs:
_config.read_kwargs(**kwargs)

# Now we can add any extra trackers specified in the config.
# Set environment variables specified in the configuration.
for line in _config['pgfutils']['environment'].splitlines():
line = line.strip()
if not line:
continue

# Check the variables are formatted correctly.
if '=' not in line:
raise ValueError(
"Environment variables should be in the form NAME=VALUE. "
"The line '{}' does not match this.".format(line)
)

# And set them.
key, value = line.split("=", 1)
os.environ[key.strip()] = value.strip()

# Install file trackers if desired. This must be done before anything which
# imports Matplotlib.
if 'PGFUTILS_TRACK_FILES' in os.environ:
_install_standard_file_trackers()
extra = _config['pgfutils']['extra_tracking'].strip()
if extra:
_install_extra_file_trackers(extra.split(","))
Expand Down
14 changes: 14 additions & 0 deletions tests/sources/environment/check_set/basic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from pgfutils import setup_figure, save
setup_figure()

import os

name1 = os.environ.get("name1", "not set")
name2 = os.environ.get("name2", "not set")

if name1 != "value1":
raise ValueError("Incorrect value ({}) for environment variable name1".format(name1))
if name2 != "value2":
raise ValueError("Incorrect value ({}) for environment variable name2".format(name2))

save()
17 changes: 17 additions & 0 deletions tests/sources/environment/check_set/override.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import os
os.environ["name1"] = "original value"

from pgfutils import setup_figure, save
setup_figure()

import os

name1 = os.environ.get("name1", "not set")
name2 = os.environ.get("name2", "not set")

if name1 != "value1":
raise ValueError("Incorrect value ({}) for environment variable name1".format(name1))
if name2 != "value2":
raise ValueError("Incorrect value ({}) for environment variable name2".format(name2))

save()
4 changes: 4 additions & 0 deletions tests/sources/environment/check_set/pgfutils.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[pgfutils]
environment=
name1=value1
name2 = value2
3 changes: 3 additions & 0 deletions tests/sources/environment/invalid/basic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from pgfutils import setup_figure, save
setup_figure()
save()
4 changes: 4 additions & 0 deletions tests/sources/environment/invalid/pgfutils.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[pgfutils]
environment=
line1=ok
line2 should fail
14 changes: 14 additions & 0 deletions tests/sources/environment/repeated/basic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from pgfutils import setup_figure, save
setup_figure()

import os

name1 = os.environ.get("name1", "not set")
name2 = os.environ.get("name2", "not set")

if name1 != "value3":
raise ValueError("Incorrect value ({}) for environment variable name1".format(name1))
if name2 != "value2":
raise ValueError("Incorrect value ({}) for environment variable name2".format(name2))

save()
5 changes: 5 additions & 0 deletions tests/sources/environment/repeated/pgfutils.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[pgfutils]
environment=
name1=value1
name2 = value2
name1=value3
20 changes: 20 additions & 0 deletions tests/sources/tracking/config_enabled/config_enabled.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from pgfutils import setup_figure, add_dependencies, save
setup_figure(width=1, height=1)

import numpy as np
from matplotlib import pyplot as plt
import os.path

noise = np.load('noise.npy')
plt.imshow(noise)
plt.colorbar()

data = np.loadtxt('scatter.csv', delimiter=',', dtype=np.int)

x = data[:, :3]
y = data[:, 3:]

plt.scatter(x, y)

add_dependencies("extra.file")
save()
Binary file added tests/sources/tracking/config_enabled/noise.npy
Binary file not shown.
3 changes: 3 additions & 0 deletions tests/sources/tracking/config_enabled/pgfutils.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[pgfutils]
environment =
PGFUTILS_TRACK_FILES = 1
30 changes: 30 additions & 0 deletions tests/sources/tracking/config_enabled/scatter.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
-41, 8, 40, 63, 11, -20
198, -4, -173, -19, -107, -96
-127, -137, -19, -49, -65, 79
302, 116, -23, -22, 23, -65
-97, 138, -85, -13, 10, -75
-167, 82, 34, 41, 31, -10
73, -71, 92, 59, 55, 21
-18, 268, 11, 101, -57, -1
101, -41, -58, -34, -63, -19
2, -80, -146, 31, 18, 65
54, -3, 23, 45, -5, -36
63, 76, 199, -3, -21, 58
-185, -7, -32, -58, -20, -30
100, 91, 53, 29, -105, 16
-30, 37, 281, 15, 34, -41
-146, -204, -37, 12, 9, -77
22, 78, -34, -2, 68, -100
-97, 14, -9, -42, 90, -36
-5, 213, -73, -14, -15, -11
51, 2, -102, 26, 23, -30
-13, -30, -242, -30, -27, -45
-5, -18, 19, -78, 129, 7
-84, -76, -92, -34, 10, -7
72, 20, -35, -49, -8, -52
27, -5, 102, 0, 3, -66
128, 93, -121, -28, -15, 21
-77, 11, -150, -15, -18, 72
-53, -7, -137, 17, 41, 37
98, -46, 224, -20, -43, 0
-158, -15, -98, -21, 12, 26
34 changes: 34 additions & 0 deletions tests/test_environment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import os.path
from .utils import build_figure, clean_dir
import pytest

srcdir = os.path.join(os.path.normpath(os.path.dirname(__file__)), "sources", "environment")


def test_environment_set():
"""Check environment variables can be set..."""
res = build_figure(os.path.join(srcdir, "check_set"), "basic.py")
assert res.returncode == 0, "Environment variables not set correctly."
clean_dir(srcdir)


def test_environment_override():
"""Check environment variables can override existing ones..."""
res = build_figure(os.path.join(srcdir, "check_set"), "override.py")
assert res.returncode == 0, "Environment variables not set correctly."
clean_dir(srcdir)


def test_environment_repeated():
"""Check the last value of repeated environment variables is used..."""
res = build_figure(os.path.join(srcdir, "repeated"), "basic.py")
assert res.returncode == 0, "Environment variables not set correctly."
clean_dir(srcdir)


def test_environment_invalid():
"""Check invalid environment variable in configuration is rejected..."""
res = build_figure(os.path.join(srcdir, "invalid"), "basic.py")
assert res.returncode != 0, "Configuration not rejected."
assert "Environment variables should be in the form" in res.stderr, "Incorrect message."
clean_dir(srcdir)
20 changes: 20 additions & 0 deletions tests/test_tracking.py
Original file line number Diff line number Diff line change
Expand Up @@ -534,3 +534,23 @@ def test_import_tracking_extra_imports(self):
}
assert actual == expected
self.cleanup()


def test_track_enabled_config(self):
"""File tracking can be enabled through configured environment variables..."""
# Run the script.
res = build_figure(os.path.join(dirname, "config_enabled"), 'config_enabled.py')
assert res.returncode == 0

# Check the results are as expected.
expected = {
'r:pgfutils.cfg',
'r:noise.npy',
'r:scatter.csv',
'r:extra.file',
'w:config_enabled-img0.png',
'w:config_enabled-img1.png',
}
actual = set(res.stdout.strip().splitlines())
assert actual == expected
self.cleanup()

0 comments on commit f46da0d

Please sign in to comment.