diff --git a/.coveragerc b/.coveragerc index 9803e87..da17630 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,3 +1,6 @@ +[run] +source = epregressions + [report] omit = epregressions/runner.py diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml deleted file mode 100644 index 676a7ce..0000000 --- a/.github/workflows/build_and_test.yml +++ /dev/null @@ -1,83 +0,0 @@ -name: Build Package and Run Tests - -on: [push] - -defaults: - run: - shell: bash - -jobs: - unit_tests: - strategy: - matrix: - include: - - os: ubuntu-20.04 - python: xvfb-run python3 - pip_arg: "" - nosetests_args: --with-coverage --cover-package epregressions # --cover-html for local html results - pyinstall_args: "" - add_data: "epregressions/diffs/math_diff.config:epregressions/diffs" - pack_tool: tar -zcvf - extension: .tar.gz - pack_suffix: -C dist runner - - os: macos-11 - python: python3 - pip_arg: "" - nosetests_args: "" - pyinstall_args: --noconsole - add_data: "epregressions/diffs/math_diff.config:epregressions/diffs" - pack_tool: tar -zcvf - extension: .tar.gz - pack_suffix: -C dist runner - - os: windows-2019 - python: python - pip_arg: --user - nosetests_args: "" - pyinstall_args: --noconsole - add_data: "epregressions/diffs/math_diff.config;epregressions/diffs" - pack_tool: 7z.exe a - extension: .zip - pack_suffix: ./dist/* - - runs-on: ${{ matrix.os }} - - steps: - - uses: actions/checkout@v2 - - name: Set up Python 3.7 - uses: actions/setup-python@v2 - with: - python-version: 3.7 - - name: Install Pip Dependencies - run: pip install ${{ matrix.pip_arg }} -r requirements.txt - - name: Run Tests - run: nosetests ${{ matrix.nosetests_args }} - - name: Upload Coverage Results - if: matrix.os == 'ubuntu-20.04' - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: coveralls --service=github - - name: Make Deploy Directory - run: mkdir deploy - - name: Build Installer - run: pyinstaller --onefile ${{ matrix.pyinstall_args }} --add-data "${{ matrix.add_data }}" epregressions/runner.py - - name: Fixup Installer - run: | - VERSION_STRING=$(grep VERSION epregressions/__init__.py | cut -d= -f2 | xargs) - ${{ matrix.pack_tool }} deploy/EnergyPlusRegressionTool-"${VERSION_STRING}"-${{ matrix.os }}${{ matrix.extension }} ${{ matrix.pack_suffix }} - - name: Upload Package - uses: actions/upload-artifact@v2 - with: - name: EnergyPlusRegressionTool-${{ matrix.os }} - path: deploy/EnergyPlusRegressionTool-* - - name: Build Wheel - run: python3 setup.py bdist_wheel sdist - - name: Clean up dist/runner - run: rm -f dist/runner - - name: Publish package to PyPi (tags only) - if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') && matrix.os == 'ubuntu-20.04' - uses: pypa/gh-action-pypi-publish@release/v1 - with: - user: __token__ - password: ${{ secrets.PYPI_API_TOKEN }} - #- name: Setup upterm session - # uses: lhotari/action-upterm@v1 diff --git a/.github/workflows/flake8.yml b/.github/workflows/flake8.yml index 50dc370..2f0c142 100644 --- a/.github/workflows/flake8.yml +++ b/.github/workflows/flake8.yml @@ -7,12 +7,12 @@ jobs: runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v2 - - name: Set up Python 3.7 - uses: actions/setup-python@v2 + - name: Set up Python 3.8 + uses: actions/setup-python@b55428b1882923874294fa556849718a1d7f2ca5 # v4.2.0 with: - python-version: 3.7 + python-version: 3.8 - name: Install Pip Dependencies run: pip install flake8 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..78dad61 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,32 @@ +name: PyPIRelease + +on: + push: + tags: + - '*' + +jobs: + release: + runs-on: ubuntu-20.04 + + steps: + - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v2 + + - name: Set up Python + uses: actions/setup-python@b55428b1882923874294fa556849718a1d7f2ca5 # v4.2.0 + with: + python-version: 3.8 + + - name: Install Pip Dependencies + shell: bash + run: pip install -r requirements.txt + + - name: Build the Wheel + shell: bash + run: rm -rf dist/ build/ && python3 setup.py bdist_wheel sdist + + - name: Deploy on Test PyPi + uses: pypa/gh-action-pypi-publish@37f50c210e3d2f9450da2cd423303d6a14a6e29f # v1.5.1 + with: + user: __token__ + password: ${{ secrets.PYPIPW }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..f1c1e60 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,29 @@ +name: Run Tests + +on: [push] + +defaults: + run: + shell: bash + +jobs: + unit_tests: + strategy: + matrix: + os: [ windows-latest, macos-11, ubuntu-20.04, ubuntu-22.04 ] # macos-12 is not playing well with Tk + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v2 + - name: Set up Python 3.8 + uses: actions/setup-python@b55428b1882923874294fa556849718a1d7f2ca5 # v4.2.0 + with: + python-version: 3.8 + - name: Install Pip Dependencies + run: pip install -r requirements.txt + - name: Run Tests + run: nosetests + - name: Coveralls + if: ${{ matrix.os == 'ubuntu-22.04' }} + run: coveralls --service=github + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index d77e768..01874b8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +*.egg-info .idea *.pyc tex_docs diff --git a/epregressions/__init__.py b/epregressions/__init__.py index 46afb66..bc6a026 100644 --- a/epregressions/__init__.py +++ b/epregressions/__init__.py @@ -1 +1 @@ -VERSION = '1.9.6' +VERSION = '1.9.7' diff --git a/epregressions/runtests.py b/epregressions/runtests.py index 93fd7eb..33b7b4e 100755 --- a/epregressions/runtests.py +++ b/epregressions/runtests.py @@ -131,6 +131,7 @@ def run_test_suite(self): self.my_cancelled() return + start_time = datetime.now() self.my_starting(len(self.entries)) # run the energyplus script @@ -144,7 +145,7 @@ def run_test_suite(self): return self.my_simulations_complete() - self.diff_logs_for_build() + self.diff_logs_for_build(start_time) try: self.my_print('Writing runtime summary file') @@ -1087,13 +1088,14 @@ def process_end_file(end_path): return [status, total_runtime_seconds] # diff_logs_for_build creates diff logs between simulations in two build directories - def diff_logs_for_build(self): + def diff_logs_for_build(self, original_start_time): self.completed_structure = CompletedStructure( self.build_tree_a['source_dir'], self.build_tree_a['build_dir'], self.build_tree_b['source_dir'], self.build_tree_b['build_dir'], os.path.join(self.build_tree_a['build_dir'], self.test_output_dir), - os.path.join(self.build_tree_b['build_dir'], self.test_output_dir) + os.path.join(self.build_tree_b['build_dir'], self.test_output_dir), + original_start_time ) diff_runs = [] for this_entry in self.entries: diff --git a/epregressions/structures.py b/epregressions/structures.py index beccece..efae00c 100755 --- a/epregressions/structures.py +++ b/epregressions/structures.py @@ -376,10 +376,10 @@ def to_dict(self): class ExtraInfo: - def __init__(self): + def __init__(self, start_time): self.descriptions = { 'time_stamps': [ - f"Start time: {datetime.now()}", "End time initialized" + f"Start time: {start_time}", "End time initialized" ] } @@ -389,7 +389,7 @@ def set_end_time(self): class CompletedStructure: def __init__(self, case_a_source_dir, case_a_build_dir, case_b_source_dir, - case_b_build_dir, results_dir_a, results_dir_b): + case_b_build_dir, results_dir_a, results_dir_b, original_start_time): self.case_a_source_dir = case_a_source_dir self.case_a_build_dir = case_a_build_dir self.case_b_source_dir = case_b_source_dir @@ -411,7 +411,7 @@ def __init__(self, case_a_source_dir, case_a_build_dir, case_b_source_dir, self.small_table_diffs = Results() self.text_diffs = Results() # extra info - self.extra = ExtraInfo() + self.extra = ExtraInfo(original_start_time) def add_test_entry(self, this_entry): self.entries_by_file.append(this_entry) diff --git a/epregressions/tests/resources/README.md b/epregressions/tests/resources/README.md index f7ce572..1169ba6 100644 --- a/epregressions/tests/resources/README.md +++ b/epregressions/tests/resources/README.md @@ -2,16 +2,15 @@ This folder contains a bunch of resources for running tests. These are extremely lightweight executable scripts that mimic the actual E+ toolchain. There are also other files in here such as example weather files and E+ run files. -def execute_energyplus(build_tree, entry_name, test_run_directory, - run_type, min_reporting_freq, this_parametric_file, weather_file_name): - # setup a few paths - energyplus = build_tree['energyplus'] - basement = build_tree['basement'] - idd_path = build_tree['idd_path'] - slab = build_tree['slab'] - basementidd = build_tree['basementidd'] - slabidd = build_tree['slabidd'] - expandobjects = build_tree['expandobjects'] - epmacro = build_tree['epmacro'] - readvars = build_tree['readvars'] - parametric = build_tree['parametric'] +The windows versions of these are prebuilt using pyinstaller and placed in the `dist/` directory +To rebuild them, ensure you have pyinstaller on Windows, change dir into the `epregressions/tests/resources` directory, and run: + +``` +PYTHONPATH=. ../../../venv/Scripts/pyinstaller.exe --onefile --log-level=WARN -n basement dummy.basement.py +PYTHONPATH=. ../../../venv/Scripts/pyinstaller.exe --onefile --log-level=WARN -n energyplus dummy.energyplus.py +PYTHONPATH=. ../../../venv/Scripts/pyinstaller.exe --onefile --log-level=WARN -n epmacro dummy.epmacro.py +PYTHONPATH=. ../../../venv/Scripts/pyinstaller.exe --onefile --log-level=WARN -n expandobjects dummy.expandobjects.py +PYTHONPATH=. ../../../venv/Scripts/pyinstaller.exe --onefile --log-level=WARN -n parametric dummy.parametric.py +PYTHONPATH=. ../../../venv/Scripts/pyinstaller.exe --onefile --log-level=WARN -n readvars dummy.readvars.py +PYTHONPATH=. ../../../venv/Scripts/pyinstaller.exe --onefile --log-level=WARN -n slab dummy.slab.py +``` diff --git a/epregressions/tests/resources/dist/basement.exe b/epregressions/tests/resources/dist/basement.exe new file mode 100644 index 0000000..471fdd2 Binary files /dev/null and b/epregressions/tests/resources/dist/basement.exe differ diff --git a/epregressions/tests/resources/dist/energyplus.exe b/epregressions/tests/resources/dist/energyplus.exe new file mode 100644 index 0000000..35ed231 Binary files /dev/null and b/epregressions/tests/resources/dist/energyplus.exe differ diff --git a/epregressions/tests/resources/dist/epmacro.exe b/epregressions/tests/resources/dist/epmacro.exe new file mode 100644 index 0000000..a3ab2c0 Binary files /dev/null and b/epregressions/tests/resources/dist/epmacro.exe differ diff --git a/epregressions/tests/resources/dist/expandobjects.exe b/epregressions/tests/resources/dist/expandobjects.exe new file mode 100644 index 0000000..c656411 Binary files /dev/null and b/epregressions/tests/resources/dist/expandobjects.exe differ diff --git a/epregressions/tests/resources/dist/parametric.exe b/epregressions/tests/resources/dist/parametric.exe new file mode 100644 index 0000000..a43bad9 Binary files /dev/null and b/epregressions/tests/resources/dist/parametric.exe differ diff --git a/epregressions/tests/resources/dist/readvars.exe b/epregressions/tests/resources/dist/readvars.exe new file mode 100644 index 0000000..38470d6 Binary files /dev/null and b/epregressions/tests/resources/dist/readvars.exe differ diff --git a/epregressions/tests/resources/dist/slab.exe b/epregressions/tests/resources/dist/slab.exe new file mode 100644 index 0000000..1a42e7e Binary files /dev/null and b/epregressions/tests/resources/dist/slab.exe differ diff --git a/epregressions/tests/test_runtests.py b/epregressions/tests/test_runtests.py index 1b31be0..4195e66 100644 --- a/epregressions/tests/test_runtests.py +++ b/epregressions/tests/test_runtests.py @@ -2,7 +2,6 @@ import os from platform import system import shutil -from subprocess import check_call import tempfile import unittest @@ -42,24 +41,6 @@ def establish_build_folder( # variables and run them all. Also, we don't want to run them for every single test, just once if the dist/ # folder hasn't been created yet. dist_folder = os.path.join(self.resources, 'dist') - if not os.path.exists(dist_folder): - # find pyinstaller -- it should be available in path I think - pyinstaller = "pyinstaller.exe" - # pyinstaller = r"C:\EnergyPlus\repos\EnergyPlusRegressionTool\venv\Scripts\pyinstaller.exe" - # run it on all these - conversions = [ - ['dummy.basement.py', 'basement'], - ['dummy.energyplus.py', 'energyplus'], - ['dummy.expandobjects.py', 'expandobjects'], - ['dummy.parametric.py', 'parametric'], - ['dummy.readvars.py', 'readvars'], - ['dummy.slab.py', 'slab'], - ['dummy.epmacro.py', 'epmacro'], - ] - working_dir = self.resources - for conv in conversions: - cmd = [pyinstaller, '--onefile', '--log-level=WARN', '-n', conv[1], conv[0]] - check_call(cmd, cwd=working_dir) products_map = { os.path.join(self.resources, 'dummy.basement.idd'): os.path.join(products_dir, 'BasementGHT.idd'), os.path.join(dist_folder, 'basement.exe'): os.path.join(products_dir, 'Basement.exe'), diff --git a/epregressions/tests/test_structures.py b/epregressions/tests/test_structures.py index 8c6ddcb..6edcecd 100644 --- a/epregressions/tests/test_structures.py +++ b/epregressions/tests/test_structures.py @@ -177,7 +177,9 @@ def test_workflow(self): class TestCompletedStructure(unittest.TestCase): def test_workflow(self): - c = CompletedStructure('/a/source/dir', '/a/build/dir', '/b/source/dir', '/b/build/dir', '/r/dir1', '/r/dir2') + c = CompletedStructure( + '/a/source/dir', '/a/build/dir', '/b/source/dir', '/b/build/dir', '/r/dir1', '/r/dir2', 'dummy_start_time' + ) t = TestEntry('filename', 'weather') t = TestTestEntry.fully_populated_entry_successful(t) c.add_test_entry(t) @@ -190,7 +192,9 @@ def test_workflow(self): c.add_test_entry(t) def test_to_csv(self): - c = CompletedStructure('/a/source/dir', '/a/build/dir', '/b/source/dir', '/b/build/dir', '/r/dir1', '/r/dir2') + c = CompletedStructure( + '/a/source/dir', '/a/build/dir', '/b/source/dir', '/b/build/dir', '/r/dir1', '/r/dir2', 'dummy_start_time' + ) t = TestEntry('filename', 'weather') t = TestTestEntry.fully_populated_entry_successful(t) c.add_test_entry(t) @@ -200,7 +204,9 @@ def test_to_csv(self): c.to_runtime_summary('/invalid/path') def test_to_json(self): - c = CompletedStructure('/a/source/dir', '/a/build/dir', '/b/source/dir', '/b/build/dir', '/r/dir1', '/r/dir2') + c = CompletedStructure( + '/a/source/dir', '/a/build/dir', '/b/source/dir', '/b/build/dir', '/r/dir1', '/r/dir2', 'dummy_start_time' + ) t = TestEntry('filename', 'weather') t = TestTestEntry.fully_populated_entry_successful(t) c.add_test_entry(t) @@ -215,7 +221,9 @@ def test_to_json(self): self.assertIn('results_by_file', obj) def test_to_json_object_response(self): - c = CompletedStructure('/a/source/dir', '/a/build/dir', '/b/source/dir', '/b/build/dir', '/r/dir1', '/r/dir2') + c = CompletedStructure( + '/a/source/dir', '/a/build/dir', '/b/source/dir', '/b/build/dir', '/r/dir1', '/r/dir2', 'dummy_start_time' + ) t = TestEntry('filename', 'weather') t = TestTestEntry.fully_populated_entry_successful(t) c.add_test_entry(t) diff --git a/epregressions/tk_window.py b/epregressions/tk_window.py index d199c2d..aea164f 100644 --- a/epregressions/tk_window.py +++ b/epregressions/tk_window.py @@ -1,6 +1,6 @@ import os import random -import subprocess +from subprocess import check_output, CalledProcessError, Popen, call import sys import webbrowser from datetime import datetime @@ -72,6 +72,57 @@ def get_all(): ] +class Notification: + """ + A thin notification class using gdbus command line calls to avoid any dependencies. + This should work on most modern Linux distributions. + """ + def __init__(self, app_name): + """Construct a new notification class, persisting the app name only""" + self.command = 'gdbus' + self.action = 'call' + self.bus = '--session' + self.destination = ("--dest", "org.freedesktop.Notifications") + self.path = ("--object-path", "/org/freedesktop/Notifications") + self.method = ("--method", "org.freedesktop.Notifications.Notify") + self.app_name = app_name + self.notification_id = '0' + self.actions = '[]' + self.hint = "{'x-canonical-private-synchronous': <''>, 'transient': , 'value': <20>}" + self.time_out = '0' # seems to be ignored, but the notification should stay in the drop-down tray + + def _build_argument_list(self, title: str, message: str, icon_path: Path) -> List[str]: + """Internal function to construct the full command line based on dynamic arguments""" + return [ + self.command, + self.action, + self.bus, + self.destination[0], self.destination[1], + self.path[0], self.path[1], + self.method[0], self.method[1], + self.app_name, + self.notification_id, + str(icon_path), + title, + message, + self.actions, + self.hint, + self.time_out + ] + + def send_notification(self, title: str, message: str, icon: Path) -> bool: + """Main action for this class, emits a notification and stores the ID to be reused later""" + command_line = self._build_argument_list(title, message, icon) + try: + # returns: b'(uint32 X,)\n' where X is some int of variable length, so trim from both sides + std_out = check_output(command_line) + self.notification_id = std_out[7:-3] + return True + except CalledProcessError: + self.notification_id = '0' + return False + + class PubSubMessageTypes: PRINT = '10' STARTING = '20' @@ -89,8 +140,9 @@ def __init__(self): Frame.__init__(self, self.root) # add the taskbar icon, but its having issues reading the png on Mac, not sure. + self.icon_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'ep.png') if system() != 'Darwin': - img = PhotoImage(file=os.path.join(os.path.dirname(os.path.abspath(__file__)), 'ep.png')) + img = PhotoImage(file=self.icon_path) self.root.iconphoto(False, img) # high level GUI configuration @@ -156,6 +208,7 @@ def __init__(self): self.reporting_frequency_option_menu = None self.force_output_sql_option_menu = None self.force_output_sql_unitconv_option_menu = None + self.idf_select_from_containing_button = None # some data holders self.tree_folders = dict() @@ -184,6 +237,12 @@ def __init__(self): pub.subscribe(self.done_handler, PubSubMessageTypes.ALL_DONE) pub.subscribe(self.cancelled_handler, PubSubMessageTypes.CANCELLED) + # on Linux, initialize the notification class instance + self.notification = None + if system() == 'Linux': + self.notification_icon = Path(self.icon_path) + self.notification = Notification('eplus_regression_runner') + def init_window(self): # changing the title of our master widget self.root.title("EnergyPlus Regression Tool") @@ -277,13 +336,17 @@ def init_window(self): ) self.idf_deselect_all_button.pack(side=LEFT, expand=1) self.idf_select_n_random_button = ttk.Button( - group_idf_tools, text="Select N Random", command=self.idf_select_random, style="C.TButton" + group_idf_tools, text="Select N Random...", command=self.idf_select_random, style="C.TButton" ) self.idf_select_n_random_button.pack(side=LEFT, expand=1) self.idf_select_from_list_button = ttk.Button( - group_idf_tools, text="Select From List", command=self.idf_select_list, style="C.TButton" + group_idf_tools, text="Select From List...", command=self.idf_select_list, style="C.TButton" ) self.idf_select_from_list_button.pack(side=LEFT, expand=1) + self.idf_select_from_containing_button = ttk.Button( + group_idf_tools, text="Select Files Containing...", command=self.idf_select_containing, style="C.TButton" + ) + self.idf_select_from_containing_button.pack(side=LEFT, expand=1) group_full_idf_list = LabelFrame(pane_idfs, text="Full IDF List") group_full_idf_list.pack(fill=BOTH, expand=True, padx=5) @@ -526,19 +589,19 @@ def open_file_browser_to_directory(dir_to_open): p = None if this_platform == 'Linux': try: - p = subprocess.Popen(['xdg-open', dir_to_open]) + p = Popen(['xdg-open', dir_to_open]) except Exception as this_exception: # pragma: no cover - not covering bad directories print("Could not open file:") print(this_exception) elif this_platform == 'Windows': # pragma: no cover - only testing on Linux try: - p = subprocess.Popen(['start', dir_to_open], shell=True) + p = Popen(['start', dir_to_open], shell=True) except Exception as this_exception: print("Could not open file:") print(this_exception) elif this_platform == 'Darwin': # pragma: no cover - only testing on Linux try: - p = subprocess.Popen(['open', dir_to_open]) + p = Popen(['open', dir_to_open]) except Exception as this_exception: print("Could not open file:") print(this_exception) @@ -807,6 +870,25 @@ def idf_select_list(self): self.active_idf_listbox.insert(END, this_idf_possibility) self.idf_refresh_count_status() + def idf_select_containing(self): + if not self.valid_idfs_in_listing: + messagebox.showerror("IDF Selection Error", "Invalid build folders or IDF list") + return + search_string = simpledialog.askstring("Input IDF String", "Plain string to search inside IDFs") + if not search_string: + return + search_string = search_string.upper() + self.idf_deselect_all() + for i in range(self.full_idf_listbox.size()): + this_idf_possibility = self.full_idf_listbox.get(i) + this_idf_full_path = Path(self.build_1.get_idf_directory()) / this_idf_possibility + if not this_idf_full_path.exists(): + print(f"Missing IDF at: {this_idf_full_path}") # some warning? + contents = this_idf_full_path.read_text().upper() + if search_string in contents: + self.active_idf_listbox.insert(END, this_idf_possibility) + self.idf_refresh_count_status() + def idf_refresh_count_status(self, test_case=None, checked=False): if not self.valid_idfs_in_listing: return @@ -1029,9 +1111,22 @@ def done_handler(self, results: CompletedStructure): self.add_to_log("All done, finished") self.label_string.set("Hey, all done!") if system() == 'Linux': - subprocess.call(['notify-send', 'EnergyPlus Regression Tool', 'Regressions Finished']) + time_format = '%Y-%m-%d %H:%M:%S.%f' + time_stamps = results.extra.descriptions['time_stamps'] + start_string = time_stamps[0][12:] + start_time = datetime.strptime(start_string, time_format) + end_string = time_stamps[1][10:] + end_time = datetime.strptime(end_string, time_format) + time_report = '' + whole_minutes, remaining_time = divmod((end_time - start_time).total_seconds(), 60) + if int(whole_minutes) > 0: + time_report += f'{whole_minutes:.0f}m ' + time_report += f'{remaining_time:.0f}s' + self.notification.send_notification( + 'EnergyPlus Regression Tool', f'Regressions Finished ({time_report})', self.notification_icon + ) elif system() == 'Darwin': - subprocess.call([ + call([ 'osascript', '-e', 'display notification "Regressions Finished" with title "EnergyPlus Regression Tool"' diff --git a/requirements.txt b/requirements.txt index 9a87684..168e269 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,10 +10,12 @@ coveralls==2.1.2 flake8==3.8.4 nose==1.3.7 +# on windows, if you need to rebuild the unit test resource exes, just install pyinstaller and follow the directions in epregressions/tests/resources/README.md +# pyinstaller; platform_system == "Windows" + # to generate documentation Sphinx==3.2.1 docutils==0.16 # pinning this because it breaks at 0.18 # for packaging -pyinstaller wheel diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..81ece2d --- /dev/null +++ b/setup.cfg @@ -0,0 +1,10 @@ +# this command line arg was required for Python 3.8+ to get nose to find tests +# adding it here so that a tester or CI machine can just run `nosetests` without args +# if there is a better way around it I'd be happy to remove this +[nosetests] +traverse-namespace=1 +with-coverage=1 +cover-html=1 +cover-package=epregressions +cover-tests=1 +cover-inclusive=1 diff --git a/setup.py b/setup.py index 9932801..5624f8b 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ long_description = i_file.read() setup( - name='EnergyPlusRegressionTool', + name='energyplus_regressions', version=VERSION, packages=find_packages(exclude=['test', 'tests', 'test.*']), url='https://github.com/NREL/EnergyPlusRegressionTool',