Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
13a1963
remove lowercase while parsing csv
bhuvneshdev Jan 4, 2023
644b265
Merge pull request #218 from tableau/bhuvnesh.singh/1486558
bhuvneshdev Jan 6, 2023
02edb28
Jac/user agent (#219)
jacalata Jan 6, 2023
6e48d62
Jac/logging (#224)
jacalata Feb 1, 2023
c261d76
Jac/filter spaces (#225)
jacalata Feb 2, 2023
9d1d40d
Jac/delete extract (#227)
jacalata Feb 17, 2023
c734a9e
Merge branch 'main' into development
jacalata Feb 17, 2023
6a2311c
Jac/readme updates (#235)
jacalata Mar 11, 2023
c46a8ca
Always log version (#234)
jacalata Mar 11, 2023
1361c92
Jac/content listing (#230)
jacalata Mar 11, 2023
80cb757
Jac/parse publish options (#236)
jacalata Mar 11, 2023
c2857e9
proxy settings (#241)
jacalata Mar 24, 2023
fc992e4
freeze tsc dependency (#248)
jacalata Apr 26, 2023
248aa85
add --token-file option (#243)
jacalata Apr 27, 2023
f8d22e5
Merge down changes from main (#258)
jacalata Jul 27, 2023
321622d
Merge branch 'main' into development
jacalata Jul 27, 2023
4741edb
Remove duplicated tests in merge
jacalata Jul 27, 2023
fa12da8
ignore errors from missing var files when in github
jacalata Jul 28, 2023
2e04907
fix log error on publish (#262)
jacalata Jul 28, 2023
d42e037
Merge branch 'main' into development
jacalata Feb 16, 2024
71d36c3
fix filepath handling in Get command (#277)
jacalata Feb 22, 2024
fa14810
Fix for "this application can't be opened" error on opening tabcmd.ap…
renoyjohnm May 3, 2024
60b9995
Remove argparse (#282)
fabaff May 6, 2024
4c5186d
Add all test assets, some test improvements (#290)
jacalata Jun 7, 2024
2567208
Ignore deprecation warning, with explanation in test file (#291)
jacalata Jun 12, 2024
f0aea21
Improvements while working on E2E tests (#293)
bcantoni Jun 12, 2024
8a42f75
Merge branch 'main' into development
jacalata Jun 13, 2024
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
35 changes: 33 additions & 2 deletions .github/workflows/package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,21 @@ jobs:
pyinstaller tabcmd-windows.spec --clean --noconfirm --distpath ./dist/windows
OUT_FILE_NAME: tabcmd.exe
ASSET_MIME: application/vnd.microsoft.portable-executable
- os: macos-13
TARGET: macos
CMD_BUILD: >
pyinstaller tabcmd-mac.spec --clean --noconfirm --distpath ./dist/macos/
BUNDLE_NAME: tabcmd.app
OUT_FILE_NAME: tabcmd.app
APP_BINARY_FILE_NAME: tabcmd
ASSET_MIME: application/zip
- os: macos-latest
TARGET: macos
CMD_BUILD: >
pyinstaller tabcmd-mac.spec --clean --noconfirm --distpath ./dist/macos
pyinstaller tabcmd-mac.spec --clean --noconfirm --distpath ./dist/macos/
BUNDLE_NAME: tabcmd_arm64.app
OUT_FILE_NAME: tabcmd.app
APP_BINARY_FILE_NAME: tabcmd
ASSET_MIME: application/zip
- os: ubuntu-latest
TARGET: ubuntu
Expand Down Expand Up @@ -64,9 +74,30 @@ jobs:
run: ${{matrix.CMD_BUILD}}

- name: Validate package for ${{matrix.TARGET}}
if: matrix.TARGET != 'macos'
run: ./dist/${{ matrix.TARGET }}/${{matrix.OUT_FILE_NAME}}

- uses: actions/upload-artifact@v4
- name: Validate package for Mac
if: matrix.TARGET == 'macos'
run: ./dist/${{ matrix.TARGET }}/${{ matrix.OUT_FILE_NAME }}/Contents/MacOS/${{ matrix.APP_BINARY_FILE_NAME }}

- name: Tar app bundle for Mac
if: matrix.TARGET == 'macos'
run: |
rm -f dist/${{ matrix.TARGET }}/${{ matrix.APP_BINARY_FILE_NAME }}
cd dist/${{ matrix.TARGET }}
tar -cvf ${{ matrix.BUNDLE_NAME }}.tar ${{ matrix.OUT_FILE_NAME }}

- name: Upload artifact
if: matrix.TARGET != 'macos'
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.OUT_FILE_NAME }}
path: ./dist/${{ matrix.TARGET }}/${{ matrix.OUT_FILE_NAME }}

- name: Upload artifact for Mac
if: matrix.TARGET == 'macos'
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.BUNDLE_NAME }}
path: ./dist/${{ matrix.TARGET }}/${{ matrix.BUNDLE_NAME }}.tar
20 changes: 8 additions & 12 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# general dev/ide files
*.log
*.vscode
*.csv
.idea
*.DS_Store

Expand All @@ -24,19 +23,20 @@ workon/
.coverage
pytest.xml

*.txt
# content
# todo probably want to add a workbook and ds in /res for getting started easily
*.pdf
*.png
*.twbx
*.hyper
*.twb
*.twbr
html
*.html
*.twbr
# *.twbx
# *.hyper
# *.twb
# *.twbr
# *.tdsx
**/credentials.py
*.txt
# exceptions
!tests/assets/

# doit
.doit.*
Expand All @@ -48,7 +48,3 @@ site-packages
tabcmd-dev
workon
test.junit.xml

# exceptions
!tests/assets/detailed_users.csv
est
Binary file removed World Indicators.tdsx
Binary file not shown.
Binary file removed WorldIndicators.tdsx
Binary file not shown.
6 changes: 3 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ packages = ["tabcmd"]
tabcmd = ["tabcmd.locales/**/*.mo"]
[tool.black]
line-length = 120
required-version = 22
target-version = ['py38', 'py39', 'py310', 'py311']
extend-exclude = '^/bin/*'
[tool.mypy]
Expand Down Expand Up @@ -40,7 +41,6 @@ classifiers = [
"Programming Language :: Python :: 3.11"
]
dependencies = [
'argparse',
"appdirs",
"doit",
"ftfy",
Expand All @@ -52,8 +52,8 @@ dependencies = [
"types-mock",
"types-requests",
"types-setuptools",
"tableauserverclient==0.25",
"urllib3>=1.24.3,<2.0",
"tableauserverclient==0.31",
"urllib3",
]
[project.optional-dependencies]
test = [
Expand Down
6 changes: 3 additions & 3 deletions tabcmd-mac.spec
Original file line number Diff line number Diff line change
Expand Up @@ -32,20 +32,20 @@ exe = EXE(
a.zipfiles,
a.datas,
[],
name='tabcmd.app',
name='tabcmd',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
runtime_tmpdir=None,
console=True,
codesign_identity=None,
version='program_metadata.txt',
version='program_metadata.txt'
)

app = BUNDLE(
exe,
name = 'tabcmd-app',
name = 'tabcmd.app',
icon='res/tabcmd.icns',
bundle_identifier = None,
)
32 changes: 16 additions & 16 deletions tabcmd/commands/datasources_and_workbooks/get_url_command.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import inspect
import os

import tableauserverclient as TSC
from tableauserverclient import ServerResponseError
Expand Down Expand Up @@ -80,7 +81,7 @@ def explain_expected_url(logger, url: str, command: str):
def get_file_type_from_filename(logger, url, file_name):
logger.debug("Choosing between {}, {}".format(file_name, url))
file_name = file_name or url
logger.debug(_("get.options.file") + ": {}".format(file_name))
logger.debug(_("get.options.file") + ": {}".format(file_name)) # Name to save the file as
type_of_file = GetUrl.get_file_extension(file_name)

if not type_of_file and file_name is not None:
Expand All @@ -98,25 +99,24 @@ def get_file_type_from_filename(logger, url, file_name):
Errors.exit_with_error(logger, _("tabcmd.get.extension.not_found").format(file_name))

@staticmethod
def get_file_extension(filename):
parts = filename.split(".")
if len(parts) < 2:
return None
extension = parts[1]
def get_file_extension(path):
path_segments = os.path.split(path)
filename = path_segments[-1]
filename_segments = filename.split(".")
extension = filename_segments[-1]
extension = GetUrl.strip_query_params(extension)
return extension

@staticmethod
def strip_query_params(filename):
if filename.find("?") > 0:
filename = filename.split("?")[0]
return filename
if "?" in filename:
return filename.split("?")[0]
else:
return filename

@staticmethod
def get_name_without_possible_extension(filename):
if filename.find(".") > 0:
filename = filename.split(".")[0]
return filename
return filename.split(".")[0]

@staticmethod
def get_resource_name(url: str, logger): # workbooks/wb-name" -> "wb-name", datasource/ds-name -> ds-name
Expand Down Expand Up @@ -181,7 +181,7 @@ def generate_pdf(logger, server, args, view_url):
filename = GetUrl.filename_from_args(args.filename, view_item.name, "pdf")
DatasourcesAndWorkbooks.save_to_file(logger, view_item.pdf, filename)
except Exception as e:
Errors.exit_with_error(logger, e)
Errors.exit_with_error(logger, exception=e)

@staticmethod
def generate_png(logger, server, args, view_url):
Expand All @@ -195,7 +195,7 @@ def generate_png(logger, server, args, view_url):
filename = GetUrl.filename_from_args(args.filename, view_item.name, "png")
DatasourcesAndWorkbooks.save_to_file(logger, view_item.image, filename)
except Exception as e:
Errors.exit_with_error(logger, e)
Errors.exit_with_error(logger, exception=e)

@staticmethod
def generate_csv(logger, server, args, view_url):
Expand Down Expand Up @@ -226,7 +226,7 @@ def generate_twb(logger, server, args, file_extension, url):
server.workbooks.download(target_workbook.id, filepath=file_name_with_path, no_extract=False)
logger.info(_("export.success").format(target_workbook.name, file_name_with_ext))
except Exception as e:
Errors.exit_with_error(logger, e)
Errors.exit_with_error(logger, exception=e)

@staticmethod
def generate_tds(logger, server, args, file_extension):
Expand All @@ -243,4 +243,4 @@ def generate_tds(logger, server, args, file_extension):
server.datasources.download(target_datasource.id, filepath=file_name_with_path, no_extract=False)
logger.info(_("export.success").format(target_datasource.name, file_name_with_ext))
except Exception as e:
Errors.exit_with_error(logger, e)
Errors.exit_with_error(logger, exception=e)
24 changes: 11 additions & 13 deletions tabcmd/commands/datasources_and_workbooks/publish_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,19 +40,17 @@ def run_command(args):
session = Session()
server = session.create_session(args, logger)

if args.project_name:
try:
dest_project = Server.get_project_by_name_and_parent_path(
logger, server, args.project_name, args.parent_project_path
)
project_id = dest_project.id
except Exception as exc:
logger.error(exc.__str__())
Errors.exit_with_error(logger, _("publish.errors.server_resource_not_found"), exc)
else:
project_id = ""
args.project_name = "default"
if not args.project_name:
args.project_name = "Default"
args.parent_project_path = ""
try:
dest_project = Server.get_project_by_name_and_parent_path(
logger, server, args.project_name, args.parent_project_path
)
project_id = dest_project.id
except Exception as exc:
logger.error(exc.__str__())
Errors.exit_with_error(logger, _("publish.errors.server_resource_not_found"), exc)

publish_mode = PublishCommand.get_publish_mode(args, logger)

Expand Down Expand Up @@ -82,7 +80,7 @@ def run_command(args):
# args.thumbnail_group,
connection_credentials=creds,
as_job=False,
skip_connection_check=False,
skip_connection_check=args.skip_connection_check,
)
except Exception as e:
Errors.exit_with_error(logger, exception=e)
Expand Down
1 change: 0 additions & 1 deletion tabcmd/commands/site/list_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ class ListCommand(Server):
"tabcmd_content_none": "No content found.",
}


name: str = "list"
description: str = "List content items of a specified type"

Expand Down
5 changes: 5 additions & 0 deletions tabcmd/execution/global_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,11 @@ def set_publish_args(parser):
help="Encrypt extracts in the workbook, datasource, or extract being published to the server. "
"[N/a on Tableau Cloud: extract encryption is controlled by Site Admin]",
)
parser.add_argument(
"--skip-connection-check",
action="store_true",
help="Skip connection check: do not validate the workbook/datasource connection during publishing",
)

# These two only apply for a workbook, not a datasource
thumbnails = parser.add_mutually_exclusive_group()
Expand Down
6 changes: 6 additions & 0 deletions tabcmd/execution/localize.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,13 @@ def _load_language(current_locale, domain, logger):


def _get_default_locale():
# c:\dev\tabcmd\tabcmd\execution\localize.py:85: DeprecationWarning 'locale.getdefaultlocale' is deprecated
# see test_localize for details
import logging

logging.captureWarnings(True)
current_locale, encoding = locale.getdefaultlocale()
logging.captureWarnings(False)
current_locale = _validate_lang(current_locale)
return current_locale

Expand Down
6 changes: 4 additions & 2 deletions tabcmd/execution/tabcmd_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,16 @@ def run(parser, user_input=None):
logger.debug(namespace)
if namespace.language:
set_client_locale(namespace.language, logger)

try:
func = namespace.func
# if a subcommand was identified, call the function assigned to it
# this is the functional equivalent of the call by reflection in the previous structure
# https://stackoverflow.com/questions/49038616/argparse-subparsers-with-functions
namespace.func.run_command(namespace)
except AttributeError:
parser.error("No command identified or too few arguments")
except Exception as e:
# todo: use log_stack here for better presentation
# todo: use log_stack here for better presentation?
logger.exception(e)
# if no command was given, argparse will just not create the attribute
sys.exit(2)
Expand Down
Loading