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
21 changes: 7 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ e.g
* `tabcmd help`

###or
## Install on the command line (requires Python 3.7+)
## Install on the command line

(Note: this requires Python 3.7+. Generally we will actively support versions of Python that are still in security support).

```shell
pip install tabcmd
Expand Down Expand Up @@ -83,21 +85,12 @@ see the user documentation at https://tableau.github.io/tabcmd/


## Release Notes
Version 2.0 is the first version of tabcmd built in python.
Version 2 is the first version of tabcmd built in python.
It is specifically targeted to support users of Tableau Online, who are required to have MFA enabled.
(MFA support is not available in tabcmd 2022.2). It does not yet fully replace the existing tabcmd client.\
**Known gaps**
- handling custom views in get/export commands
- several commands that can only be run by a Server Admin:
- editdomain / listdomains
- initialuser
- reset_openid_sub
- runschedule
- set
- syncgroup
- upgradethumbnails
- validateidpmetadata
(MFA support is not available in the tabcmd program that ships with Tableau Server).

Version 2 does not yet fully replace the existing tabcmd client, in particular it **does not support most server admin actions**.
For known gaps in supported functionality, see the latest [release notes](https://github.com/tableau/tabcmd/releases)

## About

Expand Down
98 changes: 55 additions & 43 deletions contributing.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,35 @@

# For developers
* [Install tabcmd](#install-tabcmd)
* [Run tabcmd](#run-tabcmd)
* [Development commands](#development-commands)
* [Contributing](#contributing)
* [To add a new command](#to-add-a-new-command)
* [Why Python\?](#why-python)
* [Project Structure](#project-structure)

* [Development](#development)
* [Dev scripts](#dev-scripts)
* [Why Python\?](#why-python)
* [Project structure](#project-structure)
* [To add a new command](#to-add-a-new-command)
* [Localization](#localization)
* [Releases](#releases)
* [Versioning](#versioning)
* [Packaging](#packaging)


These instructions are for people who want to download the code and edit it directly. If you are interested in tabcmd but not the code, see [here](Readme.md).
####To work with tabcmd, you need to have **Python 3.7+** installed.


## Install tabcmd
These instructions are only necessary if you want to download the code and run it directly. If you are interested in tabcmd but not the code, see [here](Readme.md).
####To work with tabcmd, you need to have **Python 3.7+** installed.
## Contributing

###
Code contributions and improvements by the community are welcomed!

See the LICENSE file for current open-source licensing and use information.

Before we can accept pull requests from contributors, we require a signed [Contributor License Agreement (CLA)](http://tableau.github.io/contributing.html).


## Development

To work on the tabcmd code, use these scripts. On Windows,
### Dev scripts
To work on the tabcmd code, use these scripts.
_(note that running mypy and black is required for code being submitted to the repo)_

- build
Expand All @@ -38,42 +47,14 @@ _(note that running mypy and black is required for code being submitted to the r
- do test coverage calculation (https://coverage.readthedocs.io/en/6.3.2)
> bin/coverage.sh

- To trigger publishing to pypi tag a commit on main with 'pypi'. Versioning is done with
- setuptools_scm so it will be a x.y.dev0 pre-release version unless you first tag the
- commit with a new version tag. e.g
> git tag -d pypi && git push --delete origin pypi
> git tag v2.0.4 && git tag pypi && git push --tags

# Missing step: a job that is triggered by pypi tag and creates a release
# Missing trigger: when pypi-release is done, begin the app smoke test

- packaging to an exe is done with pyinstaller. You can only build an executable for
- the platform you build on.
- On github this job is triggered by creating a release (or manually)
> doit version <-- produce a current version and metadata file to package
> pyinstaller tabcmd-windows.spec .... # see package.yml for OS-specific arguments

Packaging produces dist/tabcmd.exe (or equivalent).
- Run the package
> dist/tabcmd/tabcmd.exe --help


## Why Python?
### Why Python?

* Cross-platform
* Build on our existing Python [Tableau Server Client](https://github.com/tableau/server-client-python/)


## Contributing

Code contributions and improvements by the community are welcomed!

See the LICENSE file for current open-source licensing and use information.

Before we can accept pull requests from contributors, we require a signed [Contributor License Agreement (CLA)](http://tableau.github.io/contributing.html).


## Project structure
### Project structure
The core design principles for this app are
- it must provide the functionality of the instance of tabcmd, with drop-in replacement CLI options
- it should be able to call [tsc](https://github.com/tableau/server-client-python/) for all server actions
Expand All @@ -84,12 +65,43 @@ The core design principles for this app are
3. the 'commands' module contains the logic required to translate the tabcmd CLI interface into calls to tsc. This is completely dissociated from the parsers, and could theoretically be called from a completely different interface.
4. The 'execution' module is the core logic. TabcmdController gets an argparse parser, then attaches all the defined parsers to it and associates one command with each parser.

## To add a new command
### To add a new command
0. choose the single word that will be used as your command. Let's call this one `dream`
1. add parsers/dream_parser.py, and use methods from parent_parser to define the arguments
2. add commands/dreams/dream_command.py. It must have a method run_command.py(args) and the args object must contain all information needed from the user.
3. in map_of_parsers.py, add an entry for your new parser, like "dreams": DreamParser.dream_parser
4. in map_of_commands.py, add an entry for your new command, like "dream": ("dream", DreamCommand, "Think about picnics"),"
5. add tests!
5. add tests!

### Localization

Strings are stored in /tabcmd/locales/[language]/*.properties by id and referred to in code as
> string = _("string.id")

For runtime execution these files must be converted to .mo via .po
> doit mo


## Releases
To trigger publishing to pypi tag a commit on main with 'pypi'.
When pypi-release is done, begin the app smoke test action.

### Versioning
Versioning is done with setuptools_scm and based on git tags.
It will be a x.y.dev0 pre-release version except for commits with a new version tag. e.g
> git tag v2.0.4 && git push --tags

A new tag is created with the name of each release on github.

### Packaging
Before packaging, we produce a current metadata file to include in the bundle
> doit version

Packaging is done with pyinstaller, which will build an executable for the platform it runs on.
A github action runs on Mac, Windows and Linux to generate each executable.

> pyinstaller tabcmd-windows.spec ....

Packaging produces executables in the dist folder. To run:
> dist/tabcmd/tabcmd.exe --help

10 changes: 6 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ packages = ["tabcmd"]
tabcmd = ["tabcmd.locales/**/*.mo"]
[tool.black]
line-length = 120
target-version = ['py37', 'py38', 'py39', 'py310']
target-version = ['py37', 'py38', 'py39', 'py310', 'py311']
extend-exclude = '^/bin/*'
[tool.mypy]
disable_error_code = [
Expand All @@ -30,14 +30,16 @@ description="A command line client for working with Tableau Server."
authors = [{name="Tableau", email="github@tableau.com"}]
license = {file = "LICENSE"}
readme = "README.md"
requires-python = ">=3.7"
requires-python = ">=3.7" # https://devguide.python.org/versions/
classifiers = [
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10"
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12"
]
dependencies = [
'argparse',
Expand All @@ -56,7 +58,7 @@ dependencies = [
]
[project.optional-dependencies]
test = [
"black",
"black>=22,<23",
"mock",
"mypy",
"pytest>=7.0",
Expand Down
5 changes: 2 additions & 3 deletions tabcmd/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@
try:
from tabcmd.tabcmd import main
except ImportError as e:
print(sys.stderr, e)
print(sys.stderr, "Tabcmd needs to be run as a module, it cannot be run as a script")
print(sys.stderr, "Try running python -m tabcmd")
print("Exception thrown running program: `{}`, `{}`".format(e, e.__context__), file=sys.stderr)
print("[Possible cause: Tabcmd needs to be run as a module, try running `python -m tabcmd`]", file=sys.stderr)
sys.exit(1)

if __name__ == "__main__":
Expand Down
Loading