Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable Ruff rule family "N" and "S" #3892

Merged
merged 73 commits into from
Aug 7, 2024
Merged
Show file tree
Hide file tree
Changes from 70 commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
c5f904c
enable ruff rule family N
DanielYang59 Jun 23, 2024
9e6aefb
fix NPY002 in code (tests to be fixed)
DanielYang59 Jun 23, 2024
6d7718a
fix NPY002 in tests
DanielYang59 Jun 23, 2024
e6b4414
replace random with np where np is imported
DanielYang59 Jun 23, 2024
5075261
fix miller index type
DanielYang59 Jun 23, 2024
560ef73
[Need Confirm] remove rnd seed and reduce distortion
DanielYang59 Jun 23, 2024
ccd484f
fix random seed
DanielYang59 Jun 23, 2024
e3cea79
correct replacement of randn with standard_normal
DanielYang59 Jun 23, 2024
39f6267
enable rule family S and format tweaks
DanielYang59 Jun 24, 2024
7f0ef83
suppress S501 error
DanielYang59 Jun 24, 2024
156bf36
suppress S105 errors
DanielYang59 Jun 24, 2024
62ede68
suppress S602
DanielYang59 Jun 24, 2024
af8af85
replace weak `sha1` hash with `sha256`
DanielYang59 Jun 24, 2024
0e19912
ignore S311 as pymatgen is not for cryptography
DanielYang59 Jun 24, 2024
e2e14d2
suppress S605 for trusted source
DanielYang59 Jun 24, 2024
26ccb85
NEED CONFIRM: fix S607 for the starting of a process with a partial e…
DanielYang59 Jun 24, 2024
33401d4
suppress S310 for trusted source
DanielYang59 Jun 24, 2024
ebb299f
suppress S608 for trusted source
DanielYang59 Jun 24, 2024
c52f162
NEED CONFIRMATION: rewrite subprocess without shell
DanielYang59 Jun 24, 2024
9d3c6da
suppress S301, but still enable it because pickle is known to have po…
DanielYang59 Jun 24, 2024
4947ff5
replace xml with defusedxml to fix S314
DanielYang59 Jun 24, 2024
8a75287
Merge branch 'master' into enable-ruff-s-npy
DanielYang59 Jun 25, 2024
a51d075
Revert "replace xml with defusedxml to fix S314"
DanielYang59 Jun 25, 2024
84e9cdd
ignore S314
DanielYang59 Jun 25, 2024
02a7979
suppress S607 in tasks.py
DanielYang59 Jun 25, 2024
abf9edd
Revert "NEED CONFIRM: fix S607 for the starting of a process with a p…
DanielYang59 Jun 26, 2024
7d09bdf
Fix DTZ003 deprecated datetime API
DanielYang59 Jun 26, 2024
8c8b3e7
Merge branch 'master' into enable-ruff-s-npy
DanielYang59 Jun 26, 2024
3cb9c71
Merge branch 'master' into enable-ruff-s-npy
DanielYang59 Jun 26, 2024
d366898
Merge branch 'master' into enable-ruff-s-npy
DanielYang59 Jul 1, 2024
ec5ea31
pre-commit auto-fixes
pre-commit-ci[bot] Jul 1, 2024
71b7af4
Merge branch 'master' into enable-ruff-s-npy
DanielYang59 Jul 3, 2024
e1b5db3
Merge branch 'master' into enable-ruff-s-npy
DanielYang59 Jul 12, 2024
732841d
update monty to fix datetime serialization
DanielYang59 Jul 13, 2024
67d1aa6
replace np.exceptions.RankWarning
DanielYang59 Jul 13, 2024
89e0d22
update monty in pyproject
DanielYang59 Jul 13, 2024
a4f2080
revert to np.RankWarning for now
DanielYang59 Jul 13, 2024
98f4501
revert accidental np.trapz change during merge
DanielYang59 Jul 13, 2024
f6a7275
pre-commit auto-fixes
pre-commit-ci[bot] Jul 13, 2024
2adac55
Merge branch 'master' into enable-ruff-s-npy
DanielYang59 Jul 15, 2024
21022c6
Merge branch 'master' into enable-ruff-s-npy
DanielYang59 Jul 17, 2024
9f3a8bc
Merge branch 'master' into enable-ruff-s-npy
DanielYang59 Jul 18, 2024
d75e0c5
Merge branch 'master' into enable-ruff-s-npy
DanielYang59 Jul 24, 2024
aa3d6cb
Merge branch 'master' into enable-ruff-s-npy
DanielYang59 Jul 28, 2024
134a11c
pre-commit auto-fixes
pre-commit-ci[bot] Jul 28, 2024
f82d0a3
Merge branch 'master' into enable-ruff-s-npy
DanielYang59 Aug 3, 2024
d0ef23d
Merge branch 'master' into enable-ruff-s-npy
DanielYang59 Aug 3, 2024
52e8735
Merge branch 'master' into enable-ruff-s-npy
DanielYang59 Aug 5, 2024
64a702a
suppress S202 for trusted source
DanielYang59 Aug 5, 2024
91b1ea6
ignore NPY201 for now
DanielYang59 Aug 5, 2024
5a923af
Revert "pre-commit auto-fixes"
DanielYang59 Aug 5, 2024
bc3caa9
pre-commit auto-fixes
pre-commit-ci[bot] Aug 5, 2024
57848ed
Merge branch 'master' into enable-ruff-s-npy
DanielYang59 Aug 5, 2024
94ca1fd
fix indentation
DanielYang59 Aug 5, 2024
638a75f
Revert "pre-commit auto-fixes"
DanielYang59 Aug 5, 2024
5723727
regenerate requirement.txt
DanielYang59 Aug 5, 2024
2cbff0b
fix indentation
DanielYang59 Aug 5, 2024
d65f4f4
rename single-letter p = subprocess.run
janosh Aug 5, 2024
de81808
replace stdlib random with numpy
DanielYang59 Aug 5, 2024
374f711
avoid assign single use rng
DanielYang59 Aug 5, 2024
2378f85
fix unit test
DanielYang59 Aug 5, 2024
0ffeac4
keep non-imperative
DanielYang59 Aug 5, 2024
fdf52f1
replace os.system with subprocess
DanielYang59 Aug 6, 2024
08ec70d
docstring and type tweaks for io.packmol
DanielYang59 Aug 6, 2024
69802bf
io.packmol format tweaks
DanielYang59 Aug 6, 2024
684520a
fix subprocess run usage for stdin file
DanielYang59 Aug 6, 2024
9370c6f
add return type in docstring
DanielYang59 Aug 6, 2024
d73aa3b
(feel free to revert) use list join over str concat
DanielYang59 Aug 6, 2024
2134e59
Merge branch 'master' into enable-ruff-s-npy
DanielYang59 Aug 6, 2024
bcf1c0b
Merge branch 'master' into enable-ruff-s-npy
DanielYang59 Aug 6, 2024
f84c906
use f-str
janosh Aug 7, 2024
701faac
map(str, box)
janosh Aug 7, 2024
33c1dcd
revert f-str
janosh Aug 7, 2024
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
7 changes: 4 additions & 3 deletions dev_scripts/potcar_scrambler.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,20 +48,21 @@ def __init__(self, potcars: Potcar | PotcarSingle) -> None:
def _rand_float_from_str_with_prec(self, input_str: str, bloat: float = 1.5) -> float:
n_prec = len(input_str.split(".")[1])
bd = max(1, bloat * abs(float(input_str))) # ensure we don't get 0
return round(bd * np.random.rand(1)[0], n_prec)
return round(bd * np.random.default_rng().random(), n_prec)

def _read_fortran_str_and_scramble(self, input_str: str, bloat: float = 1.5):
input_str = input_str.strip()
rng = np.random.default_rng()

if input_str.lower() in {"t", "f", "true", "false"}:
return bool(np.random.randint(2))
return rng.choice((True, False))

if input_str.upper() == input_str.lower() and input_str[0].isnumeric():
if "." in input_str:
return self._rand_float_from_str_with_prec(input_str, bloat=bloat)
integer = int(input_str)
fac = int(np.sign(integer)) # return int of same sign
return fac * np.random.randint(abs(max(1, int(np.ceil(bloat * integer)))))
return fac * rng.integers(abs(max(1, int(np.ceil(bloat * integer)))))
try:
float(input_str)
return self._rand_float_from_str_with_prec(input_str, bloat=bloat)
Expand Down
36 changes: 21 additions & 15 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -187,12 +187,10 @@ ignore = [
"ERA", # Check for commented-out code
"FIX", # Check for FIXME, TODO and other developer notes
"FURB", # refurb (need preview mode, too many preview errors)
"G", # validate logging format strings
"G", # Validate logging format strings
"INP", # Ban PEP-420 implicit namespace packages
"N", # pep8-naming (many var/arg names are intended)
"NPY", # NumPy-specific rules (TODO: enable this)
"N", # PEP8-naming (many var/arg names are intended)
"PTH", # Prefer pathlib over os.path
"S", # flake8-bandit (TODO: enable this)
"SLF", # Access "private" class members
"T20", # Check for print/pprint
"TD", # TODO tags related
Expand All @@ -203,24 +201,32 @@ ignore = [
"B904", # Within an except clause, raise exceptions with ...
"C408", # unnecessary-collection-call
"D105", # Missing docstring in magic method
"D205", # 1 blank line required between summary line and description
"D205", # One blank line required between summary line and description
"D212", # Multi-line docstring summary should start at the first line
"FBT001", # Boolean-typed positional argument in function definition
"FBT002", # Boolean default positional argument in function
"NPY201", # TODO: enable after migration to NumPy 2.0
"PD901", # pandas-df-variable-name
"PERF203", # try-except-in-loop
"PERF401", # manual-list-comprehension
"PLR0911", # too many return statements
"PLR0912", # too many branches
"PLR0913", # too many arguments
"PLR0915", # too many statements
"PLR2004", # magic-value-comparison TODO fix these
"PERF203", # Use of try-except in for/while loop
"PERF401", # Replace "for" loops with list comprehension
"PLR0911", # Too many return statements
"PLR0912", # Too many branches
"PLR0913", # Too many arguments
"PLR0915", # Too many statements
"PLR2004", # Magic-value-comparison TODO fix these
"PLW2901", # Outer for loop variable overwritten by inner assignment target
"PT013", # pytest-incorrect-pytest-import
"PT013", # Incorrect import of pytest
"S101", # Use of "assert"
"S110", # Log for try-except-pass
"S112", # Log for try-except-continue
"S311", # Use random module for cryptographic purposes
"S314", # Replace xml with defusedxml to avoid XML attacks
"S603", # Check source for use of "subprocess" call
"S607", # Start process with relative path
"SIM105", # Use contextlib.suppress() instead of try-except-pass
"TRY003", # Avoid specifying long messages outside the exception class
"TRY300", # Checks for return statements in try blocks
"TRY301", # Checks for raise statements within try blocks
"TRY300", # Check for return statements in try blocks
"TRY301", # Check for raise statements within try blocks
]
pydocstyle.convention = "google"
isort.required-imports = ["from __future__ import annotations"]
Expand Down
21 changes: 2 additions & 19 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,17 @@ fonttools==4.53.0
idna==3.7
# via requests
joblib==1.4.2
# via pymatgen (pyproject.toml)
kiwisolver==1.4.5
# via matplotlib
latexcodec==3.0.0
# via pybtex
matplotlib==3.9.0
# via pymatgen (pyproject.toml)
monty==2024.5.24
# via pymatgen (pyproject.toml)
monty==2024.7.30
mpmath==1.3.0
# via sympy
networkx==3.3
# via pymatgen (pyproject.toml)
numpy==2.0.0
# via
# pymatgen (pyproject.toml)
# contourpy
# matplotlib
# pandas
Expand All @@ -39,15 +34,11 @@ packaging==24.1
# matplotlib
# plotly
palettable==3.3.3
# via pymatgen (pyproject.toml)
pandas==2.2.2
# via pymatgen (pyproject.toml)
pillow==10.3.0
# via matplotlib
plotly==5.22.0
# via pymatgen (pyproject.toml)
pybtex==0.24.0
# via pymatgen (pyproject.toml)
pyparsing==3.1.2
# via matplotlib
python-dateutil==2.9.0.post0
Expand All @@ -59,30 +50,22 @@ pytz==2024.1
pyyaml==6.0.1
# via pybtex
requests==2.32.3
# via pymatgen (pyproject.toml)
ruamel-yaml==0.18.6
# via pymatgen (pyproject.toml)
ruamel-yaml-clib==0.2.8
# via ruamel-yaml
scipy==1.13.1
# via pymatgen (pyproject.toml)
six==1.16.0
# via
# pybtex
# python-dateutil
spglib==2.4.0
# via pymatgen (pyproject.toml)
spglib==2.5.0
sympy==1.12.1
# via pymatgen (pyproject.toml)
tabulate==0.9.0
# via pymatgen (pyproject.toml)
tenacity==8.4.1
# via plotly
tqdm==4.66.4
# via pymatgen (pyproject.toml)
tzdata==2024.1
# via pandas
uncertainties==3.2.1
# via pymatgen (pyproject.toml)
urllib3==2.2.2
# via requests
Original file line number Diff line number Diff line change
Expand Up @@ -993,15 +993,17 @@ def setup_test_perfect_environment(
raise ValueError("Wrong mp_symbol to setup coordination geometry")
neighb_coords = []
_points = points if points is not None else cg.points
rng = np.random.default_rng()

if randomness:
rv = np.random.random_sample(3)
rv = rng.random(3)
while norm(rv) > 1.0:
rv = np.random.random_sample(3)
rv = rng.random(3)
coords = [np.zeros(3, float) + max_random_dist * rv]
for pp in _points:
rv = np.random.random_sample(3)
rv = rng.random(3)
while norm(rv) > 1.0:
rv = np.random.random_sample(3)
rv = rng.random(3)
neighb_coords.append(np.array(pp) + max_random_dist * rv)
else:
coords = [np.zeros(3, float)]
Expand All @@ -1016,7 +1018,7 @@ def setup_test_perfect_environment(

# Scaling the test environment
if random_scale == "RANDOM":
scale = 0.1 * np.random.random_sample() + 0.95
scale = 0.1 * rng.random() + 0.95
elif random_scale == "NONE":
scale = 1.0
else:
Expand All @@ -1026,9 +1028,9 @@ def setup_test_perfect_environment(

# Rotating the test environment
if random_rotation == "RANDOM":
uu = np.random.random_sample(3) + 0.1
uu = rng.random(3) + 0.1
uu = uu / norm(uu)
theta = np.pi * np.random.random_sample()
theta = np.pi * rng.random()
cos_theta = np.cos(theta)
sin_theta = np.sin(theta)
ux = uu[0]
Expand Down Expand Up @@ -1068,7 +1070,7 @@ def setup_test_perfect_environment(

# Translating the test environment
if random_translation == "RANDOM":
translation = 10.0 * (2.0 * np.random.random_sample(3) - 1.0)
translation = 10.0 * (2.0 * rng.random(3) - 1.0)
elif random_translation == "NONE":
translation = np.zeros(3, float)
else:
Expand Down Expand Up @@ -1113,7 +1115,7 @@ def setup_random_structure(self, coordination):
bb = -0.2
coords = []
for _ in range(coordination + 1):
coords.append(aa * np.random.random_sample(3) + bb)
coords.append(aa * np.random.default_rng().random(3) + bb)
self.set_structure(
lattice=np.array(np.eye(3) * 10, float),
species=["Si"] * (coordination + 1),
Expand All @@ -1130,7 +1132,7 @@ def setup_random_indices_local_geometry(self, coordination):
"""
self.icentral_site = 0
self.indices = list(range(1, coordination + 1))
np.random.shuffle(self.indices)
np.random.default_rng().shuffle(self.indices)

def setup_ordered_indices_local_geometry(self, coordination):
"""Set up ordered indices for the local geometry, for testing purposes.
Expand Down Expand Up @@ -2049,8 +2051,9 @@ def coordination_geometry_symmetry_measures_fallback_random(
algos = []
perfect2local_maps = []
local2perfect_maps = []
rng = np.random.default_rng()
for idx in range(n_random):
perm = np.random.permutation(coordination_geometry.coordination_number)
perm = rng.permutation(coordination_geometry.coordination_number)
permutations.append(perm)
p2l = {}
l2p = {}
Expand Down
9 changes: 5 additions & 4 deletions src/pymatgen/analysis/piezo_sensitivity.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ def get_rand_BEC(self, max_charge=1):
BEC = np.zeros((n_atoms, 3, 3))
for atom, ops in enumerate(self.BEC_operations):
if ops[0] == ops[1]:
temp_tensor = Tensor(np.random.rand(3, 3) - 0.5)
temp_tensor = Tensor(np.random.default_rng().random((3, 3)) - 0.5)
temp_tensor = sum(temp_tensor.transform(symm_op) for symm_op in self.pointops[atom]) / len(
self.pointops[atom]
)
Expand Down Expand Up @@ -238,7 +238,7 @@ def get_rand_IST(self, max_force=1):
temp_tensor += op[1].transform_tensor(IST[op[0]])

if len(ops) == 0:
temp_tensor = Tensor(np.random.rand(3, 3, 3) - 0.5)
temp_tensor = Tensor(np.random.default_rng().random((3, 3, 3)) - 0.5)
for dim in range(3):
temp_tensor[dim] = (temp_tensor[dim] + temp_tensor[dim].T) / 2
temp_tensor = sum(temp_tensor.transform(symm_op) for symm_op in self.pointops[atom]) / len(
Expand Down Expand Up @@ -385,7 +385,7 @@ def get_unstable_FCM(self, max_force=1):
].T
continue

temp_tensor = Tensor(np.random.rand(3, 3) - 0.5) * max_force
temp_tensor = Tensor(np.random.default_rng().random((3, 3)) - 0.5) * max_force

temp_tensor_sum = sum(temp_tensor.transform(symm_op) for symm_op in self.sharedops[op[0]][op[1]])
temp_tensor_sum = temp_tensor_sum / (len(self.sharedops[op[0]][op[1]]))
Expand Down Expand Up @@ -484,9 +484,10 @@ def get_stable_FCM(self, fcm, fcmasum=10):

max_eig = np.max(-1 * eigs)
eig_sort = np.argsort(np.abs(eigs))
rng = np.random.default_rng()
for idx in range(3, len(eigs)):
if eigs[eig_sort[idx]] > 1e-6:
eigs[eig_sort[idx]] = -1 * max_eig * np.random.rand()
eigs[eig_sort[idx]] = -1 * max_eig * rng.random()
diag = np.real(np.eye(len(fcm)) * eigs)

fcm = np.real(np.matmul(np.matmul(vecs, diag), vecs.T))
Expand Down
6 changes: 3 additions & 3 deletions src/pymatgen/analysis/surface_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@

import copy
import itertools
import random
import warnings
from typing import TYPE_CHECKING

Expand Down Expand Up @@ -801,14 +800,15 @@ def color_palette_dict(self, alpha=0.35):
surface will be transparent.
"""
color_dict = {}
rng = np.random.default_rng()
for hkl in self.all_slab_entries:
rgb_indices = [0, 1, 2]
color = [0, 0, 0, 1]
random.shuffle(rgb_indices)
rng.shuffle(rgb_indices)
for idx, ind in enumerate(rgb_indices):
if idx == 2:
break
color[ind] = np.random.uniform(0, 1)
color[ind] = rng.uniform(0, 1)

# Get the clean (solid) colors first
clean_list = np.linspace(0, 1, len(self.all_slab_entries[hkl]))
Expand Down
6 changes: 3 additions & 3 deletions src/pymatgen/cli/pmg_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ def setup_potcars(potcar_dirs: list[str]):
dest = os.path.join(base_dir, os.path.basename(fname))
shutil.copy(fname, dest)
ext = fname.split(".")[-1]
if ext.upper() in ["Z", "GZ"]:
if ext.upper() in {"Z", "GZ"}:
with subprocess.Popen(["gunzip", dest]) as process:
process.communicate()
elif ext.upper() == "BZ2":
Expand Down Expand Up @@ -202,8 +202,8 @@ def build_bader(fortran_command="gfortran"):
cwd = os.getcwd()
state = True
try:
urlretrieve(bader_url, "bader.tar.gz")
subprocess.call(["tar", "-zxf", "bader.tar.gz"])
urlretrieve(bader_url, "bader.tar.gz") # noqa: S310
subprocess.call(["/usr/bin/tar", "-zxf", "bader.tar.gz"])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure we can hard-code /usr/bin/tar here. leaving it at tar will search everything on the user's path, not just 1 directory

Copy link
Contributor Author

@DanielYang59 DanielYang59 Aug 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was quite concerned about these changes as well (the absolute path consistency across different OS), #3892 (comment), as security is not a core concern for pymatgen (probably?). Explicitly using the absolute path could avoid PATH hijacking

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@janosh I'm still pretty concerned about commit 26ccb85 which includes using the absolute path for the following:

  • /usr/bin/gunzip
  • /usr/bin/gzip
  • /usr/bin/make
  • /usr/bin/tar
  • /bin/cp

There are pretty basic packages but owing to the huge diversities of Linux distro, I'm unsure if there would be any exception. According to ChatGPT 4o:

the Filesystem Hierarchy Standard (FHS) provides guidelines and standards for directory structures and file placements in Unix-like operating systems, including Linux. The FHS is maintained by the Linux Foundation.

Here are some relevant points from the FHS regarding the locations of these binaries:

/bin: This directory contains essential command binaries that are required for single-user mode and for all users (e.g., cp, ls, cat).

/usr/bin: This directory contains the majority of user commands. Binaries that are not essential for system boot or repair but are intended for use by all users are placed here. This includes binaries like gzip, gunzip, make, and tar.

It should be quite safe IMO.

os.chdir("bader")
subprocess.call(["cp", "makefile.osx_" + fortran_command, "makefile"])
subprocess.call(["make"])
Expand Down
17 changes: 12 additions & 5 deletions src/pymatgen/command_line/mcsqs_caller.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,11 @@ def _parse_sqs_path(path) -> Sqs:
detected_instances = len(list(path.glob("bestsqs*[0-9]*.out")))

# Convert best SQS structure to CIF file and pymatgen Structure
with Popen("str2cif < bestsqs.out > bestsqs.cif", shell=True, cwd=path) as process:
with (
open(os.path.join(path, "bestsqs.out")) as input_file,
open(os.path.join(path, "bestsqs.cif"), "w") as output_file,
):
process = Popen(["str2cif"], stdin=input_file, stdout=output_file, cwd=path)
process.communicate()

with warnings.catch_warnings():
Expand All @@ -197,12 +201,15 @@ def _parse_sqs_path(path) -> Sqs:
all_sqs = []

for idx in range(detected_instances):
sqs_out = f"bestsqs{idx + 1}.out"
sqs_cif = f"bestsqs{idx + 1}.cif"
corr_out = f"bestcorr{idx + 1}.out"
with Popen(f"str2cif < {sqs_out} > {sqs_cif}", shell=True, cwd=path) as process:
sqs_out = os.path.join(path, f"bestsqs{idx + 1}.out")
sqs_cif = os.path.join(path, f"bestsqs{idx + 1}.cif")

with open(sqs_out) as input_file, open(sqs_cif, "w") as output_file:
process = Popen(["str2cif"], stdin=input_file, stdout=output_file, cwd=path)
process.communicate()
sqs = Structure.from_file(path / sqs_out)

corr_out = f"bestcorr{idx + 1}.out"
with open(path / corr_out) as file:
lines = file.readlines()

Expand Down
4 changes: 2 additions & 2 deletions src/pymatgen/core/sites.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,8 @@ def __getitem__(self, el: Element) -> float: # type: ignore[override]

def __eq__(self, other: object) -> bool:
"""Site is equal to another site if the species and occupancies are the
same, and the coordinates are the same to some tolerance. numpy
function `allclose` is used to determine if coordinates are close.
same, and the coordinates are the same to some tolerance. `numpy.allclose`
is used to determine if coordinates are close.
"""
if not isinstance(other, type(self)):
return NotImplemented
Expand Down
Loading