wenv Documentation Release 0.2.1

Sebastian M. Ernst

Jul 10, 2020

Contents

1 Introduction 3 1.1 Synopsis...... 3 1.2 Motivation...... 3 1.3 Implementation...... 4 1.4 Use cases...... 4

2 Installation 5 2.1 Getting Wine ...... 5 2.2 Getting wenv ...... 5 2.3 Possible problem: OSError: [WinError 6] Invalid handle ...... 6 2.4 Installing wenv in development mode...... 6

3 Examples 7

4 Configuration 9 4.1 Configuration files...... 9 4.2 Configuration environment variables...... 9 4.3 Configurable parameters...... 10

5 Usage 13 5.1 : wenv init ...... 13 5.2 Command: wenv clean ...... 13 5.3 Command: wenv help ...... 13 5.4 Command: wenv python ...... 13 5.5 Command: wenv pip ...... 14 5.6 Command: wenv init_coverage ...... 14

6 API: class Env 15 6.1 Constructor: Env(**kwargs) ...... 15 6.2 Method: ensure() ...... 15 6.3 Method: wine_47766_workaround() ...... 15 6.4 Method: setup_wineprefix(overwrite = False) ...... 16 6.5 Method: setup_pythonprefix(overwrite = False) ...... 16 6.6 Method: setup_pip() ...... 16 6.7 Method: install_package(name, update = False) ...... 16 6.8 Method: uninstall_package(name) ...... 16 6.9 Method: list_packages() ...... 16

i 6.10 Method: () ...... 16 6.11 Method: cli() ...... 16 6.12 Method: uninstall() ...... 16 6.13 Method: setup_coverage_activate() ...... 17

7 Security 19

8 Bugs 21 8.1 How to bisect issues...... 21

9 FAQ 23 9.1 Why?...... 23 9.2 What are actual use cases for this project?...... 23 9.3 How does it work?...... 23 9.4 Is it secure?...... 23

10 Indices and tables 25

Index 27

ii wenv Documentation, Release 0.2.1

Running Python on Wine. wenv is a Python package (currently in development status 4/beta). It allows to run Python on top of Wine on , MacOS or BSD. It handles required plumbing related to making Python and a number of Python modules work on Wine. wenv creates isolated virtual environments which can be transparently used from a command line and which seamlessly integrate into Unix Python virtual environments.

Contents 1 wenv Documentation, Release 0.2.1

2 Contents CHAPTER 1

Introduction

1.1 Synopsis wenv is a Python package (currently in development status 4/beta). It allows to run Python on top of Wine on Linux, MacOS or BSD. It handles required plumbing related to making Python and a number of Python modules work on Wine. wenv creates isolated virtual environments which can be transparently used from a Unix command line and which seamlessly integrate into Unix Python virtual environments.

1.2 Motivation wenv was derived from the Python package zugbruecke. zugbruecke allows to call routines in Windows DLLs from Python code running on Unices / Unix-like systems such as Linux, MacOS or BSD. wenv’s code started out as infras- tructure for zugbruecke. Eventually, it became too complex on its own and - the same - began to enable new and interesting use cases beyond the scope of zugbruecke. Technically, the basic problem is how to (and run) just any version or distribution of Python on Wine. The in- stallers of most Python distributions including Anaconda and even CPython itself tend to be broken on most versions of Wine (“garbage” in Wine jargon). For a while, ActiveState’s ActivePython was the only “easy” way of directly installing Python on Wine, but even this was (and still is) extremely unreliable. The commonly recommended workaround is to install Python directly on Windows and copy the resulting installation directory tree over to Unix/Wine. First, this is not an option for everybody as it requires a Windows installation. Second, it is also notoriously unreliable. While researching options for developing zugbruecke, CPython’s embeddable package for Windows showed up on the radar. It is a simple ZIP-file without any installer. By merely unpacking it, one can run Python without an issue. With some manual tweaking and tuning of both the unpacked folder and Wine, it becomes possible to pip work and install just about anything on top. wenv essentially takes care of the entire process automatically.

3 wenv Documentation, Release 0.2.1

1.3 Implementation wenv has two roles. First, it downloads, installs and configures both CPython and pip. The process is based on CPython’s embeddable package distribution for Windows. Second, wenv provides a thin launcher for staring Python (or just any Python application) on Wine. The installer and launcher themselves are also written in Python and run on any Unix-version of Python. The launcher sets the stage in Unix Python before using an exec syscall to replace itself with Windows Python.

1.4 Use cases

• Running Python apps & scripts written for Windows on Unix. • Running critical portions of Python apps depending on Windows on Unix - while the remaining uncritical por- tions of those apps can directly run on Unix. Inter-process communication can bridge the gap. • Testing the Windows compatibility of Python apps directly on Unix. • Accessing proprietary DLLs through ctypes, cffi, swig, sip, f2py and friends. Also see the zugbruecke project. • Running a Windows version of Python as a Jupyter kernel next to a Unix version, see the wenv-kernel project.

4 Chapter 1. Introduction CHAPTER 2

Installation

2.1 Getting Wine

For using wenv, you need to install Wine first. Depending on your platform, there are different ways of doing that. • Installation instructions for various Linux distributions • Installation instructions for Mac OS X • Installation instructions for FreeBSD Currently, Wine >= 4.x is supported (tested). If you are limited to an older version of Wine such as 2.x or 3.x, you have one option: Try to set the pythonversion configuration parameter to 3.5.4.

2.2 Getting wenv

The latest stable release version can be installed with pip:

pip install wenv

If you are interested in testing the latest work from the development branch, you can try it like this:

pip install git+https://github.com/pleiszenburg/wenv.git@develop

After installing the package with pip, you must initialize the “Wine Python environment” by running wenv init. If you are relying on wenv, please notice that it uses semantic versioning. Breaking changes are indicated by increasing the first version number, the major version. Going for example from 0.0.x to 1.0.0 or going from 0.1.y to 1.0.0 therefore indicates a breaking change.

5 wenv Documentation, Release 0.2.1

2.3 Possible problem: OSError: [WinError 6] Invalid handle

On older versions of Linux such as Ubuntu 14.04 Trusty Tahr (released 2014), you may observe errors when run- ning wenv python. Most commonly, they will present themselves as OSError: [WinError 6] Invalid handle: 'z:\\... triggered by calling os.listdir on a symbolic (“symlink”) to a folder. A clean solution is to upgrade to a younger version of Linux. E.g. Ubuntu 16.04 alias Xenial Xerus (released 2016) is known to work.

2.4 Installing wenv in development mode

If you are interested in contributing to wenv, you might want to install it in development mode. You can find the latest instructions on how to do this in the CONTRIBUTING file of this project on Github.

6 Chapter 2. Installation CHAPTER 3

Examples

Fire up a shell and try the following:

(env) user@comp:~> Linux (env) user@comp:~> python-m platform Linux (env) user@comp:~> wenv python-m platform Windows wenv pip works just like one would expect. Have a look at the output of wenv help for commands and in- formation. For use as a shebang, wenv python has an alias: One can #!/usr/bin/env _wenv_python at the top of scripts. wenv python can also be used as a Jupyter kernel, side-by-side with a Unix-version of Python. Have a look at the wenv-kernel project.

7 wenv Documentation, Release 0.2.1

8 Chapter 3. Examples CHAPTER 4

Configuration

wenv can configure itself automatically or can be configured with files and environment variables manually.

4.1 Configuration files wenv uses JSON configuration files named .wenv.json. They are expected in the following locations (in that order): • The current working directory • A directory specified in the WENV • The user profile folder (~ / /home/{username}) • /etc There is one optional addition to the above rules: The path specified in the WENV environment variable can directly point to a configuration file. I.e. the WENV environment variable can also contain a path similar to /path/to/ some/.json. Configuration options are being looked for location after location in the above listed places. If, after checking for configuration files in all those locations, there are still configuration options left undefined, wenv will fill them with its defaults. A configuration option found in a location higher in the list will always be given priority over a the same configuration option with different content found in a location further down the list.

4.2 Configuration environment variables

Independently of the WENV environment variable, all configurable parameters of wenv can directly be overridden with environment variables. All values coming from configuration files will then be ignored for this particular parameter. Take the name of any configurable parameter, convert it to upper case and prefix it with WENV. Example: The arch parameter can be overridden by declaring the WENV_ARCH environment variable.

9 wenv Documentation, Release 0.2.1

4.3 Configurable parameters

4.3.1 arch (str)

Defines the architecture of Wine & Wine Python. It can be set to win32 or win64. Default is win32, even on 64-bit systems. It appears to be a more stable configuration.

4.3.2 pythonversion (str)

The pythonversion parameter tells wenv what version of the Windows CPython it should use. By default, it is set to 3.7.4. Please note that 3.4 and earlier are not supported. In the opposite direction, at the time of writing, 3.6 (and later) do require Wine 4.0 or later. If you are forced to use Wine 2.0 or 3.0, you may try to set this parameter to 3.5.4. Note that you can only specify versions for which an “Windows embeddable zip file” is available, see python.org. Release candidates, alpha and beta versions can be accessed in the following form: 3.7.0.rc1. 3.7.0.a1 or 3.7.0.b1.

4.3.3 prefix (str)

If wenv is installed into a Python virtual environment or system-wide, this option’s defaults is sys.prefix. If wenv is installed user-wide, its default is site.USER_BASE (typically ~/.local).

4.3.4 wineprefix (str)

This parameter can be used to point to a custom WINEPREFIX outside of the shared folder of the current Unix Python’s prefix. By default, it is set to {prefix}/share/wenv/{arch}

4.3.5 pythonprefix (str)

This parameter can be used to specify a custom location for the Wine Python environment outside of wineprefix if required. By default, it is set to {wineprefix}/drive_c/python-{pythonversion}/

4.3.6 winedebug (str)

Wine allows to control the level of debugging output through the WINEDEBUG environment variable. wenv will by default disable all output by setting it to -all. A custom value can be specified in the winedebug configuration parameter. See the Wine documentation for details.

4.3.7 offline (str/bool)

If set to true, wenv init will try to create a Wine Python environment from a locally cached Windows Python in- terpreter, a locally cached get-pip.py script as well as locally cached wheels for pip, wheel and setuptools. An exception is raised if any of the required components is not found in the local cache. For API usage, a boolean is expected. For command line usage / environment variables, equal to TRUE/True/true or FALSE/False/false are expected. By default, this option is set to false. wenv cache can be used, while online, to initialize the cache and download all required items.

10 Chapter 4. Configuration wenv Documentation, Release 0.2.1

4.3.8 cache (str)

Path to the local cache directory. By default, it is set to {prefix}/share/wenv/cache.

4.3.9 packages (str)

Path to the local package cache directory. By default, it is set to {cache}/packages. This cache is used for offline initialization of wenv only, see offline option. It is not a general offline cache for wenv pip.

4.3.10 wineinstallprefix (str)

Path to custom Wine installation. Binaries are expected in {wineinstallprefix}/bin, libraries in {wineinstallprefix}/lib and {wineinstallprefix}/lib64. If set to an empty string or None, its value is ignored.

4.3. Configurable parameters 11 wenv Documentation, Release 0.2.1

12 Chapter 4. Configuration CHAPTER 5

Usage

This chapter covers the main modes of usage of wenv.

5.1 Command: wenv init

If you have not initialized wenv before, you must initialize the Wine Python environment first by running wenv init. This will configure Wine, install a Windows version of Python and fetch pip.

5.2 Command: wenv clean

This command is useful if you want to remove your current Wine Python environment and all related data (including the relevant Wine prefix). wenv’s configuration is left untouched.

5.3 Command: wenv help

This command provides help and lists all currently available sub-commands (such as init or python).

5.4 Command: wenv python

This command behaves just like the regular python command in a , except that it fires up a Windows Python interpreter on top of Wine. It works with all regular parameters and switches, accepts pipes and can be launched in interactive mode. You can also use it for creating executable Python scripts by adding the following at their top: #!/usr/bin/env _wenv_python. Do not forget +x your_script.py. Notice that there is a difference between the more general wenv python command and its alias _wenv_python, which is meant to be used only with a shebang.

13 wenv Documentation, Release 0.2.1

5.5 Command: wenv pip

This command behaves just like the regular pip command on Unix, except that it attempts to install Python packages into a dedicated Python environment under Wine. So if you need any specific packages in wenv python, this is how you install them. Most packages written in pure Python should work just fine. Anything requiring a compiler during installation does not work. Packages / wheels with pre-compiled binary components in them might work, although this is largely untested territory. Feel free to report any (positive or negative) results.

5.6 Command: wenv init_coverage

This command enables coverage analysis across the entire Wine Python environment. The coverage package must have been installed before running this command.

14 Chapter 5. Usage CHAPTER 6

API: class Env

wenv can not only be used from the command line. It also offers an API through its Env class.

6.1 Constructor: Env(**kwargs)

The constructor expects an arbitrary number of keyword arguments matching valid configuration options. In previous releases, the constructor expected one optional argument, parameter. It should either be None or a dictionary. In the latter case, the dictionary may contain all valid configuration options. parameter can still be used but is deprecated.

6.2 Method: ensure()

Equivalent of wenv init. Intended to be used by 3rd-party packages which want to “ensure” that wenv has been initialized (i.e. Python and pip are present and working). ensure() calls wine_47766_workaround() inter- nally.

6.3 Method: wine_47766_workaround()

Due to Wine’s bug #47766, Wine crashes if any folder in the path to pythonprefix is hidden Unix-style (i.e. prefixed with a dot / .). This workaround creates a symlink directly pointing to pythonprefix into /tmp, which is (more or less) guaranteed to be visible. It is then used instead of the actual pythonprefix. Run setup_wineprefix and setup_pythonprefix before calling wine_47766_workaround. Any sub- sequent action such as installing or using pip must happen after calling wine_47766_workaround.

15 wenv Documentation, Release 0.2.1

6.4 Method: setup_wineprefix(overwrite = False)

Part of the initialization process, but can be triggered on its own if required. It creates a Wine prefix according to wenv’s configuration. If overwrite is set to True, a pre-existing Wine prefix is removed before a new one is created.

6.5 Method: setup_pythonprefix(overwrite = False)

Part of the initialization process, but can be triggered on its own if required. It installs the CPython interpreter into the Python prefix. If overwrite is set to True, a pre-existing Python prefix is removed before a new one is created.

6.6 Method: setup_pip()

Part of the initialization process, but can be triggered on its own if required. It installs pip, assuming that both the wineprefix and pythonprefix are already present.

6.7 Method: install_package(name, update = False)

Thin wrapper around wenv pip install [-U] {name}.

6.8 Method: uninstall_package(name)

Thin wrapper around wenv pip uninstall -y {name}.

6.9 Method: list_packages()

Thin wrapper around wenv pip list --format json. Returns a list of dictionaries.

6.10 Method: shebang()

Shebang entry point.

6.11 Method: cli()

Command line interface entry point.

6.12 Method: uninstall()

Equivalent of wenv clear. Removes the current Wine Python environment.

16 Chapter 6. API: class Env wenv Documentation, Release 0.2.1

6.13 Method: setup_coverage_activate()

Equivalent of wenv init_coverage. Activates coverage analysis throughout the Wine Python environment.

6.13. Method: setup_coverage_activate() 17 wenv Documentation, Release 0.2.1

18 Chapter 6. API: class Env CHAPTER 7

Security

wenv should be used with caution. • DO NOT run untrusted code (or DLLs)! • DO NOT run it with root / super users privileges! The following problems also directly apply to wenv: • Wine can in fact theoretically run (some) Windows malware. • NEVER run Wine as root! See FAQ at WineHQ for details. wenv does not actively prohibit its use with root privileges.

19 wenv Documentation, Release 0.2.1

20 Chapter 7. Security CHAPTER 8

Bugs

Please report bugs in wenv in wenv’s GitHub issue tracker. Please report bugs in Wine in the WineHQ Bug Tracking System. Make sure to separate between wenv-related and Wine-related bugs.

8.1 How to bisect issues

You can drop a configuration file named .wenv.json into your current working directory or your home folder (/home/username) and add configuration parameters to it, for example:

{"pythonversion":"3.8.0","winedebug":"warn+all"}

If you are running into problems, the best approach usually is to try older versions of Python such as 3.7, 3.6 or 3.5 first. Newer versions of Python use younger Windows APIs, which tend to cause more issues on Wine. If you change your Python version, you must initialize the new environment with wenv init. If you suspect that Wine is at fault, you can access Wine debug channels for more information by setting the winedebug option. See the Wine documentation for details. For more wenv configuration options check the chapter on configuration. As an alternative approach, you can also investigate what happens if you run your code directly on Windows.

21 wenv Documentation, Release 0.2.1

22 Chapter 8. Bugs CHAPTER 9

FAQ

9.1 Why?

Good question. Have a look at the motivation section in the introduction.

9.2 What are actual use cases for this project?

Read the section on use cases in the introduction.

9.3 How does it work?

Have a closer look at the section describing the implementation in the introduction.

9.4 Is it secure?

Yes - limitations apply, though. See chapter on security. Interested in contributing?

23 wenv Documentation, Release 0.2.1

24 Chapter 9. FAQ CHAPTER 10

Indices and tables

• genindex • search

25 wenv Documentation, Release 0.2.1

26 Chapter 10. Indices and tables Index

A installation, wine,4 arch M architecture, python,7 architecture, wine,7 macos architecture installation, wine,4 python arch,7 module wine arch,7 wenv._core.config,7 wenv._core.env, 11, 14 B motivation,1 bisect bug issue, 19 P bsd pip,6 installation, wine,4 install,4 bug privileges issue bisect, 19 root super user, 17 issue report, 19 python,6 arch architecture,7 E environment, wine, 11, 14 env init, 14 version,7 env pip, 14 env pytest, 14 R env python, 14 report environment bug issue, 19 wine python, 11, 14 root super user privileges, 17 I implementation,1 S init,6 shebang,6 install super user pip,4 privileges, root, 17 installation wine bsd,4 U wine linux,4 use cases,1 wine macos,4 issue V bisect, bug, 19 version report, bug, 19 python,7 L W linux wenv init, 11

27 wenv Documentation, Release 0.2.1 wenv pip, 11 wenv pytest, 11 wenv python, 11 wenv._core.config module,7 wenv._core.env module, 11, 14 wine, 19 arch architecture,7 bsd installation,4 linux installation,4 macos installation,4 python environment, 11, 14

28 Index