Skip to content

Latest commit

 

History

History
167 lines (115 loc) · 7.06 KB

contributing.md

File metadata and controls

167 lines (115 loc) · 7.06 KB

For developers

Install Tabcmd

Note

These instructions are for people who want to work with the python code behind tabcmd. If you are interested in tabcmd but not the code, see here.

####To work with tabcmd, you need to have Python 3.8+ installed. To propose changes, you must have a Github account.

To make changes to tabcmd code

Fork the tabcmd repo and create a branch off the development branch, not the default branch (named main) (See Github Docs)

As a library that you can use in another application:

To install the current release:

pip install tabcmd

Or install the current work-in-progress version from Git
Only do this if you know you want the development version, no guarantee that we won't break APIs during development

pip install git+https://github.com/tableau/tabcmd.git@development

Tip

If you want to switch back to the non-development version, you need to run the following command before installing the stable version:

pip uninstall tabcmd

Software design

Why Python?

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 for all server actions
  • architecture is as simple as possible
  1. tabcmd.py exists only as a module entry point that calls TabCmdController.
  2. the 'parsers' module contains only argument and option definitions, no logic.
  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

  1. choose the single word that will be used as your command. Let's call this one dream
  2. add parsers/dream_parser.py, and use methods from parent_parser to define the arguments
  3. 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.
  4. in map_of_parsers.py, add an entry for your new parser, like "dreams": DreamParser.dream_parser
  5. in map_of_commands.py, add an entry for your new command, like "dream": ("dream", DreamCommand, "Think about picnics"),"
  6. add tests!

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).

Developing

To work on the tabcmd code, use these scripts. (note that running mypy and black with no errors is required before code will be merged into the repo)

  • build and run

pip install build python setup.py build python -m tabcmd.py [command_name] [--flags]

  • run tests

pytest

  • run tests against a live server

python -m tabcmd login {your server info here} pytest -q tests\e2e\online_tests.py -r pfE

black .

  • check types

mypy tabcmd tests

bin/coverage.sh

Packaging

Note

You can only build an executable for the platform you are running pyinstaller on. The spec for each platform is stored in tabcmd-platform.spec and the exact build commands for each platform can be checked in our packaging script.

e.g for Windows

pyinstaller tabcmd-windows.spec --clean --distpath .\dist\windows

produces dist\windows\tabcmd.exe To run the newly created executable, from a console window in the same directory as the file tabcmd.py:

dist\windows\tabcmd.exe --help dist\windows\tabcmd.exe publish --country FR --language FR cookie.twbx

To investigate what's packaged in the executable, use https://pyinstxtractor-web.netlify.app/

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 from .properties -> .po -> .mo files. These .mo files will be bundled in the the package by pyinstaller. The entire conversion action is done by a .doit script:

doit properties po mo You can also check that there are no malformed/forgotten message keys in the code with doit strings

Versioning

Versioning is done with setuptools_scm and based on git tags. The version number will be x.y.dev0.dirty except for commits with a new version tag. This is pulled from the git state, and to get a clean version like "v2.1.0", you must be on a commit with the tag "v2.1.0" (Creating a Github release also creates a tag on the selected branch.) The version reflected in the executable (tabcmd -v) is stored in a metadata file created by a .doit script:

doit version

Release process

  1. Create a new Github project release manually: https://docs.github.com/en/repositories/releasing-projects-on-github/about-releases

    • include a useful list of changes since the last release
    • include a clear list of remaining non-server-admin functional gaps
  2. This will trigger our github packaging action to run on 3 different OSs.

    • write an updated metadata file with the correct version number.
    • build the python wheel
    • run pyinstaller to create executables
    • save the executable as an artifact on that job.
  3. Find the artifacts created by this job and manually copy them to the new release.

  • manually download. They will all be returned as zips
  • unzip the windows.exe and mac[64].app.tar files and upload those
  • do not unzip the linux app, github doesn't like it. upload as tabcmd.zip (Pay attention to what the file type is, github also sends it as a zip if you download with curl etc. TODO: automate workflow with a github action)
  1. To trigger publishing to pypi run the manual workflow on main with 'pypi'. (TODO: automate trigger)

  2. When the packages are available on pypi, you can run the 'Pypi smoke test action'. This action will also be run every 24 hours to validate doing pip install. (TODO: automate the after-release trigger)