diff --git a/.gitignore b/.gitignore index 8eea0ce410..033d468de6 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ build/* zulip_term.egg-info zulip-terminal-tracebacks.log zulip-terminal-API-requests.log +zt_venv/* .vscode/* .DS_Store diff --git a/Pipfile b/Pipfile index 75909d115f..e41fcd577f 100644 --- a/Pipfile +++ b/Pipfile @@ -25,3 +25,5 @@ pudb = "==2017.1.4" snakeviz = "==0.4.2" gitlint = "==0.10.0" isort = "==4.3.21" +autopep8 = "~=1.5.4" +autoflake = "~=1.3.1" diff --git a/README.md b/README.md index 4b353efd66..c540c1356a 100644 --- a/README.md +++ b/README.md @@ -264,11 +264,18 @@ $ pipenv run pip3 install -r requirements.txt $ pip3 install -e '.[dev]' ``` +#### make/pip + +This is the newest and simplest approach, if you have `make` installed: + +1. `make` (sets up an installed virtual environment in `zt_venv` in the current directory) +2. `source zt_venv/bin/activate` (activates the venv; this assumes a bash-like shell) + ### Development tasks Once you have a development environment set up, you might find the following useful, depending upon your type of environment: -| Task | Pip | Pipenv | +| Task | Make & Pip | Pipenv | |-|-|-| | Run normally | `zulip-term` | `pipenv run zulip-term` | | Run in debug mode | `zulip-term -d` | `pipenv run zulip-term -d` | @@ -277,8 +284,12 @@ Once you have a development environment set up, you might find the following use | Run all tests | `pytest` | `pipenv run pytest` | | Build test coverage report | `pytest --cov-report html:cov_html --cov=./` | `pipenv run pytest --cov-report html:cov_html --cov=./` | +If using make with pip, running `make` will ensure the development environment is up to date with the specified dependencies, useful after fetching from git and rebasing. + NOTE: The linters and pytest are run in CI (travis) when you submit a pull request (PR), and we expect them to pass before code is merged. Running them locally can speed your development time, but if you have troubles understanding why the linters or pytest are failing, please do push your code to a branch/PR and we can discuss the problems in the PR or on chat.zulip.org. +If using make with pip, there are corresponding make targets for running linting and testing if you wish to use them (`make lint` & `make test`), and before pushing a pull-request (PR) ready for merging you may find it useful to ensure that `make check` runs successfully (which runs both). + NOTE: The lint script runs a number of separate linters to simplify the development workflow, but each individual linter can be run separately if you find this useful. #### GitLint (optional) diff --git a/makefile b/makefile new file mode 100644 index 0000000000..6f0154ebd1 --- /dev/null +++ b/makefile @@ -0,0 +1,49 @@ +.PHONY: install-devel check lint test check-clean-tree fix force-fix venv + +# NOTE: ZT_VENV and BASEPYTHON are advanced undocumented features +# Customize your venv name by running make as "ZT_VENV=my_venv_name make " + +BASEPYTHON?=python3 +ZT_VENV?=zt_venv + +VENV_ACTIVATE=. $(ZT_VENV)/bin/activate +PYTHON=${ZT_VENV}/bin/$(BASEPYTHON) + +SOURCES = zulipterminal tests setup.py + +# Default target at top +install-devel: venv + +### LINT/TEST FILES ### + +check: lint test + +lint: venv + @tools/lint-all + +test: venv + @pytest + +### FIX FILES ### + +check-clean-tree: + @git diff --exit-code --quiet || (echo 'Tree is not clean - commit changes in git first' && false) + +fix: check-clean-tree + @make force-fix + +force-fix: venv + @echo "=== Auto-fixing files ===" + isort --recursive $(SOURCES) + autopep8 --recursive --in-place $(SOURCES) + autoflake --recursive --in-place $(SOURCES) + +### VENV SETUP ### +# Short name for file dependency +venv: $(ZT_VENV)/bin/activate + +# If setup.py is updated or activate script doesn't exist, update virtual env +$(ZT_VENV)/bin/activate: setup.py + @echo "=== Installing development environment ===" + test -d $(ZT_VENV) || $(BASEPYTHON) -m venv $(ZT_VENV) + $(PYTHON) -m pip install -U pip && $(PYTHON) -m pip install -e .[dev] && touch $(ZT_VENV)/bin/activate diff --git a/requirements.txt b/requirements.txt index ab64989b5e..3608399b9a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -18,5 +18,7 @@ beautifulsoup4>=4.9.0 lxml>=4.5.2 python-dateutil>=2.8.1 tzlocal>=2.1 +autopep8~=1.5.4 +autoflake~=1.3.1 zipp==1.0.0 # To support Python 3.5 diff --git a/setup.py b/setup.py index c0540cf11e..a9911e8088 100644 --- a/setup.py +++ b/setup.py @@ -43,15 +43,17 @@ def long_description(): linting_deps = [ 'isort==4.3.21', 'mypy==0.782', - 'flake8==3.7.9', - 'flake8-quotes==3.0.0', - 'flake8-continuation==1.0.5', + 'flake8~=3.8.3', + 'flake8-quotes~=3.2.0', + 'flake8-continuation~=1.0.5', ] dev_helper_deps = [ 'pudb==2017.1.4', 'snakeviz==0.4.2', 'gitlint>=0.10', + 'autopep8~=1.5.4', + 'autoflake~=1.3.1', ] setup( diff --git a/tests/model/test_model.py b/tests/model/test_model.py index 2146d30f3e..052d4782f9 100644 --- a/tests/model/test_model.py +++ b/tests/model/test_model.py @@ -283,7 +283,7 @@ def test_set_narrow_not_already_set(self, model, initial_narrow, narrow, } }, {0, 1}), ([['stream', 'FOO'], - ['topic', 'BOO']], { + ['topic', 'BOO']], { 'topic_msg_ids': { 1: { 'BOO': {0, 1} @@ -291,7 +291,7 @@ def test_set_narrow_not_already_set(self, model, initial_narrow, narrow, } }, {0, 1}), ([['stream', 'FOO'], # Covers one empty-set case - ['topic', 'BOOBOO']], { + ['topic', 'BOOBOO']], { 'topic_msg_ids': { 1: { 'BOO': {0, 1} @@ -859,11 +859,11 @@ def test__handle_message_event(self, mocker, user_profile, response, @pytest.mark.parametrize(['topic_name', 'topic_order_initial', 'topic_order_final'], [ ('TOPIC3', ['TOPIC2', 'TOPIC3', 'TOPIC1'], - ['TOPIC3', 'TOPIC2', 'TOPIC1']), + ['TOPIC3', 'TOPIC2', 'TOPIC1']), ('TOPIC1', ['TOPIC1', 'TOPIC2', 'TOPIC3'], - ['TOPIC1', 'TOPIC2', 'TOPIC3']), + ['TOPIC1', 'TOPIC2', 'TOPIC3']), ('TOPIC4', ['TOPIC1', 'TOPIC2', 'TOPIC3'], - ['TOPIC4', 'TOPIC1', 'TOPIC2', 'TOPIC3']), + ['TOPIC4', 'TOPIC1', 'TOPIC2', 'TOPIC3']), ('TOPIC1', [], ['TOPIC1']) ], ids=['reorder_topic3', 'topic1_discussion_continues', 'new_topic4', 'first_topic_1']) @@ -1321,7 +1321,7 @@ def test_update_star_status(self, mocker, model, event_op, assert model.index['messages'][changed_id]['flags'] == flags_after (model._update_rendered_view. assert_has_calls([mocker.call(changed_id) - for changed_id in changed_ids])) + for changed_id in changed_ids])) for unchanged_id in (set(indexed_ids) - set(event_message_ids)): assert (model.index['messages'][unchanged_id]['flags'] @@ -1533,7 +1533,7 @@ def test__handle_subscription_event_mute_streams(self, model, mocker, model.controller.update_screen.assert_called_once_with() @pytest.mark.parametrize(['event', 'expected_pinned_streams', - 'expected_unpinned_streams'], [ + 'expected_unpinned_streams'], [ ( { 'property': 'pin_to_top', diff --git a/zulipterminal/ui_tools/boxes.py b/zulipterminal/ui_tools/boxes.py index 68e3bfea25..845fa7f417 100644 --- a/zulipterminal/ui_tools/boxes.py +++ b/zulipterminal/ui_tools/boxes.py @@ -1198,6 +1198,7 @@ class PanelSearchBox(urwid.Edit): """ Search Box to search panel views in real-time. """ + def __init__(self, panel_view: Any, search_command: str, update_function: Callable[..., None]) -> None: self.panel_view = panel_view diff --git a/zulipterminal/ui_tools/buttons.py b/zulipterminal/ui_tools/buttons.py index b20c05304b..31849e8380 100644 --- a/zulipterminal/ui_tools/buttons.py +++ b/zulipterminal/ui_tools/buttons.py @@ -272,4 +272,3 @@ def handle_link(self, *_: Any) -> None: """ Classifies and handles link. """ - pass diff --git a/zulipterminal/ui_tools/views.py b/zulipterminal/ui_tools/views.py index a4c8613e78..f54196d6bf 100644 --- a/zulipterminal/ui_tools/views.py +++ b/zulipterminal/ui_tools/views.py @@ -256,6 +256,7 @@ class StreamsViewDivider(urwid.Divider): """ A custom urwid.Divider to visually separate pinned and unpinned streams. """ + def __init__(self) -> None: # FIXME: Necessary since the divider is treated as a StreamButton. # NOTE: This is specifically for stream search to work correctly.