{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Version Considerations\n",
    "\n",
    "The Seeq SPy module relies upon the Seeq SDK module in order to function. Your notebook, add-on or script code may require a particular version of SPy in order to function properly. Read the following sections to follow best practices for managing version requirements."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Packaging\n",
    "\n",
    "### Seeq R59 and Earlier\n",
    "\n",
    "For Seeq R59 and earlier, both the Seeq SDK and Seeq SPy Module were distributed in a single PyPI package called **[seeq](https://pypi.org/project/seeq/)**. It had a versioning scheme that was an amalgamation of both the Seeq SDK version (which is tied directly to the Seeq Server version it supports) and the SPy version (which is independent of the Seeq Server version). It took the following form:\n",
    "\n",
    "**a.b.c.F.G**\n",
    "\n",
    "For example, `seeq` package version [59.1.2.185.2](https://pypi.org/project/seeq/59.1.2.185.2/) supports Seeq Server version R59 and includes SPy version 185.2.\n",
    "\n",
    "### Seeq R60 and Later\n",
    "\n",
    "For Seeq R60 and later, the Seeq SDK is distributed in the  PyPI package **[seeq](https://pypi.org/project/seeq/)** and the Seeq SPy Module is distributed in a separate PyPI package called **[seeq-spy](https://pypi.org/project/seeq-spy/)**. The **seeq** package versioning scheme is tied directly to the Seeq Server version it supports and the **seeq-spy** package version is independent of the Seeq Server version.\n",
    "\n",
    "The two packages can be upgraded independently. However, when using Data Lab, then the user should _only_ upgrade the SPy package and allow the SDK package to be managed directly by Data Lab."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Upgrading\n",
    "\n",
    "Due to the change in packaging between R59 and R60, it is strongly recommended that you use the built in `spy.upgrade()` function to upgrade SPy. It has all the required logic to execute the correct commands depending on the Seeq Server you are connected to. You just execute the command below and then restart your Python kernel:\n",
    "\n",
    "```\n",
    "spy.upgrade()\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Displaying Version Information\n",
    "\n",
    "If you'd like to check what version you're running with, just print out the current session information, like so:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "keep_output_in_docs": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Not logged in.\n",
       "Seeq SDK Module Version: 66.0.0 @ C:\\git\\crab\\sdk\\pypi\\seeq\\sdk\n",
       "Seeq SPy Module Version: 193.0 @ C:\\git\\crab\\sdk\\pypi\\seeq\\spy"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from seeq import spy\n",
    "\n",
    "spy.session"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Checking for a Sufficient Version\n",
    "\n",
    "If you are writing a reusable notebook or script, or you are writing an add-on, you may wish to include a _version check_ in your code. Version checks are notoriously difficult to code correctly, so the `spy.utils` module includes some convenience functions to do the hard work for you.\n",
    "\n",
    "Here are some examples:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "keep_output_in_docs": true
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Logged in to <strong>http://localhost:34216</strong> as <strong>agent_api_key</strong>.<br>Seeq Server Version: <strong>R66.0.0-SNAPSHOT</strong><br>Seeq SDK Module Version: <strong>66.0.0</strong> @ C:\\git\\crab\\sdk\\pypi\\seeq\\sdk<br>Seeq SPy Module Version: <strong>193.0</strong> @ C:\\git\\crab\\sdk\\pypi\\seeq\\spy</div>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "SPy is at least 184.3? True\n",
      "Seeq Server is at least R73.3.1? False\n"
     ]
    }
   ],
   "source": [
    "from seeq import spy\n",
    "\n",
    "# Set the compatibility option so that you maximize the chance that SPy will remain compatible with your notebook/script\n",
    "spy.options.compatibility = 193\n",
    "\n",
    "# Login so we can check the Seeq Server version\n",
    "spy.login(url='http://localhost:34216', credentials_file='../credentials.key', force=False)\n",
    "\n",
    "# Check the SPy version\n",
    "print(f'SPy is at least 184.3? {spy.utils.is_spy_module_version_at_least(184, 3)}')\n",
    "print(f'Seeq Server is at least R73.3.1? {spy.utils.is_server_version_at_least(73, 3, 1)}')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Function Reference"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Help on function get_spy_module_version_tuple in module seeq.spy._login:\n",
      "\n",
      "get_spy_module_version_tuple() -> 'Tuple[int, int]'\n",
      "    Provides a tuple of (major, minor) version of Seeq SPy module (as\n",
      "    integers).\n",
      "    \n",
      "    Use this function instead of parsing spy.__version__.\n",
      "    \n",
      "    Returns\n",
      "    -------\n",
      "    Tuple of (major, minor) version of Seeq SPy module (as integers).\n",
      "\n",
      "Help on function is_spy_module_version_at_least in module seeq.spy._login:\n",
      "\n",
      "is_spy_module_version_at_least(required_major: 'int', required_minor: 'int' = 0) -> 'bool'\n",
      "    Use this function to ensure that the SPy module meets a version requirement.\n",
      "    \n",
      "    Parameters\n",
      "    ----------\n",
      "    required_major : int\n",
      "        The SPy major version that your notebook/script/application requires.\n",
      "    \n",
      "    required_minor : int, default 0\n",
      "        The SPy minor version that your notebook/script/application requires.\n",
      "    \n",
      "    Returns\n",
      "    -------\n",
      "    True if the SPy version is equal to or greater than the version specified.\n",
      "\n"
     ]
    }
   ],
   "source": [
    "help(spy.utils.get_spy_module_version_tuple)\n",
    "help(spy.utils.is_spy_module_version_at_least)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Help on function get_sdk_module_version_tuple in module seeq.spy._login:\n",
      "\n",
      "get_sdk_module_version_tuple() -> 'Tuple[int, int, int]'\n",
      "    Provides a tuple of (major, minor, patch) version of Seeq SDK module (as integers).\n",
      "    \n",
      "    The major version of the Seeq SDK should match the major version of the Seeq Server.\n",
      "    You can retrieve the version of the Seeq Server (once you've logged in) via\n",
      "    spy.utils.get_server_version_tuple().\n",
      "    \n",
      "    Use this function instead of parsing sdk.__version__.\n",
      "    \n",
      "    Returns\n",
      "    -------\n",
      "    Tuple of (major, minor, patch) version of Seeq SDK module (as integers).\n",
      "\n",
      "Help on function is_sdk_module_version_at_least in module seeq.spy._login:\n",
      "\n",
      "is_sdk_module_version_at_least(required_major: 'int', required_minor: 'int' = 0, required_patch: 'int' = 0) -> 'bool'\n",
      "    Use this function to ensure that the SDK module meets a version requirement.\n",
      "    \n",
      "    Parameters\n",
      "    ----------\n",
      "    required_major : int\n",
      "        The SDK major version that your notebook/script/application requires.\n",
      "    \n",
      "    required_minor : int, default 0\n",
      "        The SDK minor version that your notebook/script/application requires.\n",
      "    \n",
      "    required_patch : int, default 0\n",
      "        The SDK patch version that your notebook/script/application requires.\n",
      "    \n",
      "    Returns\n",
      "    -------\n",
      "    True if the SDK version is equal to or greater than the version specified.\n",
      "\n"
     ]
    }
   ],
   "source": [
    "help(spy.utils.get_sdk_module_version_tuple)\n",
    "help(spy.utils.is_sdk_module_version_at_least)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Help on function get_server_version_tuple in module seeq.spy._login:\n",
      "\n",
      "get_server_version_tuple(session: 'Session') -> 'Tuple[int, int, int]'\n",
      "    Provides a tuple of (major, minor, patch) version of the Seeq Server the\n",
      "    supplied session is connected to (as integers). If a session is not\n",
      "    supplied, the default session is used.\n",
      "    \n",
      "    The major version of the Seeq SDK should match the major version of the\n",
      "    Seeq Server. You can retrieve the version of the Seeq Server (once you've\n",
      "    logged in) via spy.utils.get_server_version_tuple().\n",
      "    \n",
      "    Use this function instead of parsing sdk.__version__.\n",
      "    \n",
      "    Parameters\n",
      "    ----------\n",
      "    session : spy.Session, optional\n",
      "        If supplied, the Session object used for the connection to Seeq\n",
      "        Server. If not supplied, the default session is used.\n",
      "    \n",
      "    Returns\n",
      "    -------\n",
      "    Tuple of (major, minor, patch) version of Seeq Server (as integers).\n",
      "\n",
      "Help on function is_server_version_at_least in module seeq.spy._login:\n",
      "\n",
      "is_server_version_at_least(required_major: 'int', required_minor: 'int' = 0, required_patch: 'int' = 0, session: 'Optional[Session]' = None) -> 'bool'\n",
      "    Use this function to ensure that the Seeq Server meets a version requirement.\n",
      "    \n",
      "    Parameters\n",
      "    ----------\n",
      "    required_major : int\n",
      "        The Seeq Server major version that your notebook/script/application requires.\n",
      "    \n",
      "    required_minor : int, default 0\n",
      "        The Seeq Server minor version that your notebook/script/application requires.\n",
      "    \n",
      "    required_patch : int, default 0\n",
      "        The Seeq Server patch version that your notebook/script/application requires.\n",
      "    \n",
      "    session : spy.Session, optional\n",
      "        If supplied, the Session object used for the connection to Seeq\n",
      "        Server. If not supplied, the default session is used.\n",
      "    \n",
      "    Returns\n",
      "    -------\n",
      "    True if the Seeq Server version is equal to or greater than the version specified.\n",
      "\n"
     ]
    }
   ],
   "source": [
    "help(spy.utils.get_server_version_tuple)\n",
    "help(spy.utils.is_server_version_at_least)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3.11",
   "language": "python",
   "name": "python311"
  },
  "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.11.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
