Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions .github/workflows/check-coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ on:
pull_request:
branches:
- development
workflow_dispatch:

jobs:
build:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest]
python-version: ['3']
python-version: ['3.12']

runs-on: ${{ matrix.os }}

Expand All @@ -38,6 +39,10 @@ jobs:
- name: Generate coverage report
run: pytest --junitxml=pytest.xml --cov=tabcmd tests/ | tee pytest-coverage.txt

# trying another coverage reporter for PRs/badges
- name: Coveralls
uses: coverallsapp/github-action@v2

- name: Comment on pull request with coverage
uses: MishaKav/pytest-coverage-comment@main
with:
Expand All @@ -46,10 +51,6 @@ jobs:
# Error: The head commit for this pull_request event is not ahead of the base commit.
# Please submit an issue on this action's GitHub repo
# report-only-changed-files: true

# TODO update badge on readme:
# generate badge with https://pypi.org/project/coverage-badge/
# display it with https://github.com/Schneegans/dynamic-badges-action


# TODO track docstring coverage
# https://github.com/marketplace/actions/python-interrogate-check
2 changes: 1 addition & 1 deletion .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ jobs:
# 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.

# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/generate-metadata.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.9'
python-version: '3.12'

- name: Install App and Extras
run: |
Expand Down
5 changes: 2 additions & 3 deletions .github/workflows/package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ jobs:

- uses: actions/setup-python@v5
with:
python-version: 3.9
python-version: 3.12

- name: Install dependencies and build
run: |
Expand Down Expand Up @@ -94,7 +94,7 @@ jobs:
cd dist/${{ matrix.TARGET }}
tar -cvf ${{ matrix.UPLOAD_FILE_NAME }} ${{ matrix.OUT_FILE_NAME }}


- name: Upload binaries to release for ${{ matrix.TARGET }}
uses: svenstaro/upload-release-action@v2
with:
Expand All @@ -104,4 +104,3 @@ jobs:
tag: ${{ github.ref_name }}
overwrite: true
promote: true

3 changes: 1 addition & 2 deletions .github/workflows/publish-pypi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
fetch-depth: 0
- uses: actions/setup-python@v5
with:
python-version: 3.9
python-version: 3.12
- name: Build dist files
run: |
python --version
Expand All @@ -41,4 +41,3 @@ jobs:
uses: pypa/gh-action-pypi-publish@release/v1 # license BSD-2
with:
password: ${{ secrets.PYPI_API_TOKEN }}

2 changes: 1 addition & 1 deletion .github/workflows/python-app.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: ['3.x']
python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']

runs-on: ${{ matrix.os }}

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/run-e2-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
fail-fast: true
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: ['3.9', '3.10', '3.11', '3.12', '3']
python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']

runs-on: ${{ matrix.os }}

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
fail-fast: true
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: ['3.9', '3.10', '3.11', '3.12', '3']
python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']

runs-on: ${{ matrix.os }}

Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Tabcmd

[![Tableau Supported](https://img.shields.io/badge/Support%20Level-Tableau%20Supported-53bd92.svg)](https://www.tableau.com/support-levels-it-and-developer-tools)

[![Code coverage]([https://coveralls.io/repos/tableau/tabcmd/badge.png])(https://github.com/tableau/tabcmd/actions)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
[![Python tests](https://github.com/tableau/tabcmd/actions/workflows/run-tests.yml/badge.svg)](https://github.com/tableau/tabcmd/actions/workflows/run-tests.yml)
[![Pypi smoke tests](https://github.com/tableau/tabcmd/actions/workflows/python-app.yml/badge.svg)](https://github.com/tableau/tabcmd/actions/workflows/python-app.yml)
Expand Down
11 changes: 6 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ tabcmd = ["tabcmd.locales/**/*.mo"]
[tool.black]
line-length = 120
required-version = 22
target-version = ['py38', 'py39', 'py310', 'py311']
target-version = ['py39', 'py310', 'py311']
extend-exclude = '^/bin/*'
[tool.mypy]
disable_error_code = [
Expand All @@ -31,14 +31,15 @@ description="A command line client for working with Tableau Server."
authors = [{name="Tableau", email="github@tableau.com"}]
license = {file = "LICENSE"}
readme = "res/README.md"
requires-python = ">=3.7" # https://devguide.python.org/versions/
requires-python = ">=3.9" # https://devguide.python.org/versions/
classifiers = [
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11"
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13"
]
dependencies = [
"appdirs",
Expand All @@ -52,7 +53,7 @@ dependencies = [
"types-mock",
"types-requests",
"types-setuptools",
"tableauserverclient==0.35",
"tableauserverclient==0.37",
"urllib3",
]
[project.optional-dependencies]
Expand Down
15 changes: 14 additions & 1 deletion tabcmd/commands/auth/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import tableauserverclient as TSC
import urllib3
from urllib3.exceptions import InsecureRequestWarning
from urllib.parse import urlparse, urlunparse

from tabcmd.version import version
from tabcmd.commands.constants import Errors
Expand Down Expand Up @@ -61,7 +62,8 @@ def _update_session_data(self, args):
# self.command = args.???
self.username = args.username or self.username or ""
self.username = self.username.lower()
self.server_url = args.server or self.server_url or "http://localhost"
server_base_url = self._get_server_base_url(args.server) if args.server else None
self.server_url = server_base_url or self.server_url or "http://localhost"
self.server_url = self.server_url.lower()
if args.server is not None:
self.site_name = None
Expand Down Expand Up @@ -481,3 +483,14 @@ def _remove_json(self):
message = "Error clearing session data from {}: check and remove manually".format(file_path)
self.logger.error(message)
self.logger.error(e)

def _get_server_base_url(self, url: str):
try:
parsed = urlparse(url)
scheme = parsed.scheme or "http"

# If netloc is empty, treat path as netloc and discard any extra path
netloc = parsed.netloc or parsed.path.split("/")[0] # Keep only the domain
return urlunparse((scheme, netloc, "", "", "", ""))
except Exception as e:
Errors.exit_with_error(self.logger, exception=e)
Original file line number Diff line number Diff line change
Expand Up @@ -125,14 +125,18 @@ def apply_options_in_url(logger, request_options: TSC.RequestOptions, value: str
request_options.max_age = 0 # type: ignore
logger.debug("Set max age to {} from {}".format((TSC.ImageRequestOptions(request_options)).max_age, value))
elif ":size" == setting_name:
# this is only used by get as png
try:
height, width = setting_val.split(",")
(TSC.ImageRequestOptions(request_options)).viz_height = int(height)
(TSC.ImageRequestOptions(request_options)).viz_width = int(width)
except Exception as oops:
logger.warn("Unable to read image size options '{}', skipping".format(setting_val))
logger.warn(oops)
if isinstance(request_options, (TSC.ImageRequestOptions, TSC.PDFRequestOptions)):
try:
height, width = setting_val.split(",")
request_options.viz_height = int(height)
request_options.viz_width = int(width)
except Exception as oops:
logger.warn("Unable to read image size options '{}', skipping".format(setting_val))
logger.warn(oops)
else:
logger.debug(
"Request options are not of type ImageRequestOptions or PDFRequestOptions, skipping size setting"
)
else:
logger.debug("Parameter[s] not recognized: {}".format(value))

Expand All @@ -147,8 +151,10 @@ def apply_png_options(logger, request_options: TSC.ImageRequestOptions, args):
request_options.viz_height = int(args.height)
if args.width:
request_options.viz_width = int(args.width)
# Always request high-res images
request_options.image_resolution = "high"
if args.resolution and args.resolution != TSC.ImageRequestOptions.Resolution.High.lower():
request_options.image_resolution = None
else:
request_options.image_resolution = TSC.ImageRequestOptions.Resolution.High.lower()

@staticmethod
def apply_pdf_options(logger, request_options: TSC.PDFRequestOptions, args):
Expand Down
15 changes: 11 additions & 4 deletions tabcmd/commands/datasources_and_workbooks/export_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
from .datasources_workbooks_views_url_parser import DatasourcesWorkbooksAndViewsUrlParser

pagesize = TSC.PDFRequestOptions.PageType # type alias for brevity
pageorientation = TSC.PDFRequestOptions.Orientation
imageresolution = TSC.ImageRequestOptions.Resolution
ImageResolutionStandard = "standard"


class ExportCommand(DatasourcesAndWorkbooks):
Expand All @@ -29,7 +32,7 @@ def define_args(export_parser):

group.add_argument(
"--pagelayout",
choices=["landscape", "portrait"],
choices=[pageorientation.Landscape, pageorientation.Portrait],
type=str.lower,
default=None,
help="page orientation (landscape or portrait) of the exported PDF",
Expand Down Expand Up @@ -57,16 +60,20 @@ def define_args(export_parser):
help="Set the page size of the exported PDF",
)

group.add_argument(
"--width", default=800, help="[Not Yet Implemented] Set the width of the image in pixels. Default is 800 px"
)
group.add_argument("--width", default=800, help=_("export.options.width"))
group.add_argument("--filename", "-f", help="filename to store the exported data")
group.add_argument("--height", default=600, help=_("export.options.height"))
group.add_argument(
"--filter",
metavar="COLUMN=VALUE",
help="Data filter to apply to the view",
)
group.add_argument(
"--resolution",
choices=[imageresolution.High, ImageResolutionStandard],
type=str.lower,
help=_("export.options.resolution"),
)

"""
Command to Export a view_name or workbook from Tableau Server and save
Expand Down
8 changes: 3 additions & 5 deletions tabcmd/commands/extracts/refresh_extracts_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,15 @@ def run_command(args):
if args.addcalculations or args.removecalculations:
logger.warning("Add/Remove Calculations tasks are not supported.")

# docs: the REST method always runs a full refresh even if the refresh type is set to incremental.
if args.incremental: # docs: run the incremental refresh
logger.warn("Incremental refresh is not yet available through the new tabcmd")
incremental_refresh = True if args.incremental else False

try:
item = Extracts.get_wb_or_ds_for_extracts(args, logger, server)
if args.datasource:
logger.info(_("refreshextracts.status_refreshed").format(_("content_type.datasource"), args.datasource))
job: TSC.JobItem = server.datasources.refresh(item.id)
job: TSC.JobItem = server.datasources.refresh(item.id, incremental_refresh)
else:
job: TSC.JobItem = server.workbooks.refresh(item.id)
job: TSC.JobItem = server.workbooks.refresh(item.id, incremental_refresh)
logger.info(_("refreshextracts.status_refreshed").format(_("content_type.workbook"), args.workbook))

except Exception as e:
Expand Down
1 change: 1 addition & 0 deletions tabcmd/locales/de/tabcmd_messages_de.properties
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ export.options.pagelayout=Legt die Seitenausrichtung der exportierten PDF-Datei
export.options.pagesize=Legt die Seitengröße der exportierten PDF-Datei fest. Zulässige Werte: {0} (Standard: „{1}“)
export.options.pdf=Daten im PDF-Format exportieren
export.options.png=Daten im PNG-Format exportieren
export.options.resolution=Set the value to high to ensure maximum pixel density
export.options.width=Legt die Breite fest. Muss ein Ganzzahlwert (Standard: 800 Pixel) sein
export.short_description=Daten oder Bild einer Ansicht vom Server exportieren
export.status=„{0}“ wird vom Server abgerufen...
Expand Down
1 change: 1 addition & 0 deletions tabcmd/locales/en/tabcmd_messages_en.properties
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ export.options.pagelayout=Sets the page orientation of the exported PDF. Legal v
export.options.pagesize=Sets the page size of the exported PDF. Legal values: {0} (default: ''{1}'')
export.options.pdf=Export data in PDF format
export.options.png=Export data in PNG format
export.options.resolution=Set the value to high to ensure maximum pixel density
export.options.width=Sets the width. Must be an integer value (default: 800 pixels)
export.short_description=Export the data or image of a view from the server
export.status=Requesting ''{0}'' from the server...
Expand Down
1 change: 1 addition & 0 deletions tabcmd/locales/es/tabcmd_messages_es.properties
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ export.options.pagelayout=Configura la orientación de páginas del PDF exportad
export.options.pagesize=Configura el tamaño de página del PDF exportado. Valores legales: {0} (valor predeterminado: “{1}”)
export.options.pdf=Exportar datos en formato PDF
export.options.png=Exportar datos en formato PNG
export.options.resolution=Set the value to high to ensure maximum pixel density
export.options.width=Configura el ancho. Debe ser un valor entero (valor predeterminado: 800 píxeles)
export.short_description=Exportar los datos o la imagen de una vista del servidor
export.status=Solicitando “{0}” al servidor...
Expand Down
1 change: 1 addition & 0 deletions tabcmd/locales/fr/tabcmd_messages_fr.properties
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ export.options.pagelayout=Définit l’orientation de la page du PDF exporté. V
export.options.pagesize=Définit la taille de page du PDF exporté. Valeurs admises : {0} (“{1}” par défaut).
export.options.pdf=Exporter les données au format PDF
export.options.png=Exporter les données au format PNG
export.options.resolution=Set the value to high to ensure maximum pixel density
export.options.width=Définit la largeur. Doit être un nombre entier (800 pixels par défaut)
export.short_description=Exporter les données ou une image d’une vue depuis le serveur
export.status=Requête de “{0}” en provenance du serveur...
Expand Down
1 change: 1 addition & 0 deletions tabcmd/locales/ga/tabcmd_messages_ga.properties
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ export.options.pagelayout=f683-表:Sets the page orientation of the exported PDF
export.options.pagesize=70c0-表:Sets the page size of the exported PDF. Legal values: {0} (default: ‘{1}’)|桜
export.options.pdf=3ecf-表:Export data in PDF format|桜
export.options.png=9e8c-表:Export data in PNG format|桜
export.options.resolution=Set the value to high to ensure maximum pixel density
export.options.width=687b-表:Sets the width. Must be an integer value (default: 800 pixels)|桜
export.short_description=3b4e-表:Export the data or image of a view from the server|桜
export.status=e524-表:Requesting ‘{0}’ from the server...|桜
Expand Down
1 change: 1 addition & 0 deletions tabcmd/locales/it/tabcmd_messages_it.properties
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ export.options.pagelayout=Imposta l’orientamento della pagina del PDF esportat
export.options.pagesize=Imposta le dimensioni della pagina del PDF esportato. Valori consentiti: {0} (predefiniti: “{1}”)
export.options.pdf=Esporta i dati in formato PDF
export.options.png=Esporta i dati in formato PNG
export.options.resolution=Set the value to high to ensure maximum pixel density
export.options.width=Imposta la profondità. Deve essere un valore intero (predefinito: 800 pixel)
export.short_description=Esportare i dati o l’immagine di una vista dal server
export.status=Richiesta di “{0}” dal server in corso...
Expand Down
1 change: 1 addition & 0 deletions tabcmd/locales/ja/tabcmd_messages_ja.properties
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ export.options.pagelayout=エクスポートされた PDF のページの方向
export.options.pagesize=エクスポートされた PDF のページ サイズを設定します。有効な値: {0} (既定: 「{1}」)
export.options.pdf=PDF 形式でデータをエクスポート
export.options.png=PNG 形式でデータをエクスポート
export.options.resolution=Set the value to high to ensure maximum pixel density
export.options.width=幅を設定します。整数値であることが必要です (既定: 800 ピクセル)
export.short_description=サーバーから、ビューのデータまたはイメージをエクスポート
export.status=サーバーから 「{0}」 を要求しています...
Expand Down
1 change: 1 addition & 0 deletions tabcmd/locales/ko/tabcmd_messages_ko.properties
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ export.options.pagelayout=내보낸 PDF의 페이지 방향을 설정합니다.
export.options.pagesize=내보낸 PDF의 페이지 크기를 설정합니다. 사용할 수 있는 값: {0}(기본값: ’{1}’)
export.options.pdf=PDF 형식으로 데이터 내보내기
export.options.png=PNG 형식으로 데이터 내보내기
export.options.resolution=Set the value to high to ensure maximum pixel density
export.options.width=너비를 설정합니다. 정수 값이어야 합니다(기본값: 800픽셀)
export.short_description=서버에서 뷰의 이미지 또는 데이터 내보내기
export.status=서버에서 ’{0}’을(를) 요청하는 중...
Expand Down
1 change: 1 addition & 0 deletions tabcmd/locales/pt/tabcmd_messages_pt.properties
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ export.options.pagelayout=Define a orientação da página do PDF exportado. Val
export.options.pagesize=Define o tamanho da página do PDF exportado. Valores legais: {0} (padrão: “{1}”)
export.options.pdf=Exporte dados em formato PDF
export.options.png=Exporte dados em formato PNG
export.options.resolution=Set the value to high to ensure maximum pixel density
export.options.width=Define a largura. Deve ser um valor integral (padrão: 800 pixels)
export.short_description=Exporte os dados ou imagem de uma exibição do servidor
export.status=Solicitando “{0}” do servidor...
Expand Down
1 change: 1 addition & 0 deletions tabcmd/locales/sv/tabcmd_messages_sv.properties
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ export.options.pagelayout=Ställer in sidorienteringen för den exporterade PDF-
export.options.pagesize=Ställer in sidstorleken för den exporterade PDF-filen. Giltiga värden: {0} (standard: ”{1}”)
export.options.pdf=Exportera data i PDF-format
export.options.png=Exportera data i PNG-format
export.options.resolution=Set the value to high to ensure maximum pixel density
export.options.width=Ställer in bredden. Måste vara ett heltalsvärde (standard: 800 bildpunkter)
export.short_description=Exportera en vys data eller avbildning från servern
export.status=Begär ”{0}” från servern ...
Expand Down
1 change: 1 addition & 0 deletions tabcmd/locales/zh/tabcmd_messages_zh.properties
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ export.options.pagelayout=设置导出的 PDF 的页面方向。合法值: {0}
export.options.pagesize=设置导出的 PDF 的页面大小。合法值: {0} (默认值: “{1}”)
export.options.pdf=将数据导出为 PDF 格式
export.options.png=将数据导出为 PNG 格式
export.options.resolution=Set the value to high to ensure maximum pixel density
export.options.width=设置宽度。必须为整数值(默认值: 800 个像素)
export.short_description=从服务器中导出数据或视图的图像
export.status=正向服务器请求 “{0}”...
Expand Down
Loading