diff --git a/htcondor_jobs/handles.py b/htcondor_jobs/handles.py index 29d9eb1..7b6b439 100644 --- a/htcondor_jobs/handles.py +++ b/htcondor_jobs/handles.py @@ -194,7 +194,9 @@ def edit(self, attr: str, value: Union[str, int, float]) -> classad.ClassAd: logger.info( f"Executing edit {attr} = {value} against schedd {self.schedd} with constraint {cs}" ) - return self.schedd.edit(cs, attr, value) + if isinstance(value, str): + value = f'"{value}"' + return self.schedd.edit(cs, attr, str(value)) class ConstraintHandle(Handle): diff --git a/htcondor_jobs/submit.py b/htcondor_jobs/submit.py index 370afc1..4f3a9f2 100644 --- a/htcondor_jobs/submit.py +++ b/htcondor_jobs/submit.py @@ -40,7 +40,7 @@ def submit( itemdata: Optional[Iterable[T_ITEMDATA_ELEMENT]] = None, collector: Optional[str] = None, scheduler: Optional[str] = None, -) -> handles.Handle: +) -> handles.ConstraintHandle: with Transaction(collector=collector, scheduler=scheduler) as txn: handle = txn.submit(description, count, itemdata) @@ -62,7 +62,7 @@ def submit( description: descriptions.SubmitDescription, count: Optional[int] = 1, itemdata: Optional[Iterable[T_ITEMDATA_ELEMENT]] = None, - ) -> handles.Handle: + ) -> handles.ConstraintHandle: if any((self._schedd is None, self._txn is None)): raise exceptions.UninitializedTransaction( "the transaction has not been initialized (use it as a context manager)" diff --git a/tests/conftest.py b/tests/conftest.py index effa924..08bb40b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -15,9 +15,15 @@ import pytest +import htcondor_jobs as jobs from htcondor_jobs.locate import SCHEDD_CACHE @pytest.fixture(scope="function", autouse=True) def clear_schedd_cache(): SCHEDD_CACHE.clear() + + +@pytest.fixture(scope="function") +def long_sleep(): + return jobs.SubmitDescription(executable="/bin/sleep", args="5m") diff --git a/tests/integration/test_handles/__init__.py b/tests/integration/test_handles/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/integration/test_workflows.py b/tests/integration/test_handles/test_actions.py similarity index 64% rename from tests/integration/test_workflows.py rename to tests/integration/test_handles/test_actions.py index e9cace8..953e550 100644 --- a/tests/integration/test_workflows.py +++ b/tests/integration/test_handles/test_actions.py @@ -15,15 +15,27 @@ import pytest - import htcondor_jobs as jobs -def test_submit_hold_query(): - desc = jobs.SubmitDescription(executable="/bin/sleep", args="5m") +def get_status(handle): + ad = next(handle.query(projection=["JobStatus"])) + return ad["JobStatus"] + + +def test_hold(long_sleep): + handle = jobs.submit(long_sleep, count=1) - handle = jobs.submit(desc, count=1) handle.hold() - ad = next(handle.query(projection=["JobStatus"])) - assert ad["JobStatus"] == jobs.JobStatus.Held + status = get_status(handle) + assert status == jobs.JobStatus.Held + + +@pytest.mark.parametrize( + "action", ["remove", "hold", "release", "pause", "resume", "vacate"] +) +def test_actions_will_execute(long_sleep, action): + handle = jobs.submit(long_sleep, count=1) + + getattr(handle, action)() diff --git a/tests/integration/test_handles/test_combining_handles.py b/tests/integration/test_handles/test_combining_handles.py new file mode 100644 index 0000000..e3eb5dd --- /dev/null +++ b/tests/integration/test_handles/test_combining_handles.py @@ -0,0 +1,36 @@ +# Copyright 2019 HTCondor Team, Computer Sciences Department, +# University of Wisconsin-Madison, WI. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import pytest + +import htcondor_jobs as jobs + + +def test_and_of_cluster_handles_gives_right_number_of_jobs_in_query(long_sleep): + a = jobs.submit(long_sleep, count=1) + b = jobs.submit(long_sleep, count=1) + + num_jobs = len(list((a & b).query())) + + assert num_jobs == 0 + + +def test_or_of_cluster_handles_gives_right_number_of_jobs_in_query(long_sleep): + a = jobs.submit(long_sleep, count=1) + b = jobs.submit(long_sleep, count=1) + + num_jobs = len(list((a | b).query())) + + assert num_jobs == 2 diff --git a/tests/integration/test_handles/test_edit.py b/tests/integration/test_handles/test_edit.py new file mode 100644 index 0000000..340c5e8 --- /dev/null +++ b/tests/integration/test_handles/test_edit.py @@ -0,0 +1,39 @@ +# Copyright 2019 HTCondor Team, Computer Sciences Department, +# University of Wisconsin-Madison, WI. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import pytest + +import htcondor_jobs as jobs + + +def get_job_attr(handle, attr): + ad = next(handle.query(projection=[attr])) + return ad[attr] + + +def test_change_request_memory(long_sleep): + handle = jobs.submit(long_sleep, count=1) + + handle.edit("RequestMemory", 12345) + + assert get_job_attr(handle, "RequestMemory") == 12345 + + +def test_change_executable(long_sleep): + handle = jobs.submit(long_sleep, count=1) + + handle.edit("Executable", "hello") + + assert get_job_attr(handle, "Executable") == "hello"