Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-tabpy for openSUSE:Factory 
checked in at 2022-04-20 16:56:24
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-tabpy (Old)
 and      /work/SRC/openSUSE:Factory/.python-tabpy.new.1941 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-tabpy"

Wed Apr 20 16:56:24 2022 rev:4 rq:970823 version:2.5.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-tabpy/python-tabpy.changes        
2021-02-15 23:20:36.995782609 +0100
+++ /work/SRC/openSUSE:Factory/.python-tabpy.new.1941/python-tabpy.changes      
2022-04-20 16:56:49.070594343 +0200
@@ -1,0 +2,24 @@
+Tue Apr 19 12:18:05 UTC 2022 - pgaj...@suse.com
+
+- version update to 2.5.0
+  ## v2.5.0
+  ### Improvements
+  - A server with Adhoc Disabled Flag on with the wrong credentials will now
+    return wrong credentials error instead of telling the user
+    that Adhoc Scripts are not allowed on this server.
+  - Added documentation for how to run TabPy projects with local changes
+  ### Breaking changes
+  - Discontinued support for Python 3.6
+  - Added support for Python 3.9
+  ## v2.4.0
+  ### Improvements
+  - Add toggle to turn off evaluate API.
+  ### Breaking changes
+  - Changing error code to 406 when server not configured for authentication
+    but credentials are provided by client.
+  ## v2.3.2
+  ### Improvements
+  - Test files added to tar.gz and zip releases.
+- python-mock is not required for build
+
+-------------------------------------------------------------------

Old:
----
  tabpy-2.3.1.tar.gz

New:
----
  tabpy-2.5.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-tabpy.spec ++++++
--- /var/tmp/diff_new_pack.BF4Oi9/_old  2022-04-20 16:56:49.634594870 +0200
+++ /var/tmp/diff_new_pack.BF4Oi9/_new  2022-04-20 16:56:49.638594874 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package python-tabpy
 #
-# Copyright (c) 2021 SUSE LLC
+# Copyright (c) 2022 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -20,7 +20,7 @@
 %define         skip_python2 1
 %define         skip_python36 1
 Name:           python-tabpy
-Version:        2.3.1
+Version:        2.5.0
 Release:        0
 Summary:        Tableau Python service
 License:        MIT
@@ -41,8 +41,8 @@
 Recommends:     python-nltk
 Recommends:     python-numpy
 Recommends:     python-pandas
-Recommends:     python-scipy
 Recommends:     python-scikit-learn
+Recommends:     python-scipy
 Suggests:       python-textblob
 BuildArch:      noarch
 # SECTION test requirements
@@ -52,7 +52,6 @@
 BuildRequires:  %{python_module docopt}
 BuildRequires:  %{python_module genson}
 BuildRequires:  %{python_module jsonschema}
-BuildRequires:  %{python_module mock}
 BuildRequires:  %{python_module nltk}
 BuildRequires:  %{python_module numpy}
 BuildRequires:  %{python_module pandas}
@@ -92,7 +91,7 @@
 }
 
 %check
-mkdir ~/bin
+mkdir -p ~/bin
 export PATH=~/bin:$PATH
 %{python_expand export PYTHONPATH=%{buildroot}%{$python_sitelib}
 cp %{buildroot}/%{_bindir}/tabpy-%{$python_bin_suffix} ~/bin/tabpy

++++++ tabpy-2.3.1.tar.gz -> tabpy-2.5.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/TabPy-2.3.1/.github/workflows/coverage.yml 
new/TabPy-2.5.0/.github/workflows/coverage.yml
--- old/TabPy-2.3.1/.github/workflows/coverage.yml      2020-11-10 
19:28:04.000000000 +0100
+++ new/TabPy-2.5.0/.github/workflows/coverage.yml      2022-01-20 
22:20:43.000000000 +0100
@@ -27,8 +27,13 @@
         pip install -r requirements_dev.txt
 
     - name: Test with pytest
-      run: |
+      run: 
         pytest tests --cov=tabpy --cov-config=setup.cfg
-        coveralls
       env:
         COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }}
+    
+    - name: Run coveralls
+      run: 
+        coveralls --service=github
+      env:
+        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/TabPy-2.3.1/.github/workflows/docker-publish.yml 
new/TabPy-2.5.0/.github/workflows/docker-publish.yml
--- old/TabPy-2.3.1/.github/workflows/docker-publish.yml        2020-11-10 
19:28:04.000000000 +0100
+++ new/TabPy-2.5.0/.github/workflows/docker-publish.yml        2022-01-20 
22:20:43.000000000 +0100
@@ -2,7 +2,7 @@
 
 on:
   release:
-    types: [released]
+    types: [published]
     
 env:
   IMAGE_NAME: tabpy
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/TabPy-2.3.1/.github/workflows/pull_request.yml 
new/TabPy-2.5.0/.github/workflows/pull_request.yml
--- old/TabPy-2.3.1/.github/workflows/pull_request.yml  2020-11-10 
19:28:04.000000000 +0100
+++ new/TabPy-2.5.0/.github/workflows/pull_request.yml  2022-01-20 
22:20:43.000000000 +0100
@@ -9,7 +9,7 @@
     
     strategy:
       matrix:
-        python-version: [3.6, 3.7, 3.8]
+        python-version: [3.7, 3.8, 3.9]
         os: [ubuntu-latest, windows-latest, macos-latest]
 
     steps:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/TabPy-2.3.1/.github/workflows/push.yml 
new/TabPy-2.5.0/.github/workflows/push.yml
--- old/TabPy-2.3.1/.github/workflows/push.yml  2020-11-10 19:28:04.000000000 
+0100
+++ new/TabPy-2.5.0/.github/workflows/push.yml  2022-01-20 22:20:43.000000000 
+0100
@@ -9,7 +9,7 @@
     
     strategy:
       matrix:
-        python-version: [3.6, 3.7, 3.8]
+        python-version: [3.7, 3.8, 3.9]
         os: [ubuntu-latest, windows-latest, macos-latest]
 
     steps:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/TabPy-2.3.1/CHANGELOG new/TabPy-2.5.0/CHANGELOG
--- old/TabPy-2.3.1/CHANGELOG   2020-11-10 19:28:04.000000000 +0100
+++ new/TabPy-2.5.0/CHANGELOG   2022-01-20 22:20:43.000000000 +0100
@@ -1,5 +1,36 @@
 # Changelog
 
+## v2.5.0
+
+### Improvements
+
+- A server with Adhoc Disabled Flag on with the wrong credentials will now
+  return wrong credentials error instead of telling the user
+  that Adhoc Scripts are not allowed on this server.
+- Added documentation for how to run TabPy projects with local changes
+
+### Breaking changes
+
+- Discontinued support for Python 3.6
+- Added support for Python 3.9
+
+## v2.4.0
+
+### Improvements
+
+- Add toggle to turn off evaluate API.
+
+### Breaking changes
+
+- Changing error code to 406 when server not configured for authentication
+  but credentials are provided by client.
+
+## v2.3.2
+
+### Improvements
+
+- Test files added to tar.gz and zip releases.
+
 ## v2.3.1
 
 ### Bug fixes
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/TabPy-2.3.1/CONTRIBUTING.md 
new/TabPy-2.5.0/CONTRIBUTING.md
--- old/TabPy-2.3.1/CONTRIBUTING.md     2020-11-10 19:28:04.000000000 +0100
+++ new/TabPy-2.5.0/CONTRIBUTING.md     2022-01-20 22:20:43.000000000 +0100
@@ -30,7 +30,7 @@
 These are prerequisites for an environment required for a contributor to
 be able to work on TabPy changes:
 
-- Python 3.6, 3.7 or 3.8:
+- Python 3.7, 3.8 or 3.9:
   - To see which version of Python you have installed, run `python --version`.
 - git
 - Node.js for npm packages - install from <https://nodejs.org>.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/TabPy-2.3.1/Dockerfile new/TabPy-2.5.0/Dockerfile
--- old/TabPy-2.3.1/Dockerfile  1970-01-01 01:00:00.000000000 +0100
+++ new/TabPy-2.5.0/Dockerfile  2022-01-20 22:20:43.000000000 +0100
@@ -0,0 +1,14 @@
+FROM python:3
+
+WORKDIR /app
+
+# install the latest TabPy
+RUN python3 -m pip install --upgrade pip && python3 -m pip install --upgrade 
tabpy
+
+# start TabPy
+CMD ["sh", "-c", "tabpy"]
+
+# run startup script
+ADD start.sh /
+RUN chmod +x /start.sh
+CMD ["/start.sh"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/TabPy-2.3.1/MANIFEST.in new/TabPy-2.5.0/MANIFEST.in
--- old/TabPy-2.3.1/MANIFEST.in 2020-11-10 19:28:04.000000000 +0100
+++ new/TabPy-2.5.0/MANIFEST.in 2022-01-20 22:20:43.000000000 +0100
@@ -3,8 +3,21 @@
 
 include \
   CHANGELOG \
-  LICENSE \
+  LICENSE \
+  README.md \
+  Procfile \
   tabpy/VERSION \
   tabpy/tabpy_server/state.ini.template \
   tabpy/tabpy_server/static/* \
   tabpy/tabpy_server/common/default.conf
+
+# Docs and tests
+include requirements_dev.txt requirements.txt
+recursive-include docs *.md
+recursive-include docs *.png
+recursive-include misc *.json
+recursive-include misc *.yml
+recursive-include tests *.conf
+recursive-include tests *.crt
+recursive-include tests *.key
+recursive-include tests *.txt
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/TabPy-2.3.1/Procfile new/TabPy-2.5.0/Procfile
--- old/TabPy-2.3.1/Procfile    2020-11-10 19:28:04.000000000 +0100
+++ new/TabPy-2.5.0/Procfile    2022-01-20 22:20:43.000000000 +0100
@@ -1 +1 @@
-web: export TABPY_PORT=$PORT && tabpy
\ No newline at end of file
+web: export TABPY_PORT=$PORT && export TABPY_PWD_FILE=./file.txt && tabpy-user 
add -u $USERNAME -p $PASSWORD -f ./file.txt && tabpy
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/TabPy-2.3.1/README.md new/TabPy-2.5.0/README.md
--- old/TabPy-2.3.1/README.md   2020-11-10 19:28:04.000000000 +0100
+++ new/TabPy-2.5.0/README.md   2022-01-20 22:20:43.000000000 +0100
@@ -11,7 +11,7 @@
 ![PyPI - Python 
Version](https://img.shields.io/pypi/pyversions/tabpy?label=PyPI%20Python%20versions)
 [![PyPI 
version](https://badge.fury.io/py/tabpy.svg)](https://pypi.python.org/pypi/tabpy/)
 
-[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy)
+[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy?template=https://github.com/tableau/tabpy)
 
 TabPy (the Tableau Python Server) is an Analytics Extension implementation 
which
 expands Tableau's capabilities by allowing users to execute Python scripts and
@@ -52,5 +52,3 @@
 * [TabPy Tutorial on TabWiki](https://community.tableau.com/docs/DOC-10856)
 
 ![GitHub commit 
activity](https://img.shields.io/github/commit-activity/m/tableau/TabPy.svg)
-![GitHub 
forks](https://img.shields.io/github/forks/tableau/TabPy.svg?label=Forks&style=social)
-![GitHub 
stars](https://img.shields.io/github/stars/tableau/TabPy.svg?style=social)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/TabPy-2.3.1/app.json new/TabPy-2.5.0/app.json
--- old/TabPy-2.3.1/app.json    2020-11-10 19:28:04.000000000 +0100
+++ new/TabPy-2.5.0/app.json    2022-01-20 22:20:43.000000000 +0100
@@ -2,6 +2,18 @@
     "name": "TabPy",
     "description": "Analytics Extension implementation which expands Tableau's 
capabilities by allowing users to execute Python scripts and saved functions 
via Tableau's table calculations.",
     "repository": "https://github.com/tableau/TabPy";,
-    "logo": "",
-    "keywords": ["tableau", "python", "analytics-extension"]
+    "logo": 
"https://raw.githubusercontent.com/tableau/TabPy/master/tabpy/tabpy_server/static/TabPy_logo.png";,
+    "keywords": ["tableau", "python", "analytics-extension"],
+    "env":{
+        "USERNAME":{
+            "description": "Add your username",
+            "value": "gzanolli",
+            "required": true
+        },
+        "PASSWORD":{
+            "description": "Define your password",
+            "value": "P@ssw0rd",
+            "required": true
+        }
+    }
 }
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/TabPy-2.3.1/codeql-analysis.yml 
new/TabPy-2.5.0/codeql-analysis.yml
--- old/TabPy-2.3.1/codeql-analysis.yml 1970-01-01 01:00:00.000000000 +0100
+++ new/TabPy-2.5.0/codeql-analysis.yml 2022-01-20 22:20:43.000000000 +0100
@@ -0,0 +1,71 @@
+# For most projects, this workflow file will not need changing; you simply need
+# to commit it to your repository.
+#
+# You may wish to alter this file to override the set of languages analyzed,
+# or to provide custom queries or build logic.
+#
+# ******** NOTE ********
+# We have attempted to detect the languages in your repository. Please check
+# the `language` matrix defined below to confirm you have the correct set of
+# supported CodeQL languages.
+#
+name: "CodeQL"
+
+on:
+  push:
+    branches: [ master, dev ]
+  pull_request:
+    # The branches below must be a subset of the branches above
+    branches: [ master ]
+  schedule:
+    - cron: '0 22 * * 3'
+
+jobs:
+  analyze:
+    name: Analyze
+    runs-on: ubuntu-latest
+    permissions:
+      actions: read
+      contents: read
+      security-events: write
+
+    strategy:
+      fail-fast: false
+      matrix:
+        language: [ 'python' ]
+        # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 
'python' ]
+        # Learn more:
+        # 
https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
+
+    steps:
+    - name: Checkout repository
+      uses: actions/checkout@v2
+
+    # Initializes the CodeQL tools for scanning.
+    - name: Initialize CodeQL
+      uses: github/codeql-action/init@v1
+      with:
+        languages: ${{ matrix.language }}
+        # If you wish to specify custom queries, you can do so here or in a 
config file.
+        # By default, queries listed here will override any specified in a 
config file.
+        # Prefix the list here with "+" to use these queries and those in the 
config file.
+        # queries: ./path/to/local/query, your-org/your-repo/queries@main
+
+    # Autobuild attempts to build any compiled languages  (C/C++, C#, or Java).
+    # If this step fails, then you should remove it and run the build manually 
(see below)
+    - name: Autobuild
+      uses: github/codeql-action/autobuild@v1
+
+    # ?????? Command-line programs to run using the OS shell.
+    # ???? https://git.io/JvXDl
+
+    # ?????? If the Autobuild fails above, remove it and uncomment the 
following three lines
+    #    and modify them (or add more) to build your code if your project
+    #    uses a compiled language
+
+    #- run: |
+    #   make bootstrap
+    #   make release
+
+    - name: Perform CodeQL Analysis
+      uses: github/codeql-action/analyze@v1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/TabPy-2.3.1/docs/TableauConfiguration.md 
new/TabPy-2.5.0/docs/TableauConfiguration.md
--- old/TabPy-2.3.1/docs/TableauConfiguration.md        2020-11-10 
19:28:04.000000000 +0100
+++ new/TabPy-2.5.0/docs/TableauConfiguration.md        2022-01-20 
22:20:43.000000000 +0100
@@ -1,16 +1,20 @@
 # Using Python in Tableau Calculations
 
 <!-- markdownlint-disable MD004 -->
+
 <!-- toc -->
 
 - [Configuration](#configuration)
   * [Tableau Desktop](#tableau-desktop)
-  * [Tableau Server 2018.2 and Newer 
Versions](#tableau-server-20182-and-newer-versions)
+  * [Tableau Server 2020.2 and Newer 
Versions](#tableau-server-20202-and-newer-versions)
+  * [Tableau Server 2020.1 and older](#tableau-server-20201-and-older)
+  * [Tableau Server 2018.2 and 2018.3](#tableau-server-20182-and-20183)
   * [Tableau Server 2018.1 and Older 
Versions](#tableau-server-20181-and-older-versions)
 - [Anatomy of a Python Calculation](#anatomy-of-a-python-calculation)
 - [Using Deployed Functions](#using-deployed-functions)
 
 <!-- tocstop -->
+
 <!-- markdownlint-enable MD004 -->
 
 ## Configuration
@@ -25,7 +29,24 @@
 [Configure an Analytics Extension 
connection](https://help.tableau.com/current/pro/desktop/en-us/r_connection_manage.htm#configure-an-external-service-connection)
 documentation page.
 
-### Tableau Server 2018.2 and Newer Versions
+### Tableau Server 2020.2 and Newer Versions
+
+Starting from Tableau Server 2020.2 analytics extensions connections
+are configured on site level as shown of
+[Configure Connections to Analytics 
Extensions](https://help.tableau.com/current/server/en-us/config_r_tabpy.htm)
+page.
+
+### Tableau Server 2020.1 and older
+
+For older Tableau Server versions refer to version specific documentation:
+
+- [2020.1](https://help.tableau.com/v2020.1/server/en-us/config_r_tabpy.htm).
+- [2019.4](https://help.tableau.com/v2019.4/server/en-us/config_r_tabpy.htm).
+- 
[2019.3](https://help.tableau.com/v2019.3/server/en-us/cli_security_tsm.htm#tsm_security_vizql-extsvc-ssl-enable).
+- 
[2019.2](https://help.tableau.com/v2019.2/server/en-us/cli_security_tsm.htm#tsm_security_vizql-extsvc-ssl-enable).
+- 
[2019.1](https://help.tableau.com/v2019.1/server/en-us/cli_security_tsm.htm#tsm_security_vizql-extsvc-ssl-enable).
+
+### Tableau Server 2018.2 and 2018.3
 
 To configure Tableau Server 2018.2 and newer versions to connect to TabPy 
server
 follow instructions on Tableau
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/TabPy-2.3.1/docs/security.md 
new/TabPy-2.5.0/docs/security.md
--- old/TabPy-2.3.1/docs/security.md    2020-11-10 19:28:04.000000000 +0100
+++ new/TabPy-2.5.0/docs/security.md    2022-01-20 22:20:43.000000000 +0100
@@ -14,3 +14,6 @@
   - Install new Python packages which can contain binary code.
   - Execute operating system commands.
   - Open network connections to other servers and download files.
+- Execution of ad-hoc Python scripts can be disabled by turning off the
+  /evaluate endpoint. To disable /evaluate endpoint, set 
"TABPY_EVALUATE_ENABLE"
+  to false in config file.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/TabPy-2.3.1/docs/server-config.md 
new/TabPy-2.5.0/docs/server-config.md
--- old/TabPy-2.3.1/docs/server-config.md       2020-11-10 19:28:04.000000000 
+0100
+++ new/TabPy-2.5.0/docs/server-config.md       2022-01-20 22:20:43.000000000 
+0100
@@ -87,6 +87,8 @@
 - `TABPY_MAX_REQUEST_SIZE_MB` - maximal request size supported by TabPy server
   in Megabytes. All requests of exceeding size are rejected. Default value is
   100 Mb.
+- `TABPY_EVALUATE_ENABLE` - enable evaluate api to execute ad-hoc Python 
scripts
+  Default value - `true`.
 - `TABPY_EVALUATE_TIMEOUT` - script evaluation timeout in seconds. Default
   value - `30`. This timeout does not apply when evaluating models either
   through the `/query` method, or using the `tabpy.query(...)` syntax with
@@ -125,6 +127,10 @@
 # Default value is 100 Mb.
 # TABPY_MAX_REQUEST_SIZE_MB = 100
 
+# Enable evaluate api to execute ad-hoc Python scripts
+# Enabled by default. Disabling it will result in 404 error.
+# TABPY_EVALUATE_ENABLE = true
+
 # Configure how long a custom script provided to the /evaluate method
 # will run before throwing a TimeoutError.
 # The value should be a float representing the timeout time in seconds.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/TabPy-2.3.1/docs/server-install.md 
new/TabPy-2.5.0/docs/server-install.md
--- old/TabPy-2.3.1/docs/server-install.md      2020-11-10 19:28:04.000000000 
+0100
+++ new/TabPy-2.5.0/docs/server-install.md      2022-01-20 22:20:43.000000000 
+0100
@@ -47,3 +47,19 @@
 It is highly recommended to use Python virtual environment for running TabPy.
 Check the [Running TabPy in Python Virtual Environment](tabpy-virtualenv.md) 
page
 for more details.
+
+## Starting a Local TabPy Project
+
+To create a version of TabPy that incorporates locally-made changes,
+use pip to create a package from your local TabPy project
+and install it within that directory (preferably a virtual environment):
+
+```sh
+pip install -e .
+```
+
+Then start TabPy just like it was mentioned earlier
+
+```sh
+tabpy
+```
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/TabPy-2.3.1/docs/tabpy-tools.md 
new/TabPy-2.5.0/docs/tabpy-tools.md
--- old/TabPy-2.3.1/docs/tabpy-tools.md 2020-11-10 19:28:04.000000000 +0100
+++ new/TabPy-2.5.0/docs/tabpy-tools.md 2022-01-20 22:20:43.000000000 +0100
@@ -18,6 +18,7 @@
 - [Providing Schema Metadata](#providing-schema-metadata)
 - [Querying an Endpoint](#querying-an-endpoint)
 - [Evaluating Arbitrary Python Scripts](#evaluating-arbitrary-python-scripts)
+- [Deploying Models in TabPy Docker 
Container](#deploying-models-in-tabpy-docker-container)
 
 <!-- tocstop -->
 
@@ -38,7 +39,7 @@
 
 The URL and port are where the Tableau-Python-Server process has been started -
 more info can be found in the
-[server section](server-startup.md#Command-Line-Arguments) of the 
documentation.
+[Starting TabPy](server-install.md#starting-tabpy) section of the 
documentation.
 
 ## Authentication
 
@@ -433,3 +434,16 @@
 The convention for this is to use a provided function call `tabpy.query` in the
 code, which behaves like the `query` method in `tabpy-tools`. See the
 [REST API documentation](server-rest.md) for an example.
+
+## Deploying Models in TabPy Docker Container
+
+To deploy custom models for TabPy running in docker container, first copy all
+python model files onto host machine.
+
+For example, `myFunction.py` is the model we want to deploy.
+Run following from the folder containing `myFunction.py` on host machine
+
+```console
+docker cp myFunction.py <container_id>:/app/scripts/myFunction.py
+docker exec -it <container_id> python /app/scripts/myFunction.py
+```
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/TabPy-2.3.1/docs/tabpy-virtualenv.md 
new/TabPy-2.5.0/docs/tabpy-virtualenv.md
--- old/TabPy-2.3.1/docs/tabpy-virtualenv.md    2020-11-10 19:28:04.000000000 
+0100
+++ new/TabPy-2.5.0/docs/tabpy-virtualenv.md    2022-01-20 22:20:43.000000000 
+0100
@@ -33,10 +33,27 @@
       ```
 
 4. Run TabPy:
+   1. Default TabPy
 
-   ```sh
-   tabpy
-   ```
+      ```sh
+      tabpy
+      ```
+
+   2. Local TabPy
+
+      To create a version of TabPy that incorporates locally-made changes,
+      use pip to create a package from your local TabPy project and install
+      it within that directory:
+
+         ```sh
+         pip install -e .
+         ```
+
+      Then start TabPy just like it was mentioned earlier
+
+         ```sh
+         tabpy
+         ```
 
 5. To deactivate virtual environment run:
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/TabPy-2.3.1/setup.py new/TabPy-2.5.0/setup.py
--- old/TabPy-2.3.1/setup.py    2020-11-10 19:28:04.000000000 +0100
+++ new/TabPy-2.5.0/setup.py    2022-01-20 22:20:43.000000000 +0100
@@ -39,9 +39,9 @@
             "Intended Audience :: Developers",
             "Intended Audience :: Science/Research",
             "License :: OSI Approved :: MIT License",
-            "Programming Language :: Python :: 3.6",
             "Programming Language :: Python :: 3.7",
             "Programming Language :: Python :: 3.8",
+            "Programming Language :: Python :: 3.9",
             "Topic :: Scientific/Engineering",
             "Topic :: Scientific/Engineering :: Information Analysis",
             "Operating System :: Microsoft :: Windows",
@@ -60,7 +60,7 @@
                 "tabpy_server/common/default.conf",
             ]
         },
-        python_requires=">=3.6",
+        python_requires=">=3.7",
         license="MIT",
         # Note: many of these required packages are included in base python
         # but are listed here because different linux distros use custom
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/TabPy-2.3.1/start.sh new/TabPy-2.5.0/start.sh
--- old/TabPy-2.3.1/start.sh    1970-01-01 01:00:00.000000000 +0100
+++ new/TabPy-2.5.0/start.sh    2022-01-20 22:20:43.000000000 +0100
@@ -0,0 +1,23 @@
+#!/bin/bash
+
+# Start tabpy
+tabpy &
+
+# Wait for server to become available, wait 1 min maximum
+attempt_counter=0
+max_attempts=20
+
+until $(curl --output /dev/null --silent --head --fail localhost:9004); do
+    if [ ${attempt_counter} -eq ${max_attempts} ];then
+      echo "Maximum attempts reached, tabpy server not started"
+      exit 1
+    fi
+
+    echo "Waiting for tabpy server"
+    attempt_counter=$(($attempt_counter+1))
+    sleep 3
+done
+
+# Deploy tabpy models
+tabpy-deploy-models &
+wait
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/TabPy-2.3.1/tabpy/VERSION 
new/TabPy-2.5.0/tabpy/VERSION
--- old/TabPy-2.3.1/tabpy/VERSION       2020-11-10 19:28:04.000000000 +0100
+++ new/TabPy-2.5.0/tabpy/VERSION       2022-01-20 22:20:43.000000000 +0100
@@ -1 +1 @@
-2.3.1
\ No newline at end of file
+2.5.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/TabPy-2.3.1/tabpy/tabpy_server/app/app.py 
new/TabPy-2.5.0/tabpy/tabpy_server/app/app.py
--- old/TabPy-2.3.1/tabpy/tabpy_server/app/app.py       2020-11-10 
19:28:04.000000000 +0100
+++ new/TabPy-2.5.0/tabpy/tabpy_server/app/app.py       2022-01-20 
22:20:43.000000000 +0100
@@ -18,6 +18,7 @@
     EndpointHandler,
     EndpointsHandler,
     EvaluationPlaneHandler,
+    EvaluationPlaneDisabledHandler,
     QueryPlaneHandler,
     ServiceInfoHandler,
     StatusHandler,
@@ -150,7 +151,8 @@
                 ),
                 (
                     self.subdirectory + r"/evaluate",
-                    EvaluationPlaneHandler,
+                    EvaluationPlaneHandler if 
self.settings[SettingsParameters.EvaluateEnabled]
+                    else EvaluationPlaneDisabledHandler,
                     dict(executor=executor, app=self),
                 ),
                 (
@@ -259,6 +261,8 @@
         settings_parameters = [
             (SettingsParameters.Port, ConfigParameters.TABPY_PORT, 9004, None),
             (SettingsParameters.ServerVersion, None, __version__, None),
+            (SettingsParameters.EvaluateEnabled, 
ConfigParameters.TABPY_EVALUATE_ENABLE,
+             True, parser.getboolean),
             (SettingsParameters.EvaluateTimeout, 
ConfigParameters.TABPY_EVALUATE_TIMEOUT,
              30, parser.getfloat),
             (SettingsParameters.UploadDir, 
ConfigParameters.TABPY_QUERY_OBJECT_PATH,
@@ -412,6 +416,7 @@
                 "methods": {"basic-auth": {}},
             }
 
+        features["evaluate_enabled"] = 
self.settings[SettingsParameters.EvaluateEnabled]
         return features
 
     def _build_tabpy_state(self):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/TabPy-2.3.1/tabpy/tabpy_server/app/app_parameters.py 
new/TabPy-2.5.0/tabpy/tabpy_server/app/app_parameters.py
--- old/TabPy-2.3.1/tabpy/tabpy_server/app/app_parameters.py    2020-11-10 
19:28:04.000000000 +0100
+++ new/TabPy-2.5.0/tabpy/tabpy_server/app/app_parameters.py    2022-01-20 
22:20:43.000000000 +0100
@@ -14,6 +14,7 @@
     TABPY_LOG_DETAILS = "TABPY_LOG_DETAILS"
     TABPY_STATIC_PATH = "TABPY_STATIC_PATH"
     TABPY_MAX_REQUEST_SIZE_MB = "TABPY_MAX_REQUEST_SIZE_MB"
+    TABPY_EVALUATE_ENABLE = "TABPY_EVALUATE_ENABLE"
     TABPY_EVALUATE_TIMEOUT = "TABPY_EVALUATE_TIMEOUT"
 
 
@@ -34,3 +35,4 @@
     StaticPath = "static_path"
     MaxRequestSizeInMb = "max_request_size_in_mb"
     EvaluateTimeout = "evaluate_timeout"
+    EvaluateEnabled = "evaluate_enabled"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/TabPy-2.3.1/tabpy/tabpy_server/common/default.conf 
new/TabPy-2.5.0/tabpy/tabpy_server/common/default.conf
--- old/TabPy-2.3.1/tabpy/tabpy_server/common/default.conf      2020-11-10 
19:28:04.000000000 +0100
+++ new/TabPy-2.5.0/tabpy/tabpy_server/common/default.conf      2022-01-20 
22:20:43.000000000 +0100
@@ -25,6 +25,10 @@
 # Default value is 100 Mb.
 # TABPY_MAX_REQUEST_SIZE_MB = 100
 
+# Enable evaluate api to execute ad-hoc Python scripts
+# Enabled by default. Disabling it will result in 404 error.
+# TABPY_EVALUATE_ENABLE = true
+
 # Configure how long a custom script provided to the /evaluate method
 # will run before throwing a TimeoutError.
 # The value should be a float representing the timeout time in seconds.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/TabPy-2.3.1/tabpy/tabpy_server/handlers/__init__.py 
new/TabPy-2.5.0/tabpy/tabpy_server/handlers/__init__.py
--- old/TabPy-2.3.1/tabpy/tabpy_server/handlers/__init__.py     2020-11-10 
19:28:04.000000000 +0100
+++ new/TabPy-2.5.0/tabpy/tabpy_server/handlers/__init__.py     2022-01-20 
22:20:43.000000000 +0100
@@ -3,6 +3,7 @@
 
 from tabpy.tabpy_server.handlers.endpoint_handler import EndpointHandler
 from tabpy.tabpy_server.handlers.endpoints_handler import EndpointsHandler
+from tabpy.tabpy_server.handlers.evaluation_plane_handler import 
EvaluationPlaneDisabledHandler
 from tabpy.tabpy_server.handlers.evaluation_plane_handler import 
EvaluationPlaneHandler
 from tabpy.tabpy_server.handlers.query_plane_handler import QueryPlaneHandler
 from tabpy.tabpy_server.handlers.service_info_handler import ServiceInfoHandler
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/TabPy-2.3.1/tabpy/tabpy_server/handlers/base_handler.py 
new/TabPy-2.5.0/tabpy/tabpy_server/handlers/base_handler.py
--- old/TabPy-2.3.1/tabpy/tabpy_server/handlers/base_handler.py 2020-11-10 
19:28:04.000000000 +0100
+++ new/TabPy-2.5.0/tabpy/tabpy_server/handlers/base_handler.py 2022-01-20 
22:20:43.000000000 +0100
@@ -421,7 +421,7 @@
 
     def fail_with_auth_error(self):
         """
-        Prepares server 401 response and server 400 response depending
+        Prepares server 401 response and server 406 response depending
         on the value of the self.auth_error flag
         """
         if self.auth_error == AuthErrorStates.NotAuthorized:
@@ -434,11 +434,11 @@
                 log_message="Invalid credentials provided.",
             )
         else:
-            self.logger.log(logging.ERROR, "Failing with 400 for Bad Request")
-            self.set_status(400)
+            self.logger.log(logging.ERROR, "Failing with 406 for Not 
Acceptable")
+            self.set_status(406)
             self.set_header("WWW-Authenticate", f'Basic 
realm="{self.tabpy_state.name}"')
             self.error_out(
-                400,
-                info="Bad request.",
-                log_message="Username or Password provided when authentication 
not available",
+                406,
+                info="Not Acceptable",
+                log_message="Username or password provided when authentication 
not available.",
             )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/TabPy-2.3.1/tabpy/tabpy_server/handlers/evaluation_plane_handler.py 
new/TabPy-2.5.0/tabpy/tabpy_server/handlers/evaluation_plane_handler.py
--- old/TabPy-2.3.1/tabpy/tabpy_server/handlers/evaluation_plane_handler.py     
2020-11-10 19:28:04.000000000 +0100
+++ new/TabPy-2.5.0/tabpy/tabpy_server/handlers/evaluation_plane_handler.py     
2022-01-20 22:20:43.000000000 +0100
@@ -29,6 +29,24 @@
         return response.json()
 
 
+class EvaluationPlaneDisabledHandler(BaseHandler):
+    """
+    EvaluationPlaneDisabledHandler responds with error message when ad-hoc 
scripts have been disabled.
+    """
+
+    def initialize(self, executor, app):
+        super(EvaluationPlaneDisabledHandler, self).initialize(app)
+        self.executor = executor
+
+    @gen.coroutine
+    def post(self):
+        if self.should_fail_with_auth_error() != AuthErrorStates.NONE:
+            self.fail_with_auth_error()
+            return
+        self.error_out(404, "Ad-hoc scripts have been disabled on this 
analytics extension, please contact your "
+                            "administrator.")
+
+
 class EvaluationPlaneHandler(BaseHandler):
     """
     EvaluationPlaneHandler is responsible for running arbitrary python scripts.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/TabPy-2.3.1/tabpy/tabpy_server/handlers/query_plane_handler.py 
new/TabPy-2.5.0/tabpy/tabpy_server/handlers/query_plane_handler.py
--- old/TabPy-2.3.1/tabpy/tabpy_server/handlers/query_plane_handler.py  
2020-11-10 19:28:04.000000000 +0100
+++ new/TabPy-2.5.0/tabpy/tabpy_server/handlers/query_plane_handler.py  
2022-01-20 22:20:43.000000000 +0100
@@ -104,7 +104,7 @@
             elif response_type == QueryError:
                 self.error_out(400, "QueryError", info=response)
             else:
-                self.error_out(500, "Error querying GLS", info=response)
+                self.error_out(500, f"Error querying function '{po_name}'", 
info=response)
 
             return (None, None)
 
@@ -149,7 +149,7 @@
             # endpoint_name) is None
             if not po_name:
                 self.error_out(
-                    404, "UnknownURI", info=f'Endpoint "{endpoint_name}" does 
not exist'
+                    404, "UnknownURI", info=f"Endpoint '{endpoint_name}' does 
not exist"
                 )
                 return
 
Binary files old/TabPy-2.3.1/tabpy/tabpy_server/static/TabPy_logo.png and 
new/TabPy-2.5.0/tabpy/tabpy_server/static/TabPy_logo.png differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/TabPy-2.3.1/tests/unit/server_tests/test_endpoint_handler.py 
new/TabPy-2.5.0/tests/unit/server_tests/test_endpoint_handler.py
--- old/TabPy-2.3.1/tests/unit/server_tests/test_endpoint_handler.py    
2020-11-10 19:28:04.000000000 +0100
+++ new/TabPy-2.5.0/tests/unit/server_tests/test_endpoint_handler.py    
2022-01-20 22:20:43.000000000 +0100
@@ -161,4 +161,4 @@
                 )
             },
         )
-        self.assertEqual(400, response.code)
+        self.assertEqual(406, response.code)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/TabPy-2.3.1/tests/unit/server_tests/test_endpoints_handler.py 
new/TabPy-2.5.0/tests/unit/server_tests/test_endpoints_handler.py
--- old/TabPy-2.3.1/tests/unit/server_tests/test_endpoints_handler.py   
2020-11-10 19:28:04.000000000 +0100
+++ new/TabPy-2.5.0/tests/unit/server_tests/test_endpoints_handler.py   
2022-01-20 22:20:43.000000000 +0100
@@ -143,4 +143,4 @@
                 )
             },
         )
-        self.assertEqual(400, response.code)
+        self.assertEqual(406, response.code)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/TabPy-2.3.1/tests/unit/server_tests/test_evaluation_plane_handler.py 
new/TabPy-2.5.0/tests/unit/server_tests/test_evaluation_plane_handler.py
--- old/TabPy-2.3.1/tests/unit/server_tests/test_evaluation_plane_handler.py    
2020-11-10 19:28:04.000000000 +0100
+++ new/TabPy-2.5.0/tests/unit/server_tests/test_evaluation_plane_handler.py    
2022-01-20 22:20:43.000000000 +0100
@@ -2,16 +2,16 @@
 import os
 import tempfile
 
-from argparse import Namespace
+from tornado.testing import AsyncHTTPTestCase
+
 from tabpy.tabpy_server.app.app import TabPyApp
 from tabpy.tabpy_server.handlers.util import hash_password
-from tornado.testing import AsyncHTTPTestCase
 
 
-class TestEvaluationPlainHandlerWithAuth(AsyncHTTPTestCase):
+class TestEvaluationPlaneHandlerWithAuth(AsyncHTTPTestCase):
     @classmethod
     def setUpClass(cls):
-        prefix = "__TestEvaluationPlainHandlerWithAuth_"
+        prefix = "__TestEvaluationPlaneHandlerWithAuth_"
         # create password file
         cls.pwd_file = tempfile.NamedTemporaryFile(
             mode="w+t", prefix=prefix, suffix=".txt", delete=False
@@ -205,10 +205,10 @@
         self.assertEqual(b'null', response.body)
 
 
-class TestEvaluationPlainHandlerWithoutAuth(AsyncHTTPTestCase):
+class TestEvaluationPlaneHandlerWithoutAuth(AsyncHTTPTestCase):
     @classmethod
     def setUpClass(cls):
-        prefix = "__TestEvaluationPlainHandlerWithoutAuth_"
+        prefix = "__TestEvaluationPlaneHandlerWithoutAuth_"
 
         # create state.ini dir and file
         cls.state_dir = tempfile.mkdtemp(prefix=prefix)
@@ -285,4 +285,212 @@
                 )
             },
         )
-        self.assertEqual(400, response.code)
+        self.assertEqual(406, response.code)
+
+
+class TestEvaluationPlaneHandlerDisabledWithoutAuth(AsyncHTTPTestCase):
+    @classmethod
+    def setUpClass(cls):
+        prefix = "__TestEvaluationPlaneHandlerDisabledWithoutAuth_"
+
+        # create config file
+        cls.config_file = tempfile.NamedTemporaryFile(
+            mode="w+t", prefix=prefix, suffix=".conf", delete=False
+        )
+        cls.config_file.write(
+            "[TabPy]\n"
+            f"TABPY_EVALUATE_ENABLE = false"
+        )
+        cls.config_file.close()
+
+        cls.script = (
+            '{"data":{"_arg1":[2,3],"_arg2":[3,-1]},'
+            '"script":"res=[]\\nfor i in range(len(_arg1)):\\n  '
+            'res.append(_arg1[i] * _arg2[i])\\nreturn res"}'
+        )
+
+    @classmethod
+    def tearDownClass(cls):
+        os.remove(cls.config_file.name)
+
+    def get_app(self):
+        self.app = TabPyApp(self.config_file.name)
+        return self.app._create_tornado_web_app()
+
+    def test_evaluation_disabled_fails(self):
+        response = self.fetch(
+            "/evaluate",
+            method="POST",
+            body=self.script
+        )
+        self.assertEqual(404, response.code)
+
+
+class TestEvaluationPlaneHandlerDisabledWithAuth(AsyncHTTPTestCase):
+    @classmethod
+    def setUpClass(cls):
+        prefix = "__TestEvaluationPlaneHandlerDisabledWithAuth_"
+
+        # create password file
+        cls.pwd_file = tempfile.NamedTemporaryFile(
+            mode="w+t", prefix=prefix, suffix=".txt", delete=False
+        )
+        username = "username"
+        password = "password"
+        cls.pwd_file.write(f"{username} {hash_password(username, password)}\n")
+        cls.pwd_file.close()
+
+        # create state.ini dir and file
+        cls.state_dir = tempfile.mkdtemp(prefix=prefix)
+        cls.state_file = open(os.path.join(cls.state_dir, "state.ini"), "w+")
+        cls.state_file.write(
+            "[Service Info]\n"
+            "Name = TabPy Serve\n"
+            "Description = \n"
+            "Creation Time = 0\n"
+            "Access-Control-Allow-Origin = \n"
+            "Access-Control-Allow-Headers = \n"
+            "Access-Control-Allow-Methods = \n"
+            "\n"
+            "[Query Objects Service Versions]\n"
+            "\n"
+            "[Query Objects Docstrings]\n"
+            "\n"
+            "[Meta]\n"
+            "Revision Number = 1\n"
+        )
+        cls.state_file.close()
+
+        # create config file
+        cls.config_file = tempfile.NamedTemporaryFile(
+            mode="w+t", prefix=prefix, suffix=".conf", delete=False
+        )
+        cls.config_file.write(
+            "[TabPy]\n"
+            f"TABPY_PWD_FILE = {cls.pwd_file.name}\n"
+            f"TABPY_STATE_PATH = {cls.state_dir}\n"
+            f"TABPY_EVALUATE_ENABLE = false"
+        )
+        cls.config_file.close()
+
+        cls.script = (
+            '{"data":{"_arg1":[2,3],"_arg2":[3,-1]},'
+            '"script":"res=[]\\nfor i in range(len(_arg1)):\\n  '
+            'res.append(_arg1[i] * _arg2[i])\\nreturn res"}'
+        )
+
+    @classmethod
+    def tearDownClass(cls):
+        os.remove(cls.pwd_file.name)
+        os.remove(cls.state_file.name)
+        os.remove(cls.config_file.name)
+        os.rmdir(cls.state_dir)
+
+    def get_app(self):
+        self.app = TabPyApp(self.config_file.name)
+        return self.app._create_tornado_web_app()
+
+    def test_evaluation_disabled_fails_with_invalid_creds(self):
+        response = self.fetch(
+            "/evaluate",
+            method="POST",
+            body=self.script,
+            headers={
+                "Authorization": "Basic {}".format(
+                    
base64.b64encode("user:wrong_password".encode("utf-8")).decode(
+                        "utf-8"
+                    )
+                )
+            },
+        )
+        self.assertEqual(401, response.code)
+
+    def test_evaluation_disabled_fails_with_valid_creds(self):
+        response = self.fetch(
+            "/evaluate",
+            method="POST",
+            body=self.script,
+            headers={
+                "Authorization": "Basic {}".format(
+                    
base64.b64encode("username:password".encode("utf-8")).decode(
+                        "utf-8"
+                    )
+                )
+            },
+        )
+        self.assertEqual(404, response.code)
+
+
+class TestEvaluationPlaneHandlerEnabled(AsyncHTTPTestCase):
+    @classmethod
+    def setUpClass(cls):
+        prefix = "__TestEvaluationPlaneHandlerEnabled_"
+
+        # create config file
+        cls.config_file = tempfile.NamedTemporaryFile(
+            mode="w+t", prefix=prefix, suffix=".conf", delete=False
+        )
+        cls.config_file.write(
+            "[TabPy]\n"
+            f"TABPY_EVALUATE_ENABLE = true"
+        )
+        cls.config_file.close()
+
+        cls.script = (
+            '{"data":{"_arg1":[2,3],"_arg2":[3,-1]},'
+            '"script":"res=[]\\nfor i in range(len(_arg1)):\\n  '
+            'res.append(_arg1[i] * _arg2[i])\\nreturn res"}'
+        )
+
+    @classmethod
+    def tearDownClass(cls):
+        os.remove(cls.config_file.name)
+
+    def get_app(self):
+        self.app = TabPyApp(self.config_file.name)
+        return self.app._create_tornado_web_app()
+
+    def test_evaluation_enabled(self):
+        response = self.fetch(
+            "/evaluate",
+            method="POST",
+            body=self.script
+        )
+        self.assertEqual(200, response.code)
+
+
+class TestEvaluationPlaneHandlerDefault(AsyncHTTPTestCase):
+    @classmethod
+    def setUpClass(cls):
+        prefix = "__TestEvaluationPlaneHandlerDefault_"
+
+        # create config file
+        cls.config_file = tempfile.NamedTemporaryFile(
+            mode="w+t", prefix=prefix, suffix=".conf", delete=False
+        )
+        cls.config_file.write(
+            "[TabPy]"
+        )
+        cls.config_file.close()
+
+        cls.script = (
+            '{"data":{"_arg1":[2,3],"_arg2":[3,-1]},'
+            '"script":"res=[]\\nfor i in range(len(_arg1)):\\n  '
+            'res.append(_arg1[i] * _arg2[i])\\nreturn res"}'
+        )
+
+    @classmethod
+    def tearDownClass(cls):
+        os.remove(cls.config_file.name)
+
+    def get_app(self):
+        self.app = TabPyApp(self.config_file.name)
+        return self.app._create_tornado_web_app()
+
+    def test_evaluation_default(self):
+        response = self.fetch(
+            "/evaluate",
+            method="POST",
+            body=self.script
+        )
+        self.assertEqual(200, response.code)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/TabPy-2.3.1/tests/unit/server_tests/test_service_info_handler.py 
new/TabPy-2.5.0/tests/unit/server_tests/test_service_info_handler.py
--- old/TabPy-2.3.1/tests/unit/server_tests/test_service_info_handler.py        
2020-11-10 19:28:04.000000000 +0100
+++ new/TabPy-2.5.0/tests/unit/server_tests/test_service_info_handler.py        
2022-01-20 22:20:43.000000000 +0100
@@ -14,7 +14,7 @@
         "state_path": settings["state_file_path"],
         "server_version": settings[SettingsParameters.ServerVersion],
         "name": tabpy_state.name,
-        "versions": settings["versions"],
+        "versions": settings["versions"]
     }
 
 
@@ -100,7 +100,7 @@
         self.assertTrue("features" in v1)
         features = v1["features"]
         self.assertDictEqual(
-            {"authentication": {"methods": {"basic-auth": {}}, "required": 
True}},
+            {"authentication": {"methods": {"basic-auth": {}}, "required": 
True}, 'evaluate_enabled': True},
             features,
         )
 
@@ -126,7 +126,7 @@
         v1 = versions["v1"]
         self.assertTrue("features" in v1)
         features = v1["features"]
-        self.assertDictEqual({}, features)
+        self.assertDictEqual({'evaluate_enabled': True}, features)
 
     def 
test_given_server_with_no_auth_and_password_expect_correct_info_response(self):
         header = {
@@ -137,4 +137,4 @@
         }
 
         response = self.fetch("/info", headers=header)
-        self.assertEqual(response.code, 400)
+        self.assertEqual(response.code, 406)

Reply via email to