from fastcore.test import test_eq, ExceptionExpected
import tempfileconfig
Before we can use pystata, we need to find the local Stata path (i.e., find_path) and then add pystata to sys.path (i.e., set_pystata_path) so it can be imported.
The get_config function handles nbstata configuration, more broadly.
pystata configuration
Auto-detect Stata directory and edition
find_dir_edition
def find_dir_edition(
stata_path:NoneType=None
):
test_eq(find_dir_edition('C:/Program Files/Stata17/StataMP-64.exe'), ('C:/Program Files/Stata17', "mp"))
with ExceptionExpected(OSError):
find_dir_edition('')find_edition
def find_edition(
stata_dir
):
if _find_path('') == '': test_eq(find_edition(''), "be")
find_edition('C:\\Program Files\\Stata18')'mp'
from nbstata.misc_utils import Timerwith Timer():
print(find_dir_edition())('C:\\Program Files\\Stata19', 'mp')
Elapsed time: 0.0004 seconds
Initialize pystata
set_pystata_path
def set_pystata_path(
stata_dir:NoneType=None
):
with Timer():
set_pystata_path()
import pystataElapsed time: 0.0031 seconds
with ExceptionExpected(): import sfilaunch_stata
def launch_stata(
stata_dir:NoneType=None, edition:NoneType=None, splash:bool=True
):
We modify stata_setup to make splash screen optional
with Timer():
launch_stata(splash=False)
pystata.config.status() System information
Python version 3.11.10
Stata version Stata 19.0 (MP)
Stata library path C:\Program Files\Stata19\mp-64.dll
Stata initialized True
sfi initialized True
Settings
graphic display True
graphic size width = default, height = default
graphic format svg
command display default
autocompletion on
streaming output on
Elapsed time: 0.5607 seconds
sfi can only be imported after Stata is launched:
import sfiConfigure pystata graph output
https://www.stata.com/python/pystata18/config.html#pystata.config.set_graph_format
set_graph_format
def set_graph_format(
gformat
):
with Timer():
set_graph_format('png')
pystata.config.status()Elapsed time: 0.0000 seconds
System information
Python version 3.11.10
Stata version Stata 19.0 (MP)
Stata library path C:\Program Files\Stata19\mp-64.dll
Stata initialized True
sfi initialized True
Settings
graphic display True
graphic size width = default, height = default
graphic format png
command display default
autocompletion on
streaming output on
_set_graph_size('2in', '4')
pystata.config.status()
_set_graph_size('default', 'default') System information
Python version 3.11.10
Stata version Stata 19.0 (MP)
Stata library path C:\Program Files\Stata19\mp-64.dll
Stata initialized True
sfi initialized True
Settings
graphic display True
graphic size width = 2.0in, height = 4in
graphic format png
command display default
autocompletion on
streaming output on
nbstata configuration
Config file location and parsing
The XDG config path is now the default, but the old path is supported for backwards compatibility. See Issue #33.
old_user_config_path
def old_user_config_path(
):
xdg_user_config_path
def xdg_user_config_path(
):
xdg_user_config_path()Path('C:/Users/tjhuegerich/.config/nbstata/nbstata.conf')
old_user_config_path()Path('C:/Users/tjhuegerich/.nbstata.conf')
configparser is used to parse the config file, after which quotes are stripped from all values.
test_config_contents = """\
[nbstata]
stata_dir = 'C:\Program Files\Stata19'
edition = mp
graph_width = default
graph_height = default
echo = None
browse_auto_height = False
"""
with tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=False) as f:
f.write(test_config_contents)
f.flush()
test_eq(_get_settings_from_config_file(f.name),
{'stata_dir': 'C:\\Program Files\\Stata19',
'edition': 'mp',
'graph_width': 'default',
'graph_height': 'default',
'echo': 'None',
'browse_auto_height': 'False'}
)Config class
The Config class loads the configuration file, after which pystata may be initialized with Config.init_stata. Config then also handles configuration changes made by the %set magic (that is, StataMagics.magic_set).
The initial Config class definition is here, but additional methods are added via patch_to below.
Test config file parsing and loading
test_config_contents = "test content"
config = Config()
print(config.env)
with tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=False) as f:
f.write(test_config_contents)
f.flush()
config._update_env_from_config_file(Path(f.name)){'stata_dir': None, 'edition': None, 'splash': 'False', 'graph_format': 'png', 'graph_width': '5.5in', 'graph_height': '4in', 'echo': 'None', 'missing': '.', 'browse_auto_height': 'True'}
Configuration error in C:\Users\TJHUEG~1\AppData\Local\Temp\tmp08ob504d.txt:
File contains no section headers.
file: 'C:\\Users\\TJHUEG~1\\AppData\\Local\\Temp\\tmp08ob504d.txt', line: 1
'test content'
test_config_contents = """\
[nbstata]
stata_dir = C:\Program Files\Stata19
edition = mp
graph_width = default
graph_height = default
echo = None
browse_auto_height = False
"""
config = Config()
with tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=False) as f:
f.write(test_config_contents)
f.flush()
config._update_env_from_config_file(Path(f.name))
config.env{'stata_dir': 'C:\\Program Files\\Stata19',
'edition': 'mp',
'splash': 'False',
'graph_format': 'png',
'graph_width': 'default',
'graph_height': 'default',
'echo': 'None',
'missing': '.',
'browse_auto_height': 'False'}
The test below reads in the configuration file for the environment in which this notebook is being run:
config = Config()
config.process_config_file()
config.env{'stata_dir': 'C:\\Program Files\\Stata19',
'edition': 'mp',
'splash': 'False',
'graph_format': 'png',
'graph_width': 'default',
'graph_height': 'default',
'echo': 'None',
'missing': '.',
'browse_auto_height': 'False'}
Testing out error messages explaining invalid keys:
config.update({'splash': 'True'})%set error(s):
'splash' is only allowed in a configuration file.
config.update({'splash': 'True'}, init=True)config.update({'not_a_key': 'True'})%set error(s):
'not_a_key' is not a valid setting.
Applying graph size/format config settings
The configuration file is read in prior to loading Stata (since it can contain a path to the desired Stata executable). But checking the validity of graph size configuration settings uses Stata, so that can’t be done in the same step in which the configuration file is read in. Thus, the following workaround is used: hold the read-in graph size settings until they are actually applied, reverting to previous valid settings if they don’t work:
Config.set_graph_size
def set_graph_size(
init:bool=False
):
If the configuration file has invalid width/height, the error message says “Graph size not changed” even though, under the hood, the pystata graph size configuration is changing from “default” to definite measures. This behavior ensures that using the %set magic to change just one of the size values, width or height, always exhibits the behavior described in the nbstata user guide rather than the (maintained aspect ratio) behavior described in the pystata docs.
config.display_status()
config.set_graph_size(init=True)
config.display_status() System information
Python version 3.11.10
Stata version Stata 19.0 (MP)
Stata library path C:\Program Files\Stata19\mp-64.dll
Stata initialized True
sfi initialized True
Settings
graphic display True
graphic size width = default, height = default
graphic format png
command display default
autocompletion on
streaming output on
echo None
missing .
browse_auto_height False
config file path C:\Users\tjhuegerich\.config\nbstata\nbstata.conf
System information
Python version 3.11.10
Stata version Stata 19.0 (MP)
Stata library path C:\Program Files\Stata19\mp-64.dll
Stata initialized True
sfi initialized True
Settings
graphic display True
graphic size width = default, height = default
graphic format png
command display default
autocompletion on
streaming output on
echo None
missing .
browse_auto_height False
config file path C:\Users\tjhuegerich\.config\nbstata\nbstata.conf
config.update({'graph_width': '3'})
config.set_graph_size()graph size was (default, default), is now (3, default).
config.display_status()
config.env System information
Python version 3.11.10
Stata version Stata 19.0 (MP)
Stata library path C:\Program Files\Stata19\mp-64.dll
Stata initialized True
sfi initialized True
Settings
graphic display True
graphic size width = 3in, height = default
graphic format png
command display default
autocompletion on
streaming output on
echo None
missing .
browse_auto_height False
config file path C:\Users\tjhuegerich\.config\nbstata\nbstata.conf
{'stata_dir': 'C:\\Program Files\\Stata19',
'edition': 'mp',
'splash': 'True',
'graph_format': 'png',
'graph_width': '3',
'graph_height': 'default',
'echo': 'None',
'missing': '.',
'browse_auto_height': 'False'}
config.update({'graph_height': '-3'})
config.set_graph_size()
config.envConfiguration error: graph height is invalid. Graph size not changed.
{'stata_dir': 'C:\\Program Files\\Stata19',
'edition': 'mp',
'splash': 'True',
'graph_format': 'png',
'graph_width': '3',
'graph_height': 'default',
'echo': 'None',
'missing': '.',
'browse_auto_height': 'False'}
Config.update_graph_config
def update_graph_config(
init:bool=False
):
config.update_graph_config()Config.init_stata
def init_stata(
):