Skip to content

Commit 1fac484

Browse files
Merge pull request #4 from cgq-qgc/setup_azure_pipeline_and_build_exe
PR: Setup azure pipeline and build an exe
2 parents 4f1b3ee + 3cfe0b7 commit 1fac484

29 files changed

Lines changed: 333 additions & 2578 deletions

.gitignore

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ __pycache__/
1010
*.so
1111

1212
# Distribution / packaging
13+
releases/Output
14+
releases/build
15+
releases/*.zip
16+
releases/*.sig
17+
releases/*.iss
18+
releases/*win_amd64
1319
.Python
1420
build/
1521
develop-eggs/
@@ -34,7 +40,6 @@ MANIFEST
3440
# Usually these files are written by a python script from a template
3541
# before PyInstaller builds the exe, so as to inject date/other infos into it.
3642
*.manifest
37-
*.spec
3843

3944
# Installer logs
4045
pip-log.txt

azure-pipelines.yml

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
11
# Python package
22
# Create and test a Python package on multiple Python versions.
3-
# Add steps that analyze code, save the dist with the build record, publish to a PyPI-compatible index, and more:
3+
# Add steps that analyze code, save the dist with the build record,
4+
# publish to a PyPI-compatible index, and more:
45
# https://docs.microsoft.com/azure/devops/pipelines/languages/python
56

67
trigger:
78
- master
89

10+
variables:
11+
AZURE: True
12+
CODECOV_TOKEN: "e1a9c98d-d8db-471d-a31d-af2a535323cd"
13+
CDPREP_OUTPUT_DIRNAME: 'cdprep_0.1.0.dev0_win_amd64'
14+
915
pool:
10-
vmImage: 'ubuntu-latest'
16+
vmImage: 'windows-2019'
17+
1118
strategy:
1219
matrix:
13-
Python27:
14-
python.version: '2.7'
15-
Python35:
16-
python.version: '3.5'
17-
Python36:
18-
python.version: '3.6'
1920
Python37:
2021
python.version: '3.7'
2122

@@ -28,9 +29,28 @@ steps:
2829
- script: |
2930
python -m pip install --upgrade pip
3031
pip install -r requirements.txt
32+
pip install -r requirements-dev.txt
33+
pip install pytest-azurepipelines
3134
displayName: 'Install dependencies'
3235

3336
- script: |
34-
pip install pytest pytest-azurepipelines
35-
pytest
36-
displayName: 'pytest'
37+
python runtests.py
38+
displayName: 'Run tests'
39+
continueOnError: false
40+
41+
- script: |
42+
codecov
43+
displayName: 'Run codecov'
44+
45+
- script: |
46+
python -m pip install pyinstaller==3.6 pywin32 tornado
47+
set PYTHONPATH=$(Build.SourcesDirectory);%PYTHONPATH%
48+
cd ./releases
49+
pyinstaller.exe cdprep.spec
50+
cd ..
51+
displayName: 'Build package'
52+
53+
- task: PublishPipelineArtifact@0
54+
inputs:
55+
artifactName: '$(CDPREP_OUTPUT_DIRNAME)'
56+
targetPath: '$(Build.SourcesDirectory)/releases/$(CDPREP_OUTPUT_DIRNAME)'

cdprep/__init__.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
# -*- coding: utf-8 -*-
2-
32
"""
4-
GWHAT License Agreement (GNU-GPLv3)
3+
Climate Data Preprocessing Tool License Agreement (GNU-GPLv3)
54
--------------------------------------
65
7-
Copyright (c) 2014-2018 GWHAT Project Contributors
8-
https://github.com/jnsebgosselin/gwhat
6+
Copyright (c) 2014-2020 Climate Data Preprocessing Tool Project Contributors
7+
https://github.com/cgq-qgc/climate-data-preprocessing-tool
98
10-
GWHAT is free software: you can redistribute it and/or modify
11-
it under the terms of the GNU General Public License as published by
12-
the Free Software Foundation, either version 3 of the License, or
9+
limate Data Preprocessing Tool is free software: you can redistribute it
10+
and/or modify it under the terms of the GNU General Public License as
11+
published by the Free Software Foundation, either version 3 of the License, or
1312
(at your option) any later version.
1413
1514
This program is distributed in the hope that it will be useful,

cdprep/app/__init__.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# -*- coding: utf-8 -*-
2+
# -----------------------------------------------------------------------------
3+
# Copyright © Climate Data Preprocessing Tool Project Contributors
4+
# https://github.com/cgq-qgc/climate-data-preprocessing-tool
5+
#
6+
# This file is part of Climate Data Preprocessing Tool.
7+
# Licensed under the terms of the GNU General Public License.
8+
# -----------------------------------------------------------------------------
Lines changed: 55 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,21 @@
77
# Licensed under the terms of the GNU General Public License.
88
# -----------------------------------------------------------------------------
99

10-
# ---- Standard imports
10+
from cdprep import __appname__
11+
print('Starting {}...'.format(__appname__))
12+
13+
# ---- Setup the main Qt application.
1114
import sys
12-
import os
15+
from qtpy.QtWidgets import QApplication
16+
app = QApplication(sys.argv)
17+
18+
# ---- Standard imports
1319
import os.path as osp
1420
import platform
1521

1622
# ---- Third parties imports
1723
from appconfigs.base import get_home_dir
18-
from qtpy.QtCore import Qt
24+
from qtpy.QtCore import Qt, QPoint
1925
from qtpy.QtWidgets import (
2026
QApplication, QMainWindow, QToolBar, QToolButton, QLineEdit, QGridLayout,
2127
QLabel, QWidget, QFileDialog)
@@ -28,8 +34,7 @@
2834
from cdprep.gapfill_data.gapfill_weather_gui import WeatherDataGapfiller
2935
from cdprep.utils.qthelpers import (
3036
create_toolbar_stretcher, qbytearray_to_hexstate, hexstate_to_qbytearray)
31-
from cdprep.config.ospath import (
32-
get_select_file_dialog_dir, set_select_file_dialog_dir)
37+
from cdprep.config.ospath import set_select_file_dialog_dir
3338

3439

3540
class MainWindow(QMainWindow):
@@ -49,17 +54,18 @@ def __init__(self):
4954
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(
5055
myappid)
5156

52-
self.data_downloader = WeatherStationDownloader(self)
57+
self.data_downloader = None
5358

5459
# Setup the toolbar.
5560
self.show_data_downloader_btn = QToolButton()
5661
self.show_data_downloader_btn.setIcon(get_icon('search_weather_data'))
5762
self.show_data_downloader_btn.setAutoRaise(True)
5863
self.show_data_downloader_btn.setToolTip("Download Data")
5964
self.show_data_downloader_btn.clicked.connect(
60-
self.data_downloader.show)
65+
self.show_data_downloader)
6166

6267
toolbar = QToolBar('Main')
68+
toolbar.setObjectName('main_toolbar')
6369
toolbar.setFloatable(False)
6470
toolbar.setMovable(False)
6571
toolbar.setIconSize(get_iconsize('normal'))
@@ -102,7 +108,8 @@ def set_workdir(self, workdir):
102108
self._workdir = workdir
103109
CONF.set('main', 'working_dir', workdir)
104110
self.workdir_ledit.setText(workdir)
105-
self.data_downloader.workdir = workdir
111+
if self.data_downloader is not None:
112+
self.data_downloader.workdir = workdir
106113
self.gapfiller.set_workdir(workdir)
107114
else:
108115
self.set_workdir(get_home_dir())
@@ -118,6 +125,24 @@ def select_working_directory(self):
118125
set_select_file_dialog_dir(dirname)
119126
self.set_workdir(dirname)
120127

128+
def show_data_downloader(self):
129+
"""
130+
Show the download data dialog.
131+
"""
132+
if self.data_downloader is None:
133+
self.data_downloader = WeatherStationDownloader(self)
134+
self.data_downloader.workdir = self._workdir
135+
self.data_downloader.show()
136+
qr = self.data_downloader.frameGeometry()
137+
wp = self.frameGeometry().width()
138+
hp = self.frameGeometry().height()
139+
cp = self.mapToGlobal(QPoint(wp/2, hp/2))
140+
qr.moveCenter(cp)
141+
self.data_downloader.move(qr.topLeft())
142+
self.data_downloader.show()
143+
self.data_downloader.activateWindow()
144+
self.data_downloader.raise_()
145+
121146
# ---- Main window settings
122147
def _restore_window_geometry(self):
123148
"""
@@ -129,7 +154,7 @@ def _restore_window_geometry(self):
129154
hexstate = hexstate_to_qbytearray(hexstate)
130155
self.restoreGeometry(hexstate)
131156
else:
132-
from gwhat.config.gui import INIT_MAINWINDOW_SIZE
157+
from cdprep.config.gui import INIT_MAINWINDOW_SIZE
133158
self.resize(*INIT_MAINWINDOW_SIZE)
134159

135160
def _save_window_geometry(self):
@@ -164,11 +189,29 @@ def closeEvent(self, event):
164189
self._save_window_geometry()
165190
self._save_window_state()
166191
self.gapfiller.close()
192+
if self.data_downloader is not None:
193+
self.data_downloader.close()
167194
event.accept()
168195

169196

197+
def except_hook(cls, exception, traceback):
198+
"""
199+
Used to override the default sys except hook so that this application
200+
doesn't automatically exit when an unhandled exception occurs.
201+
202+
See this StackOverflow answer for more details :
203+
https://stackoverflow.com/a/33741755/4481445
204+
"""
205+
sys.__excepthook__(cls, exception, traceback)
206+
207+
170208
if __name__ == '__main__':
171-
app = QApplication(sys.argv)
172-
mainwindow = MainWindow()
173-
mainwindow.show()
209+
sys.excepthook = except_hook
210+
main = MainWindow()
211+
212+
if platform.system() == 'Windows':
213+
from PyQt5.QtWidgets import QStyleFactory
214+
app.setStyle(QStyleFactory.create('WindowsVista'))
215+
216+
main.show()
174217
sys.exit(app.exec_())

cdprep/app/tests/__init__.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# -*- coding: utf-8 -*-
2+
# -----------------------------------------------------------------------------
3+
# Copyright © Climate Data Preprocessing Tool Project Contributors
4+
# https://github.com/cgq-qgc/climate-data-preprocessing-tool
5+
#
6+
# This file is part of Climate Data Preprocessing Tool.
7+
# Licensed under the terms of the GNU General Public License.
8+
# -----------------------------------------------------------------------------
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# -*- coding: utf-8 -*-
2+
# -----------------------------------------------------------------------------
3+
# Copyright © Climate Data Preprocessing Tool Project Contributors
4+
# https://github.com/cgq-qgc/climate-data-preprocessing-tool
5+
#
6+
# This file is part of Climate Data Preprocessing Tool.
7+
# Licensed under the terms of the GNU General Public License.
8+
# -----------------------------------------------------------------------------
9+
10+
"""
11+
Tests for the mainwindow.
12+
"""
13+
14+
# ---- Standard imports
15+
import os
16+
import os.path as osp
17+
os.environ['CDPREP_PYTEST'] = 'True'
18+
19+
# ---- Third party imports
20+
from appconfigs.base import get_home_dir
21+
import pytest
22+
from qtpy.QtCore import QSize
23+
24+
# ---- Local imports
25+
from cdprep.config.gui import INIT_MAINWINDOW_SIZE
26+
from cdprep.app.mainwindow import MainWindow, CONF
27+
28+
29+
# =============================================================================
30+
# ---- Fixtures
31+
# =============================================================================
32+
@pytest.fixture()
33+
def conf():
34+
CONF.reset_to_defaults()
35+
36+
37+
@pytest.fixture(scope='module')
38+
def workdir(tmp_path_factory):
39+
tmp_path = tmp_path_factory.mktemp("test_project")
40+
return osp.join(tmp_path, 'mainwindow_test_project.gwp')
41+
42+
43+
@pytest.fixture()
44+
def mainwindow(qtbot, mocker, conf):
45+
"""A fixture for Gwire mainwindow."""
46+
mainwindow = MainWindow()
47+
qtbot.addWidget(mainwindow)
48+
mainwindow.show()
49+
qtbot.waitForWindowShown(mainwindow)
50+
return mainwindow
51+
52+
53+
# =============================================================================
54+
# ---- Tests for MainWindow
55+
# =============================================================================
56+
def test_mainwindow_init(mainwindow):
57+
"""Test that the mainwindow is initialized correctly."""
58+
assert mainwindow
59+
assert mainwindow.size() == QSize(*INIT_MAINWINDOW_SIZE)
60+
assert mainwindow._workdir == get_home_dir()
61+
62+
63+
if __name__ == "__main__":
64+
pytest.main(['-x', __file__, '-v', '-rw', '-s'])

cdprep/config/gui.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,5 @@
1414
YELLOWLIGHT = '#fcf7b6'
1515
LIGHTGRAY = '#F0F0F0'
1616

17-
INIT_MAINWINDOW_SIZE = (1260, 740)
17+
INIT_MAINWINDOW_SIZE = (1028, 740)
1818
FRAME_SYLE = 22

0 commit comments

Comments
 (0)