Skip to content

Commit c9d5e95

Browse files
committed
Add CI
1 parent 28f8fb4 commit c9d5e95

File tree

8 files changed

+86
-18
lines changed

8 files changed

+86
-18
lines changed
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
env:
2+
PYTHONUNBUFFERED: "TRUE"
3+
name: test
4+
on: [pull_request, workflow_call]
5+
jobs:
6+
lint:
7+
uses: ISISComputingGroup/reusable-workflows/.github/workflows/linters.yml@main
8+
with:
9+
compare-branch: origin/main
10+
python-ver: '3.11'
11+
unit-tests:
12+
runs-on: ${{ matrix.os }}
13+
strategy:
14+
matrix:
15+
os: ["ubuntu-latest", "windows-latest"]
16+
version: ['3.11']
17+
fail-fast: false
18+
steps:
19+
- uses: actions/checkout@v4
20+
- uses: actions/setup-python@v5
21+
with:
22+
python-version: ${{ matrix.version }}
23+
- name: Install base requirements
24+
run: pip install -e .
25+
- name: Verify package is importable
26+
run: |
27+
python -c "from genie_python.genie_startup import *"
28+
python -c "from genie_python import genie as g"
29+
- name: Install dev requirements
30+
run: pip install -e .[dev]
31+
- name: Run unit tests
32+
run: python -m pytest
33+
results:
34+
if: ${{ always() }}
35+
runs-on: ubuntu-latest
36+
name: Final Results
37+
needs: [lint, unit-tests]
38+
steps:
39+
- run: exit 1
40+
# see https://stackoverflow.com/a/67532120/4907315
41+
if: >-
42+
${{
43+
contains(needs.*.result, 'failure')
44+
|| contains(needs.*.result, 'cancelled')
45+
}}

.github/workflows/linter.yml

Lines changed: 0 additions & 8 deletions
This file was deleted.

pyproject.toml

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,10 @@ dependencies = [
4141
"numpy",
4242
# EPICS PV access lib
4343
"p4p",
44-
# Used to find process by name to kill it
45-
"psutil",
4644
# For checking user scripts on g.load_script()
4745
"pylint",
46+
# Used to find process by name to kill it
47+
"psutil",
4848
# For setting windows job-object flags
4949
"pywin32;platform_system=='Windows'",
5050
]
@@ -76,6 +76,8 @@ dev = [
7676
"parameterized",
7777
"pyhamcrest",
7878
"pyright",
79+
"pytest",
80+
"pytest-cov",
7981
"ruff>=0.6",
8082
]
8183

@@ -84,6 +86,25 @@ dev = [
8486
"Bug Reports" = "https://github.com/isiscomputinggroup/genie/issues"
8587
"Source" = "https://github.com/isiscomputinggroup/genie"
8688

89+
[tool.pytest.ini_options]
90+
testpaths = "tests"
91+
addopts = "--cov --cov-report=html -vv"
92+
93+
[tool.coverage.run]
94+
branch = true
95+
source = ["src"]
96+
97+
[tool.coverage.report]
98+
exclude_lines = [
99+
"pragma: no cover",
100+
"if TYPE_CHECKING:",
101+
"if typing.TYPE_CHECKING:",
102+
"@abstractmethod",
103+
]
104+
105+
[tool.coverage.html]
106+
directory = "coverage_html_report"
107+
87108
[tool.pyright]
88109
include = ["src", "tests"]
89110
reportConstantRedefinition = true

src/genie_python/genie_api_setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ def set_user_script_dir(*directory: str | list[str]) -> None:
7575
dirs_to_create.append(base_name)
7676

7777
# Got to a single directory which does not exist
78+
# If it ends with colon, we got to the root of the drive
7879
if base_name == "":
7980
raise OSError("Script dir does not exist and can not be created: {}".format(requested_dir))
8081

src/genie_python/genie_cachannel_wrapper.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
from __future__ import absolute_import, print_function
66

7+
import os
78
import threading
89
from builtins import object
910
from collections.abc import Callable
@@ -229,6 +230,7 @@ def get_chan(name: str, timeout: float = EXIST_TIMEOUT) -> CaChannel:
229230
Raises:
230231
UnableToConnectToPVException if it was unable to connect to the channel
231232
"""
233+
232234
try:
233235
lock = CACHE_LOCK.lock
234236
except AttributeError:
@@ -279,6 +281,7 @@ def get_pv_value(
279281
ReadAccessException: If read access is denied.
280282
"""
281283
chan = CaChannelWrapper.get_chan(name)
284+
print(f"set timeout to {timeout} on {name}")
282285
chan.setTimeout(timeout)
283286
if not chan.read_access():
284287
raise ReadAccessException(name)
@@ -363,6 +366,11 @@ def connect_to_pv(ca_channel: CaChannel) -> None:
363366
Raises:
364367
UnableToConnectToPVException: If cannot connect to PV.
365368
"""
369+
if os.getenv("GITHUB_ACTIONS"):
370+
# genie_python does some PV accesses on import. To avoid them timing out and making CI
371+
# builds really slow, shortcut every PV to "non-existent" here.
372+
raise UnableToConnectToPVException("", "In CI")
373+
366374
event = Event()
367375
try:
368376
ca_channel.search_and_connect(None, CaChannelWrapper.putCB, event)

src/genie_python/genie_logging.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""Logging module for genie"""
22

3+
import getpass
34
import logging
45
import logging.config
56

@@ -93,7 +94,7 @@ def get_log_file_dir():
9394
if os.name == "nt":
9495
return os.path.join("C:", os.sep, "Instrument", "Var", "logs", "genie_python")
9596
else:
96-
return os.path.join("/tmp/{}/genie_python".format(os.getlogin()))
97+
return os.path.join("/tmp/{}/genie_python".format(getpass.getuser()))
9798

9899
@staticmethod
99100
def get_log_file_path():

tests/test_simulation.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -216,21 +216,21 @@ def test_GIVEN_running_state_WHEN_pause_run_THEN_pause_run(self):
216216

217217
def test_GIVEN_one_block_WHEN_cset_runcontrol_and_wait__true_THEN_exception(self):
218218
create_dummy_blocks(["a"])
219-
with self.assertRaisesRegexp(
219+
with self.assertRaisesRegex(
220220
Exception, "Cannot enable or disable runcontrol at the same time as setting a wait"
221221
):
222222
genie.cset(a=1, runcontrol=True, wait=True)
223223

224224
def test_GIVEN_multiple_blocks_WHEN_cset_runcontrol_THEN_exception(self):
225225
create_dummy_blocks(["a", "b"])
226-
with self.assertRaisesRegexp(
226+
with self.assertRaisesRegex(
227227
Exception, "Runcontrol and wait can only be changed for one block at a time"
228228
):
229229
genie.cset(a=1, b=2, runcontrol=True)
230230

231231
def test_GIVEN_multiple_blocks_WHEN_cset_wait_THEN_exception(self):
232232
create_dummy_blocks(["a", "b"])
233-
with self.assertRaisesRegexp(
233+
with self.assertRaisesRegex(
234234
Exception, "Runcontrol and wait can only be changed for one block at a time"
235235
):
236236
genie.cset(a=1, b=2, wait=True)
@@ -240,7 +240,7 @@ def test_GIVEN_period_WHEN_set_period_to_higher_value_THEN_exception(self):
240240
period = genie.get_number_periods()
241241

242242
# Assert
243-
with self.assertRaisesRegexp(
243+
with self.assertRaisesRegex(
244244
Exception, "Cannot set period as it is higher than the number of periods"
245245
):
246246
genie.change_period(period + 1)

tests/test_utilities.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ def test_GIVEN_invalid_json_WHEN_get_pv_THEN_list_raise(self):
282282
api = Mock()
283283
api.get_pv_value = Mock(return_value=compressed_list)
284284

285-
self.assertRaisesRegexp(
285+
self.assertRaisesRegex(
286286
PVReadException, "Can not unmarshal.*", get_json_pv_value, "name", api
287287
)
288288

@@ -301,15 +301,15 @@ def test_GIVEN_invalid_compressed_string_WHEN_get_pv_THEN_raise(self):
301301
api = Mock()
302302
api.get_pv_value = Mock(return_value=(invalid_string))
303303

304-
self.assertRaisesRegexp(
304+
self.assertRaisesRegex(
305305
PVReadException, "Can not decompress.*", get_json_pv_value, "name", api
306306
)
307307

308308
def test_GIVEN_pv_can_not_be_read_WHEN_get_pv_THEN_raise(self):
309309
api = Mock()
310310
api.get_pv_value = Mock(side_effect=Exception())
311311

312-
self.assertRaisesRegexp(PVReadException, "Can not read.*", get_json_pv_value, "name", api)
312+
self.assertRaisesRegex(PVReadException, "Can not read.*", get_json_pv_value, "name", api)
313313

314314
def test_GIVEN_unicode_with_only_ascii_WHEN_converted_THEN_no_change(self):
315315
# Arrange

0 commit comments

Comments
 (0)