Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ exclude: ^docs

repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.14.2
rev: v0.15.7
hooks:
- id: ruff-check
args: [--fix, --ignore, D]
Expand All @@ -20,7 +20,7 @@ repos:
- id: trailing-whitespace

- repo: https://github.com/codespell-project/codespell
rev: v2.4.1
rev: v2.4.2
hooks:
- id: codespell
stages: [commit, commit-msg]
Expand Down
1 change: 1 addition & 0 deletions docs_rst/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@
"python": ("https://docs.python.org/3", None),
}


# AJ: a hack found online to get __init__ to show up in docs
def skip(app, what, name, obj, skip, options):
if name == "__init__":
Expand Down
6 changes: 4 additions & 2 deletions fireworks/core/launchpad.py
Original file line number Diff line number Diff line change
Expand Up @@ -2026,14 +2026,16 @@ def recover_offline(self, launch_id, ignore_errors=False, print_errors=False):
)
fw_id = launch["fw_id"]
f = self.fireworks.find_one_and_update(
{"fw_id": fw_id}, {"$set": {"state": "RUNNING", "updated_on": datetime.datetime.now(datetime.timezone.utc)}}
{"fw_id": fw_id},
{"$set": {"state": "RUNNING", "updated_on": datetime.datetime.now(datetime.timezone.utc)}},
)
if f:
self._refresh_wf(fw_id)

# update the updated_on
self.offline_runs.update_one(
{"launch_id": launch_id}, {"$set": {"updated_on": datetime.datetime.now(datetime.timezone.utc).isoformat()}}
{"launch_id": launch_id},
{"$set": {"updated_on": datetime.datetime.now(datetime.timezone.utc).isoformat()}},
)
return None

Expand Down
2 changes: 1 addition & 1 deletion fireworks/core/rocket.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import shutil
import traceback
from threading import Event, Thread, current_thread
from typing import TYPE_CHECKING, IO
from typing import IO, TYPE_CHECKING

from monty.io import zopen
from monty.os.path import zpath
Expand Down
9 changes: 4 additions & 5 deletions fireworks/core/rocket_launcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ def get_fworker(fworker):
return my_fwkr


def launch_rocket(launchpad, fworker=None, fw_id=None, strm_lvl=STREAM_LOGLEVEL,
pdb_on_exception=False, err_file=None):
def launch_rocket(launchpad, fworker=None, fw_id=None, strm_lvl=STREAM_LOGLEVEL, pdb_on_exception=False, err_file=None):
"""Run a single rocket in the current directory.

Args:
Expand Down Expand Up @@ -107,9 +106,9 @@ def time_ok():
os.chdir(launcher_dir)
if local_redirect:
with redirect_local() as err_file:
rocket_ran = launch_rocket(launchpad, fworker, strm_lvl=strm_lvl,
pdb_on_exception=pdb_on_exception,
err_file=err_file[1])
rocket_ran = launch_rocket(
launchpad, fworker, strm_lvl=strm_lvl, pdb_on_exception=pdb_on_exception, err_file=err_file[1]
)
else:
rocket_ran = launch_rocket(launchpad, fworker, strm_lvl=strm_lvl, pdb_on_exception=pdb_on_exception)

Expand Down
2 changes: 1 addition & 1 deletion fireworks/core/tests/test_firework.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ class FiretaskPickleTest(unittest.TestCase):
def setUp(self) -> None:
self.task = PickleTask(test=0)
self.pkl_task = pickle.dumps(self.task)
self.upkl_task = pickle.loads(self.pkl_task) # noqa: S301
self.upkl_task = pickle.loads(self.pkl_task)

def test_init(self) -> None:
assert isinstance(self.upkl_task, PickleTask)
Expand Down
34 changes: 17 additions & 17 deletions fireworks/core/tests/test_launchpad.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def _is_mongomock() -> bool:
client = fireworks.fw_config.MongoClient()
# Check if the client is from mongomock
return "mongomock" in str(type(client).__module__)
except Exception: # noqa: BLE001
except Exception:
return False


Expand All @@ -72,7 +72,7 @@ def setUpClass(cls) -> None:
except OperationFailure:
pass # User doesn't exist, that's fine
client.not_the_admin_db.command({"createUser": "my-user", "pwd": "my-password", "roles": ["dbOwner"]})
except Exception: # noqa: BLE001
except Exception:
raise unittest.SkipTest("MongoDB is not running or authentication not available")

@classmethod
Expand All @@ -81,12 +81,12 @@ def tearDownClass(cls) -> None:
try:
client = fireworks.fw_config.MongoClient()
client.drop_database("not_the_admin_db")
except Exception: # noqa: BLE001, S110
except Exception:
pass # Database cleanup - OK to silently fail

def test_no_admin_privileges_for_plebs(self) -> None:
"""Normal users can not authenticate against the admin db."""
lp = LaunchPad(name="admin", username="my-user", password="my-password", authsource="admin") # noqa: S106
lp = LaunchPad(name="admin", username="my-user", password="my-password", authsource="admin")
with pytest.raises(OperationFailure):
lp.db.collection.count_documents({})

Expand All @@ -97,7 +97,7 @@ def test_authenticating_to_users_db(self) -> None:
lp = LaunchPad(
name="not_the_admin_db",
username="my-user",
password="my-password", # noqa: S106
password="my-password",
authsource="not_the_admin_db",
)
lp.db.collection.count_documents({})
Expand All @@ -106,7 +106,7 @@ def test_authsource_inferred_from_db_name(self) -> None:
"""The default behavior is to authenticate against the db that the user
is trying to access.
"""
lp = LaunchPad(name="not_the_admin_db", username="my-user", password="my-password") # noqa: S106
lp = LaunchPad(name="not_the_admin_db", username="my-user", password="my-password")
lp.db.collection.count_documents({})


Expand All @@ -117,7 +117,7 @@ def setUpClass(cls) -> None:
try:
cls.lp = LaunchPad(name=TEST_DB_NAME, strm_lvl="ERROR")
cls.lp.reset(password=None, require_password=False)
except Exception: # noqa: BLE001
except Exception:
raise unittest.SkipTest("MongoDB is not running in localhost:27017! Skipping tests.")

@classmethod
Expand Down Expand Up @@ -222,7 +222,7 @@ def setUpClass(cls) -> None:
try:
cls.lp = LaunchPad(name=TEST_DB_NAME, strm_lvl="ERROR")
cls.lp.reset(password=None, require_password=False)
except Exception: # noqa: BLE001
except Exception:
raise unittest.SkipTest("MongoDB is not running in localhost:27017! Skipping tests.")

@classmethod
Expand Down Expand Up @@ -606,7 +606,7 @@ def setUpClass(cls) -> None:
try:
cls.lp = LaunchPad(name=TEST_DB_NAME, strm_lvl="ERROR")
cls.lp.reset(password=None, require_password=False)
except Exception: # noqa: BLE001
except Exception:
raise unittest.SkipTest("MongoDB is not running in localhost:27017! Skipping tests.")

@classmethod
Expand Down Expand Up @@ -719,7 +719,7 @@ def setUpClass(cls) -> None:
try:
cls.lp = LaunchPad(name=TEST_DB_NAME, strm_lvl="ERROR")
cls.lp.reset(password=None, require_password=False)
except Exception: # noqa: BLE001
except Exception:
raise unittest.SkipTest("MongoDB is not running in localhost:27017! Skipping tests.")

@classmethod
Expand Down Expand Up @@ -1018,7 +1018,7 @@ def setUpClass(cls) -> None:
try:
cls.lp = LaunchPad(name=TEST_DB_NAME, strm_lvl="ERROR")
cls.lp.reset(password=None, require_password=False)
except Exception: # noqa: BLE001
except Exception:
raise unittest.SkipTest("MongoDB is not running in localhost:27017! Skipping tests.")

@classmethod
Expand Down Expand Up @@ -1125,7 +1125,7 @@ def test_task_level_rerun_wrong_state(self) -> None:
self.lp.rerun_fw(1, recover_launch="last")

def test_task_level_rerun_no_recovery_info(self) -> None:
self.lp.add_wf(Firework(ScriptTask.from_str('echo')))
self.lp.add_wf(Firework(ScriptTask.from_str("echo")))
launch_rocket(self.lp, self.fworker, fw_id=2)
with pytest.raises(ValueError, match="No recovery info found in launch 1"):
self.lp.rerun_fw(2, recover_launch="last")
Expand All @@ -1143,7 +1143,7 @@ def setUpClass(cls) -> None:
try:
cls.lp = LaunchPad(name=TEST_DB_NAME, strm_lvl="ERROR")
cls.lp.reset(password=None, require_password=False)
except Exception: # noqa: BLE001
except Exception:
raise unittest.SkipTest("MongoDB is not running in localhost:27017! Skipping tests.")

@classmethod
Expand Down Expand Up @@ -1208,7 +1208,7 @@ def test_fix_db_inconsistencies_completed(self) -> None:
assert "SlowAdditionTask" in child_fw.spec
assert "WaitWFLockTask" not in child_fw.spec

self.lp._refresh_wf(fw_id=2) # noqa: SLF001
self.lp._refresh_wf(fw_id=2)

child_fw = self.lp.get_fw_by_id(3)

Expand Down Expand Up @@ -1247,7 +1247,7 @@ def test_fix_db_inconsistencies_fizzled(self) -> None:
assert "SlowAdditionTask" in child_fw.spec
assert "WaitWFLockTask" not in child_fw.spec

self.lp._refresh_wf(fw_id=2) # noqa: SLF001
self.lp._refresh_wf(fw_id=2)

fast_fw = self.lp.get_fw_by_id(2)

Expand All @@ -1262,7 +1262,7 @@ def setUpClass(cls) -> None:
try:
cls.lp = LaunchPad(name=TEST_DB_NAME, strm_lvl="ERROR")
cls.lp.reset(password=None, require_password=False)
except Exception: # noqa: BLE001
except Exception:
raise unittest.SkipTest("MongoDB is not running in localhost:27017! Skipping tests.")

@classmethod
Expand Down Expand Up @@ -1343,7 +1343,7 @@ def setUpClass(cls) -> None:
try:
cls.lp = LaunchPad(name=TEST_DB_NAME, strm_lvl="ERROR")
cls.lp.reset(password=None, require_password=False)
except Exception: # noqa: BLE001
except Exception:
raise unittest.SkipTest("MongoDB is not running in localhost:27017! Skipping tests.")

@classmethod
Expand Down
2 changes: 1 addition & 1 deletion fireworks/features/multi_launcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ def split_node_lists(num_jobs, total_node_list=None, ppn=24):
return node_lists, sub_nproc_list


# TODO: why is loglvl a required parameter??? Also nlaunches and sleep_time could have a sensible default?? # noqa: E501, FIX002, TD002, TD003
# TODO: why is loglvl a required parameter??? Also nlaunches and sleep_time could have a sensible default?? # noqa: E501
def launch_multiprocess(
launchpad,
fworker,
Expand Down
3 changes: 2 additions & 1 deletion fireworks/flask_site/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,10 @@ def _addq_WF(q):
@app.template_filter("datetime")
def datetime(value):
import datetime as dt

try:
date = dt.datetime.strptime(value, "%Y-%m-%dT%H:%M:%S.%f%z")
except ValueError: #backwards comptability
except ValueError: # backwards compatibility
date = dt.datetime.strptime(value, "%Y-%m-%dT%H:%M:%S.%f")
return date.strftime("%m/%d/%Y")

Expand Down
1 change: 1 addition & 0 deletions fireworks/fw_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import pymongo
from monty.design_patterns import singleton
from monty.serialization import dumpfn, loadfn

from fireworks.utilities.exceptions import FWConfigurationError

__author__ = "Anubhav Jain"
Expand Down
19 changes: 18 additions & 1 deletion fireworks/tests/master_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
completed properly.
"""

import datetime
import unittest

import pytest
Expand All @@ -10,7 +11,7 @@
from fireworks.core.firework import Workflow
from fireworks.user_objects.firetasks.script_task import ScriptTask
from fireworks.user_objects.queue_adapters.common_adapter import CommonAdapter
from fireworks.utilities.fw_serializers import load_object
from fireworks.utilities.fw_serializers import load_object, reconstitute_dates

__author__ = "Anubhav Jain"
__copyright__ = "Copyright 2013, The Materials Project"
Expand Down Expand Up @@ -99,3 +100,19 @@ def test_recursive_deserialize(self) -> None:
"defuse_children": False,
}
FWAction.from_dict(my_dict)


@pytest.mark.parametrize(
("input_str", "expected"),
[
("2000-02-01", "2000-02-01"),
("2024-01-15", "2024-01-15"),
("1970-01-01", "1970-01-01"),
("not-a-date", "not-a-date"),
("2014-10-14T00:56:27.758673", datetime.datetime(2014, 10, 14, 0, 56, 27, 758673)),
("2024-03-15T08:30:00", datetime.datetime(2024, 3, 15, 8, 30)),
],
)
def test_reconstitute_dates_preserves_date_only_strings(input_str: str, expected: str | datetime.datetime) -> None:
"""Regression test for #570: date-only strings must not become datetime objects."""
assert reconstitute_dates(input_str) == expected
1 change: 0 additions & 1 deletion fireworks/utilities/filepad.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import zlib
from typing import TYPE_CHECKING

from uuid import uuid4
import gridfs
from bson.objectid import ObjectId
from monty.json import MSONable
Expand Down
24 changes: 10 additions & 14 deletions fireworks/utilities/fw_serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@
USER_PACKAGES,
YAML_STYLE,
)
from fireworks.utilities.exceptions import FWFormatError, FWSerializationError
from fireworks.utilities.fw_utilities import get_fw_logger
from fireworks.utilities.exceptions import FWSerializationError, FWFormatError

__author__ = "Anubhav Jain"
__copyright__ = "Copyright 2012, The Materials Project"
Expand Down Expand Up @@ -134,13 +134,7 @@ def _recursive_load(obj):
return [_recursive_load(v) for v in obj]

if isinstance(obj, str):
try:
# convert String to datetime if really datetime
return reconstitute_dates(obj)
except Exception:
# convert unicode to ASCII if not really unicode
if obj == obj.encode("ascii", "ignore"):
return str(obj)
return reconstitute_dates(obj)

return obj

Expand Down Expand Up @@ -451,17 +445,19 @@ def reconstitute_dates(obj_dict):
if isinstance(obj_dict, (list, tuple)):
return [reconstitute_dates(v) for v in obj_dict]

if isinstance(obj_dict, str):

if isinstance(obj_dict, str) and "T" in obj_dict:
# only attempt datetime parsing for strings containing 'T' (ISO 8601
# date-time separator) to avoid converting date-only or version-like
# strings such as '2000-02-01' into datetime objects (see #570)
for method, args in [
(datetime.datetime.fromisoformat, tuple()),
(datetime.datetime.fromisoformat, ()),
(datetime.datetime.strptime, ("%Y-%m-%dT%H:%M:%S.%f",)),
(datetime.datetime.strptime, ("%Y-%m-%dT%H:%M:%S", )),
(datetime.datetime.strptime, ("%Y-%m-%dT%H:%M:%S",)),
]:
try:
return method(obj_dict, *args)
except Exception:
pass
except (ValueError, TypeError):
continue
return obj_dict


Expand Down
6 changes: 3 additions & 3 deletions fireworks/utilities/fw_utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ def get_path():
full_path = get_path()
if os.path.exists(full_path):
full_path = None
time.sleep(random.random() / 3 + 0.1) # noqa: S311 (pseudo-random sufficient for retry timing)
time.sleep(random.random() / 3 + 0.1)
continue
try:
os.mkdir(full_path)
Expand Down Expand Up @@ -252,10 +252,10 @@ def explicit_serialize(o):
"""Mark a class for explicit serialization by adding _fw_name attribute."""
module_name = o.__module__
if module_name == "__main__":
import __main__ # noqa: PLC0415
import __main__

module_name = os.path.splitext(os.path.basename(__main__.__file__))[0]
o._fw_name = f"{{{{{module_name}.{o.__name__}}}}}" # noqa: SLF001
o._fw_name = f"{{{{{module_name}.{o.__name__}}}}}"
return o


Expand Down
2 changes: 1 addition & 1 deletion fireworks/utilities/visualize.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def plot_wf(
fontsize (int): font size for the node label.
"""
try:
import matplotlib.pyplot as plt # noqa: PLC0415
import matplotlib.pyplot as plt
except ImportError:
raise SystemExit("Install matplotlib. Exiting.")

Expand Down
Loading
Loading