{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "8ebbd194-14bb-498e-932b-2daacf94a1f6",
   "metadata": {},
   "source": [
    "# Virtual Environment\n",
    "\n",
    "We want to create a project directory for your project and a Python virtual environment within that directory for managing Python and all installed package files."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```{contents}\n",
    ":local:\n",
    ":depth: 2\n",
    "```\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "13785857",
   "metadata": {},
   "source": [
    "## Creating Project Directory\n",
    "In general, when we create a project, it means we are creating a folder/directory. To use a project directory, we use the CLI of your OS. Since they are CLI rather than GUI, we need to use commands to achieve this. Although this can be done with a file manager (GUI), knowing how to use the CLI is a good skill set to have in the long run. The three shell commands that we use here are: `ls` (\"list storage\"), `cd` (\"change directory\"), and `mkdir` (\"make directory\"). \n",
    "\n",
    "For the purpose of this course, we want to create a `workspace` directory inside your user home directory, and a `dsm` directory inside the `workspace` directory. \n",
    "\n",
    "Note that macOS and Linux use forward slash for directory separator, while Windows use backward slash as separator but can also interpret forward slashes.  \n",
    "\n",
    "````{tab-set} \n",
    "```{tab-item} Windows\n",
    "\n",
    "We use `PowerShell` as our CLI here because the syntax is more friendly. \n",
    "\n",
    "```bash\n",
    "PS C:\\Users\\[user]> mkdir workspace\n",
    "    Directory: C:\\Users\\[user]\n",
    "Mode                 LastWriteTime         Length Name\n",
    "----                 -------------         ------ ----\n",
    "d-----         8/31/2025   3:14 AM                workspace\n",
    "\n",
    "PS C:\\Users\\[user]> cd workspace\n",
    "PS C:\\Users\\[user]\\workspace> mkdir dsm\n",
    "    Directory: C:\\Users\\[user]\\workspace\n",
    "Mode                 LastWriteTime         Length Name\n",
    "----                 -------------         ------ ----\n",
    "d-----         8/31/2025   3:14 AM                dsm\n",
    "\n",
    "PS C:\\Users\\[user]\\workspace> cd dsm\n",
    "PS C:\\Users\\[user]\\workspace\\dsm> \n",
    "```\n",
    "\n",
    "```{tab-item} macOS\n",
    "\n",
    "Use `Terminal.app` as CLI here for this task.\n",
    "\n",
    "```bash\n",
    "[user]@[host]ː~$ mkdir workspace\n",
    "[user]@[host]ː~$ cd workspace\n",
    "[user]@[host]ː~/workspace$ mkdir dsm\n",
    "[user]@[host]ː~/workspace$ cd dsm/\n",
    "[user]@[host]ː~/workspace/dsm$ \n",
    "```\n",
    "````\n",
    "\n",
    "After issuing the above commands, you will have a project directory (**dsm**) inside the workspace directory, and your current location is inside the **dsm** project directory. \n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "35a281b2",
   "metadata": {},
   "source": [
    "## Creating Virtual Environment\n",
    "\n",
    "In the **dsm** project directory, we will create a Python virtual environment for the project. This means that we will place all installed packages (dependencies) that we use in the `site-packages` directory of the virtual environment rather than installing them in the system Python, which is prone to conflicts when different versions of software packages are installed or upgraded. \n",
    "\n",
    "On the other hand, installing the packages in the project virtual environment also means that we are making this environment portable, meaning we can replicate the dependencies in another project or device. Note that, in addition to the installed project, the virtual environment also contains a link to the desired Python version. \n",
    "\n",
    "The syntax for creating a Python virtual environment is:\n",
    "\n",
    "```bash\n",
    "python -m venv <environment_path_and_name>\n",
    "```\n",
    "\n",
    "Note that, in Windows, in addition to python, you may use the `py` launcher to achieve the same goal.\n",
    "\n",
    "To create the virtual environment for the project, we issue the command as `python -m venv .venv`, in which `python` is the default desired version of Python, `-m` means module, `venv` is the module that creates virtual environment, and `.venv`, as a convention, is the name of the project virtual environment. \n",
    "\n",
    "If you want to control which version of Python to use (3.12, for example), you will use the version suffix by issuing `py -3.12 -m venv .venv` (Windows) or `python3.12 -m venv .venv` (macOS) to specify the Python version to use (which may be different from the system default Python version): \n",
    "\n",
    "::::{tab-set}\n",
    ":::{tab-item} Windows\n",
    "\n",
    "Start `PowerShell` and change directory into your project folder. If you want to specify a Python version, use the version suffix in the example. \n",
    "\n",
    "```bash\n",
    "PS C:\\Users\\[user]\\workspace\\dsm> py -m venv .venv\n",
    "PS C:\\Users\\[user]\\workspace\\dsm> ls\n",
    "    Directory: C:\\Users\\[user]\\workspace\\dsm\n",
    "Mode                 LastWriteTime         Length Name\n",
    "----                 -------------         ------ ----\n",
    "d-----         8/31/2025   3:36 AM                .venv\n",
    "```\n",
    "\n",
    "You see that `ls` shows that `.venv` virtual environment folder is created. \n",
    ":::\n",
    "\n",
    "\n",
    ":::{tab-item} macOS\n",
    "\n",
    "Start the Terminal.app and change directory into the project folder. Since `.venv` is a hidden directory because of the `.` at beginning of the folder name, you need to use the `-a` (means `a`ll files) option to `ls` to show it. \n",
    "\n",
    "```bash\n",
    "[user]@[host]ː~/workspace/dsm$ python3 -m venv .venv\n",
    "[user]@[host]ː~/workspace/dsm$ ls -a\n",
    ".     ..    .venv\n",
    "[user]@[host]ː~/workspace/dsm$ \n",
    "```\n",
    "\n",
    "Using the `ls` command, we see that the virtual environment **.venv** folder has been created. \n",
    ":::\n",
    "::::\n",
    "\n",
    "\n",
    "::::{tab-set}\n",
    ":::{tab-item} Windows\n",
    "\n",
    "```bash\n",
    "PS C:\\Users\\[user]\\workspace\\dsm> ls\n",
    "    Directory: C:\\Users\\[user]\\workspace\\dsm\n",
    "Mode                 LastWriteTime         Length Name\n",
    "----                 -------------         ------ ----\n",
    "d-----          9/4/2025   9:41 PM                .ipynb_checkpoints\n",
    "d-----          9/4/2025   9:41 PM                .venv\n",
    "```\n",
    "```{tab-item} macOS\n",
    "In macOS, using `ls` you will not see the **.venv** folder because file and directory names beginning with a dot are hidden. To see the .venv virtual environment in macOS, add the `-a` option to the `ls` command: `$ ls -a`.\n",
    "\n",
    "```bash\n",
    "[user]@[host]ː~/workspace/dsm$ ls -a\n",
    ".                       .venv                   labs                    test.ipynb\n",
    "..                      assignments_grading     NumPy                   test.py\n",
    ".DS_Store               data                    numpy_arrays.ipynb      \n",
    "```\n",
    "````\n",
    "\n",
    "\n",
    "Inside the .venv virtual environment directory, there is a lib/Lib directory containing a folder called **site-packages**, where all packages are installed. Additionally, all binary codes, including links to Python executables, the venv activation scripts, pip, and other program executables, are installed in the **bin** (macOS) or **Scripts** (Windows) folder. \n",
    "\n",
    "````{tab-set}\n",
    "```{tab-item} Windows\n",
    "In Windows, the site-packages directory appears as follows. So far, we only have *pip*, but every package you install will have a folder here, and soon the list will be long.\n",
    "```bash\n",
    "PS C:\\Users\\[user]\\workspace\\dsm> ls .venv\\lib\\site-packages\\\n",
    "    Directory: C:\\Users\\[user]\\workspace\\dsm\\.venv\\Lib\\site-packages\n",
    "Mode                 LastWriteTime         Length Name\n",
    "----                 -------------         ------ ----\n",
    "d-----         8/31/2025   3:36 AM                pip\n",
    "d-----         8/31/2025   3:36 AM                pip-24.0.dist-info\n",
    "```\n",
    "\n",
    "```{tab-item} macOS\n",
    "In macOS, the site-packages folder looks like below. So far we only have *pip* but every package you install will come here and soon the list will be long.\n",
    "```bash\n",
    "[user]@[host]ː~/workspace/dsm$ ls .venv/lib/python3.12/site-packages/\n",
    "pip                pip-24.0.dist-info\n",
    "```\n",
    "```` \n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4009ade5-0dea-496d-9a51-30255cac532f",
   "metadata": {},
   "source": [
    "## Activating/Deactivating venv\n",
    "\n",
    "To **activate** your virtual environment, in the CLI, make sure you are in the project directory (**dsm**) and type the following command to activate the project virtual environment. After the virtual environment is activated, a prefix (\"(**.venv**)\") will be present in front of the CLI prompt. \n",
    "\n",
    "::::{tab-set}\n",
    ":::{tab-item} Windows\n",
    "\n",
    "In Windows PowerShell, issue the following command (`.\\.venv\\Scripts\\activate`) in your project folder to activate the project's Python virtual environment. If the activation is successful, you will see a `(.venv)` showing up at the beginning of the command prompt line.\n",
    "\n",
    "```powershell\n",
    "PS C:\\Users\\[user]\\workspace\\dsm> .\\.venv\\Scripts\\activate\n",
    "(.venv) PS C:\\Users\\[user]\\workspace\\dsm>                 \n",
    "```\n",
    "\n",
    "When attempting to activate the virtual environment, Windows users may encounter a PowerShell security policy error. The error message for Windows looks like below. This happens because PowerShell is blocking the virtual environment’s `Activate.ps1` script because script execution is disabled for your user/session.\n",
    "\n",
    "```{figure} ../../../figures/venv-activate-error-windows.png\n",
    ":name: venv-activate-error-windows\n",
    ":alt: venv-activate-error-windows\n",
    ":width: 90%\n",
    "\n",
    "venv Activation Error for Windows\n",
    "```\n",
    "\n",
    "If it happens, issue the command as below in PowerShell (\"Run as administrator\" is needed if you don't say `-Scope CurrentUser` at the end of the command as below), exit all PowerShell tabs, and restart PowerShell before you activate your virtual environment:\n",
    "\n",
    "```powershell\n",
    "Set-ExecutionPolicy RemoteSigned -Scope CurrentUser\n",
    "```\n",
    "After executing the fix, you should be able to activate Python virtual environment in your project folder successfully.\n",
    "\n",
    "```{figure} ../../../figures/venv-activate-error-windows-fix.png\n",
    ":name: venv-activate-error-windows-fix\n",
    ":alt: venv-activate-error-windows-fix\n",
    ":width: 90%\n",
    "```\n",
    ":::\n",
    "\n",
    ":::{tab-item} macOS\n",
    "```bash   \n",
    "[user]@[host]ː~/workspace/py$ source .venv/bin/activate\n",
    "(.venv) [user]@[host]ː~/workspace/py$   \n",
    "```\n",
    ":::\n",
    "::::\n",
    "\n",
    "When the virtual environment is successfully activated, you will see **<span style=\" color: green;\">(.venv)</span>** appears before the shell's prompt line, which tells us the virtual environment is activated, we are using the designated version of Python, and that all the packages installation will go into the `site-packages` directory. \n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d17e8028",
   "metadata": {},
   "source": [
    "## Deactivating venv\n",
    "\n",
    "When you are done working on the project, you need to **deactivate** the virtual environment to prevent unintended installation of dependencies from other projects into this virtual environment. To do that, use the `deactivate` command (you can deactivate a virtual environment anywhere; it does not have to be in the project folder):\n",
    "\n",
    "\n",
    "::::{tab-set}\n",
    ":::{tab-item} Windows\n",
    "```powershell\n",
    "(.venv) PS C:\\Users\\[user]\\workspace\\dsm> deactivate\n",
    "PS C:\\Users\\[user]\\workspace\\dsm>\n",
    "```\n",
    ":::\n",
    "\n",
    ":::{tab-item} macOS\n",
    "```bash\n",
    "(.venv) [user]@[host]:~/workspace/dsm$ deactivate \n",
    "[user]@[host]:~/workspace/dsm$ \n",
    "```\n",
    ":::\n",
    "::::\n",
    "\n",
    "After you successfully deactivated the `venv`, the **<span style=\" color: green;\">(.venv)</span>** before the system shell's prompt line will disappear."
   ]
  }
 ],
 "metadata": {
  "jupytext": {
   "cell_metadata_filter": "-all"
  },
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.13.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
