Configure tephpy From a File#

A house style is the same handful of lines at the top of every script — a colour scheme, a preferred extent, a cursor readout. A configuration file gives them a home on disk, and every later import tephpy picks them up.

Generate the Template#

$ tephpy config generate
Wrote /home/you/.config/tephpy/tephpyrc.yaml

The template carries every option tephpy has, each commented out and showing the default in force, with a line of prose above it. Nothing in it is active until you uncomment something, so a freshly generated file changes nothing. Every option is also listed in Configuration Options, with its type, its default, and the longer prose the template has no room for.

Uncomment what you want and edit the value:

isotherms:
  # Matplotlib colour for the lines and their labels.
  color: purple
  # Line width in points.
  # linewidth: 0.5

Where tephpy Looks#

The first file found wins; there is no merging across the three:

  1. the file named by $TEPHPYRC

  2. tephpyrc.yaml in the current working directory

  3. tephpyrc.yaml in your user configuration directory

tephpy config path reports the whole search, not just the winner, which is what you want when a file appears to be ignored:

$ tephpy config path
/home/you/work/tephpyrc.yaml  [in force]
/home/you/.config/tephpy/tephpyrc.yaml  [shadowed]

Being found is not the same as being used. A file tephpy could not read is marked [rejected], and the defaults stay in force:

$ tephpy config path
/home/you/work/tephpyrc.yaml  [rejected]
/home/you/.config/tephpy/tephpyrc.yaml  [absent]

/home/you/work/tephpyrc.yaml was rejected; tephpy is using its defaults. The warning it raised on import says why.

A directory that happens to be named tephpyrc.yaml is reported as [not a file], and passed over.

Setting $TEPHPYRC to a file that does not exist is never a fallthrough to the next candidate — naming a file explicitly and not having it is a mistake worth reporting. tephpy config path fails outright; import tephpy warns and falls back to the defaults, so watch for that warning if a script’s styling is not what you expect.

Quote Hex Colours#

YAML reads an unquoted # as the start of a comment, so

isotherms:
  color: #b0b0b0

sets color to null, not to grey. Quote it:

isotherms:
  color: '#b0b0b0'

tephpy warns about a null value rather than passing it on, and names the missing quotes as the likely cause. Named colours such as purple and tab:blue need no quoting.

When the File Takes Effect#

The file is read once, at import tephpy, and an isopleth family reads tephpy.config when it is created. A configuration file therefore sets the starting values for axes you create afterwards; it does not restyle axes that already exist. This is the rcParams behaviour matplotlib users already expect.

After an Upgrade#

A file written for one release of tephpy stays usable in the next, but the two halves of that promise are not the same size. An option tephpy has since renamed or dropped warns and is skipped — the rest of the file still applies. An unknown section, though, is rejected outright, and rejecting a section means rejecting the whole file: import tephpy warns and falls back to the defaults entirely, and tephpy.config.load() raises and leaves your configuration as it found it. Nothing under that section is quietly lost, because nothing in the file is applied at all.

So if a styling you have relied on for months disappears after an upgrade, read the warning: one obsolete section name is enough to switch off every other line in the file.

A value of the wrong type is treated the same way as an option tephpy no longer recognises: linewidth: thick warns, that one option is skipped and keeps its default, and every other line in the file still applies. The warning names the file, the option, what was expected and what it found:

tephpyrc.yaml: ignoring isotherms.linewidth, which expects a number, not the string 'thick'

Two details of YAML are worth knowing before you read one of these. linewidth: 1 is fine — an integer is accepted wherever a number is wanted. But linewidth: true is not a number at all, and neither are yes, no, on and off, which YAML also reads as true or false. Quote them if you meant the words.

A value of the right type can still be refused. color: notacolour is a string and interval: 0 is a number, and neither is something tephpy can draw; both warn and are skipped exactly as linewidth: thick is, and the warning says what the option can accept:

tephpyrc.yaml: ignoring isotherms.color, which expects a colour matplotlib knows, not the string 'notacolour'
tephpyrc.yaml: ignoring isobars.interval, which expects a positive, finite number, not the number 0.0

Where the set of legal values is closed, the warning lists it, because your next move is to pick from it. Where it is open — no message can enumerate the colours matplotlib knows — it is described instead. And color: b0b0b0, the mirror image of the # trap above, is told what it is probably missing:

tephpyrc.yaml: ignoring isotherms.color, which expects a colour matplotlib knows, not the string 'b0b0b0'; did you mean '#b0b0b0'?

One of these refusals will catch you out if you have relied on it. linewidth: 0 is a working matplotlib instruction — a line of zero width is a line you cannot see — but tephpy refuses it, because a line width is expected to be a positive number and because hiding a family has an option of its own:

isotherms:
  visible: false

That is the one to reach for. It says what you mean, it reads that way to whoever opens the file next, and it costs you nothing: visible is available on every isopleth family.

An option is skipped whole. emphasis holds a mapping of members to styles, so one bad member costs you the whole emphasis option, not just that member — the good members go back to being drawn like every other member of the family. This is deliberate: told that emphasis was ignored you can read your own file and see what you lost, where told it was partly applied you could not tell what was in force.

These warnings arrive once, as the file is read, and no filter of yours can turn them off: your own code has not started running yet, and the auto-load puts tephpy’s configuration warnings in front of every filter you set, so they always reach you. They are shown rather than raised, so a typo cannot take the import down with it either.

Loading the file again from Python warns again — an unknown section raises there instead — and those warnings are ordinary ones. Once you have read one and decided it is safe to live with — an unknown option you are not using yet, say — filter it by category rather than by module: the warning is attributed to your own code, not to tephpy, so a filter keyed on the module never matches it.

import warnings

import tephpy

warnings.filterwarnings("ignore", category=tephpy.exceptions.TephpyConfigWarning)
tephpy.config.load()

Saving From Python#

tephpy.config.save() writes the options you actually set, and nothing else:

import tephpy

tephpy.config.isotherms.color = "purple"
tephpy.config.save()

It is a data dump: comments and key order in an existing file are not preserved, because PyYAML cannot round-trip them. tephpy config generate is the command that produces the annotated file — reach for tephpy.config.save() to capture a configuration you arrived at interactively, not to edit one you already have.