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

Fix ruff FURB192 #3785

Merged
merged 8 commits into from
Apr 25, 2024
Merged

Fix ruff FURB192 #3785

merged 8 commits into from
Apr 25, 2024

Conversation

janosh
Copy link
Member

@janosh janosh commented Apr 25, 2024

@janosh janosh added the linting Linting and quality assurance label Apr 25, 2024
@janosh janosh enabled auto-merge (squash) April 25, 2024 19:07
Copy link

coderabbitai bot commented Apr 25, 2024

Walkthrough

The updates involve modernizing Python syntax across multiple files, enhancing code readability and efficiency. Key changes include upgrading dependency versions in pre-commit hooks, streamlining imports, refining variable names for clarity, and adopting f-strings for string formatting. Improvements also focus on optimizing logic in parsing and data handling functions, particularly within various modules related to materials science and computational chemistry software.

Changes

Files Summary of Changes
.pre-commit-config.yaml Updated versions of ruff-pre-commit, mirrors-mypy, and pyright-python.
dev_scripts/update_pt_data.py Switched to direct import of defaultdict from collections, replacing collections.defaultdict.
pymatgen/analysis/..., pymatgen/core/..., pymatgen/electronic_structure/..., pymatgen/entries/... Replaced collections.defaultdict with defaultdict for enhanced readability.
pymatgen/analysis/diffraction/neutron.py, pymatgen/analysis/diffraction/xrd.py Renamed variables for clarity: recip_latt to recip_lattice and dwfactors/_dwfactors to dw_factors/_dw_factors.
pymatgen/analysis/dimensionality.py Modified to convert dimensionality to a string with "D" suffix using f-strings.
pymatgen/analysis/nmr.py, pymatgen/analysis/structure_matcher.py, pymatgen/core/surface.py Replaced sorted with min for efficiency in selection processes.
pymatgen/analysis/topological/spillage.py Updated variable names and print statements for clarity in overlap_so_spinpol method.
pymatgen/apps/borg/hive.py Revised file selection and search string construction logic in assimilate method.
Various files across pymatgen/command_line/..., pymatgen/core/..., pymatgen/io/... Implemented f-strings for better readability and efficiency.
pymatgen/electronic_structure/boltztrap.py, pymatgen/electronic_structure/boltztrap2.py Renamed variables for clarity in file operations and property plotting.
pymatgen/io/... (multiple files) Enhanced parsing logic and variable assignments using modern Python features like the walrus operator.
pymatgen/io/vasp/... Refactored file and DOS parsing, and INCAR settings adjustment for improved accuracy and flexibility.

This table summarizes the changes made across various files, focusing on enhancements in code quality and maintenance.


Recent Review Details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits Files that changed from the base of the PR and between f52c921 and 4f890f6.
Files selected for processing (55)
  • .pre-commit-config.yaml (3 hunks)
  • dev_scripts/update_pt_data.py (3 hunks)
  • pymatgen/analysis/bond_valence.py (4 hunks)
  • pymatgen/analysis/diffraction/core.py (3 hunks)
  • pymatgen/analysis/diffraction/neutron.py (3 hunks)
  • pymatgen/analysis/diffraction/xrd.py (4 hunks)
  • pymatgen/analysis/dimensionality.py (3 hunks)
  • pymatgen/analysis/disorder.py (2 hunks)
  • pymatgen/analysis/nmr.py (1 hunks)
  • pymatgen/analysis/phase_diagram.py (3 hunks)
  • pymatgen/analysis/structure_analyzer.py (3 hunks)
  • pymatgen/analysis/structure_matcher.py (1 hunks)
  • pymatgen/analysis/topological/spillage.py (2 hunks)
  • pymatgen/analysis/xps.py (2 hunks)
  • pymatgen/apps/borg/hive.py (2 hunks)
  • pymatgen/command_line/critic2_caller.py (1 hunks)
  • pymatgen/command_line/gulp_caller.py (3 hunks)
  • pymatgen/command_line/vampire_caller.py (2 hunks)
  • pymatgen/core/bonds.py (2 hunks)
  • pymatgen/core/composition.py (8 hunks)
  • pymatgen/core/interface.py (2 hunks)
  • pymatgen/core/ion.py (1 hunks)
  • pymatgen/core/lattice.py (6 hunks)
  • pymatgen/core/operations.py (1 hunks)
  • pymatgen/core/structure.py (12 hunks)
  • pymatgen/core/surface.py (1 hunks)
  • pymatgen/core/tensors.py (1 hunks)
  • pymatgen/core/units.py (5 hunks)
  • pymatgen/electronic_structure/bandstructure.py (7 hunks)
  • pymatgen/electronic_structure/boltztrap.py (3 hunks)
  • pymatgen/electronic_structure/boltztrap2.py (3 hunks)
  • pymatgen/electronic_structure/core.py (1 hunks)
  • pymatgen/electronic_structure/plotter.py (14 hunks)
  • pymatgen/entries/correction_calculator.py (1 hunks)
  • pymatgen/entries/entry_tools.py (2 hunks)
  • pymatgen/ext/matproj_legacy.py (1 hunks)
  • pymatgen/io/abinit/inputs.py (2 hunks)
  • pymatgen/io/adf.py (4 hunks)
  • pymatgen/io/aims/inputs.py (2 hunks)
  • pymatgen/io/cif.py (2 hunks)
  • pymatgen/io/common.py (1 hunks)
  • pymatgen/io/cp2k/inputs.py (1 hunks)
  • pymatgen/io/cp2k/utils.py (1 hunks)
  • pymatgen/io/feff/outputs.py (3 hunks)
  • pymatgen/io/gaussian.py (4 hunks)
  • pymatgen/io/lammps/data.py (2 hunks)
  • pymatgen/io/lammps/inputs.py (1 hunks)
  • pymatgen/io/lobster/inputs.py (2 hunks)
  • pymatgen/io/lobster/lobsterenv.py (1 hunks)
  • pymatgen/io/lobster/outputs.py (2 hunks)
  • pymatgen/io/nwchem.py (4 hunks)
  • pymatgen/io/pwscf.py (1 hunks)
  • pymatgen/io/vasp/inputs.py (2 hunks)
  • pymatgen/io/vasp/outputs.py (6 hunks)
  • pymatgen/io/vasp/sets.py (3 hunks)
Files not processed due to max files limit (16)
  • pymatgen/io/xcrysden.py
  • pymatgen/io/xyz.py
  • pymatgen/io/zeopp.py
  • pymatgen/symmetry/maggroups.py
  • pymatgen/symmetry/settings.py
  • pymatgen/util/coord.py
  • pymatgen/util/string.py
  • tests/analysis/chemenv/connectivity/test_connected_components.py
  • tests/analysis/test_surface_analysis.py
  • tests/core/test_lattice.py
  • tests/files/.pytest-split-durations
  • tests/io/abinit/test_pseudos.py
  • tests/io/cp2k/test_sets.py
  • tests/io/lammps/test_data.py
  • tests/io/test_cif.py
  • tests/io/vasp/test_outputs.py
Files skipped from review due to trivial changes (7)
  • .pre-commit-config.yaml
  • pymatgen/analysis/diffraction/neutron.py
  • pymatgen/command_line/critic2_caller.py
  • pymatgen/command_line/vampire_caller.py
  • pymatgen/io/cif.py
  • pymatgen/io/cp2k/inputs.py
  • pymatgen/io/lammps/inputs.py
Additional comments not posted (98)
pymatgen/analysis/disorder.py (2)

6-6: Optimized import of defaultdict directly from collections.


27-28: Usage of defaultdict is consistent with the new import statement.

pymatgen/analysis/xps.py (2)

22-22: Optimized import of defaultdict directly from collections.


52-52: Usage of defaultdict is consistent with the new import statement.

pymatgen/io/cp2k/utils.py (1)

90-90: Updated regex pattern to correctly handle variable substitution in the preprocessor function.

pymatgen/core/bonds.py (2)

10-10: Optimized import of defaultdict directly from collections.


23-23: Usage of defaultdict is consistent with the new import statement.

pymatgen/analysis/nmr.py (1)

168-168: Optimized the selection of the minimum absolute value in the V_xx method using min instead of sorted.

pymatgen/analysis/diffraction/core.py (2)

6-6: Optimized import of defaultdict directly from collections.


218-218: Optimized the comparison logic in the is_perm function using NumPy functions for improved efficiency.

pymatgen/analysis/topological/spillage.py (1)

203-211: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [206-227]

Updated variable names and print statements in the overlap_so_spinpol method for clarity.

dev_scripts/update_pt_data.py (2)

157-157: Direct import of defaultdict used appropriately.


280-280: Usage of defaultdict(list) is appropriate for managing lists of ionization energies.

pymatgen/analysis/diffraction/xrd.py (2)

162-162: Renamed variable recip_latt to recip_lattice for clarity.


175-175: Renamed variable _dwfactors to _dw_factors for clarity.

pymatgen/entries/entry_tools.py (2)

15-15: Added direct import for defaultdict from collections.


118-118: Replaced collections.defaultdict with defaultdict following the direct import.

pymatgen/core/ion.py (4)

58-58: Updated to use f-string for charge calculation.


60-60: Updated to use f-string for charge calculation.


62-63: Updated to use f-string for charge calculation.


70-70: Updated to use f-string for charge calculation.

pymatgen/io/feff/outputs.py (4)

67-68: Renamed variables pot_read_start and pot_read_end for clarity.


75-75: Adjusted file path for pot.inp using regex substitution.


91-91: Renamed variable pot_string to pot_string for clarity.


98-100: Renamed variable e_fermi to e_fermi for clarity.

pymatgen/electronic_structure/core.py (1)

221-226: Variable renaming enhances clarity and maintains existing logic.

pymatgen/apps/borg/hive.py (1)

127-128: Using max instead of sorted for selecting the last file alphabetically is more efficient.

pymatgen/io/common.py (1)

264-271: Renaming the variable to total_spin_dens improves clarity and the calculations are correctly adjusted.

pymatgen/io/pwscf.py (2)

462-465: Parameter renaming from numstr to num_str improves readability and adheres to Python naming conventions.


473-473: Use of f-string for error messages enhances readability and is consistent with modern Python practices.

pymatgen/entries/correction_calculator.py (1)

409-409: Use of f-string for filename construction enhances readability and maintainability.

pymatgen/analysis/bond_valence.py (1)

8-8: Direct import of defaultdict simplifies the import statements and enhances code readability.

pymatgen/analysis/dimensionality.py (3)

350-350: Using f-strings for dimensionality output enhances readability and ensures consistent formatting.


364-364: Using f-strings for dimensionality output enhances readability and ensures consistent formatting.


375-375: Using f-strings for dimensionality output enhances readability and ensures consistent formatting.

pymatgen/analysis/structure_analyzer.py (3)

6-6: Optimized import of defaultdict directly from collections.


230-230: Use of defaultdict for initializing data enhances readability and prevents key errors.


445-445: Use of defaultdict in parse_oxide method simplifies accumulation of species occurrences.

pymatgen/io/aims/inputs.py (2)

509-509: Use of f-string for creating a header line enhances readability and maintainability.


546-546: Modification of condition check to use is False instead of not in improves clarity and correctness.

pymatgen/core/operations.py (1)

406-407: Renaming variable m to matrix enhances code readability and clarity.

pymatgen/core/units.py (5)

13-13: Direct import of defaultdict from collections simplifies the import statements and enhances code readability.


179-179: Using defaultdict for initializing unit dictionary simplifies handling of default values and improves code maintainability.


191-191: Utilization of defaultdict in __mul__ method ensures that the unit dictionary handles non-existent keys gracefully, improving robustness.


199-199: Application of defaultdict in __truediv__ method aids in managing unit calculations more effectively, enhancing code reliability.


232-232: Adoption of defaultdict in as_base_units method facilitates complex unit conversions by automatically handling missing units, thus improving the function's reliability.

pymatgen/command_line/gulp_caller.py (2)

290-290: Improved string formatting using f-strings for lattice parameters enhances readability and maintainability.


697-706: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [676-703]

Enhanced string concatenation using f-strings in the run method improves readability and maintainability. Verify that the output format aligns with expected results.

pymatgen/io/adf.py (2)

692-701: Ensure consistent handling of run types in the parsing logic.

Verify that all potential run types are handled correctly and that the None assignment for the 'CREATE' run type is intentional and documented.


725-745: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [717-742]

Refactor energy and structure parsing logic for 'GeometryOptimization' run type.

-                    match = cycle_patt.search(line)
-                    if match:
-                        cycle = int(match.group(1))
-                        if cycle <= 0:
-                            raise AdfOutputError(f"Wrong {cycle=}")
-                        if cycle > last_cycle:
-                            parse_cycle = True
-                            last_cycle = cycle
-                        else:
-                            parse_final = True
-                    elif parse_cycle:
-                        match = coord_patt.search(line)
-                        if match:
-                            sites.append([match.groups()[1], list(map(float, match.groups()[2:]))])
-                        else:
-                            match = energy_patt.search(line)
-                            if match:
-                                self.energies.append(float(match.group(1)))
-                                mol = self._sites_to_mol(sites)
-                                self.structures.append(mol)
-                                parse_cycle = False
-                                sites = []
-                    elif parse_final:
-                        match = final_energy_patt.search(line)
-                        if match:
-                            self.final_energy = float(match.group(1))
+                    if (match := cycle_patt.search(line)):
+                        cycle = int(match.group(1))
+                        if cycle <= 0:
+                            raise AdfOutputError(f"Wrong {cycle=}")
+                        parse_cycle, last_cycle = cycle > last_cycle, cycle
+                        parse_final = not parse_cycle
+                    elif parse_cycle and (match := coord_patt.search(line)):
+                        sites.append([match.groups()[1], list(map(float, match.groups()[2:]))])
+                    elif parse_cycle and (match := energy_patt.search(line)):
+                        self.energies.append(float(match.group(1)))
+                        mol = self._sites_to_mol(sites)
+                        self.structures.append(mol)
+                        parse_cycle, sites = False, []
+                    elif parse_final and (match := final_energy_patt.search(line)):
+                        self.final_energy = float(match.group(1))

This refactoring simplifies the nested conditionals and uses the walrus operator to streamline the parsing logic, enhancing readability and maintainability.

pymatgen/io/lobster/inputs.py (1)

714-721: Validate energy range calculation from Vasprun data.

Ensure that the energy range calculations are correct and consider edge cases where the minimum or maximum energy might not be straightforward due to data anomalies.

pymatgen/io/nwchem.py (8)

745-747: Use of the walrus operator for concise code.

This change leverages the walrus operator to streamline the assignment and condition check, enhancing readability and maintainability.


759-765: Refactor coordinate and lattice vector parsing.

The refactoring here uses regular expressions to parse coordinates and lattice vectors more cleanly. This change improves the clarity and efficiency of the parsing logic.


768-770: Enhanced force parsing using regular expressions.

The use of regular expressions here allows for a more robust and error-resistant parsing of force data, which is crucial for accurate simulations.


851-853: Energy parsing with immediate conversion to electron volts.

Parsing energy and converting it directly to a more commonly used unit (eV) simplifies further processing and is a good practice for maintaining clarity in units throughout the code.


857-862: Handling of different energy phases in COSMO calculations.

This segment effectively separates the handling of different phases in COSMO calculations, allowing for clearer distinctions and easier maintenance of the code related to energy calculations.


864-866: Solvent phase energy parsing and storage.

Properly parsing and storing solvent phase energy ensures that all relevant thermodynamic data is captured and available for downstream analysis.


868-874: Parsing of preamble properties with dynamic key modification.

This approach to parsing the preamble allows for flexible handling of various properties by dynamically adjusting the keys, which enhances the adaptability of the parser to different output formats.


912-914: Correction factors parsing with unit conversion.

Parsing correction factors and immediately converting them to a consistent unit (eV/atom) is a good practice, ensuring that all thermodynamic properties are comparable and easily interpretable.

pymatgen/core/tensors.py (1)

243-243: Refactored string construction using f-string for improved readability and performance.

pymatgen/io/abinit/inputs.py (1)

901-902: Check the calculation of the triple product for lattice vectors.

Ensure that the calculation correctly handles cases where the determinant might be very close to zero due to floating-point precision issues. Consider adding a small epsilon value to the condition to avoid false negatives.

pymatgen/electronic_structure/bandstructure.py (4)

248-248: Ensure that the defaultdict is imported correctly as per the new changes.


277-277: Ensure that the defaultdict is imported correctly as per the new changes.


352-352: Ensure that the defaultdict is imported correctly as per the new changes.


417-417: Ensure that the defaultdict is imported correctly as per the new changes.

pymatgen/electronic_structure/boltztrap2.py (3)

1095-1099: Variable renaming enhances code clarity.

The renaming of i to idx and di to dop_idx in the loops improves readability and makes the code more understandable.


1112-1117: Ensure consistent use of variable names.

The renaming of variables in the loops should be consistently applied throughout the method to avoid confusion and potential bugs.


1131-1142: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [1124-1139]

Update legend title to include dop_type.

The modification of the legend title to include the dop_type variable is a good practice as it provides more context to the plot, making it easier for users to understand the data being represented.

pymatgen/analysis/structure_matcher.py (1)

982-982: Optimized selection process by using min instead of sorted.

This change should enhance performance by reducing the complexity of finding the minimum value, as min is more efficient than sorted for this purpose.

pymatgen/core/composition.py (1)

227-227: Ensure that the use of defaultdict is consistent across the file to maintain readability and avoid confusion.

Please verify that defaultdict is used consistently in similar contexts throughout the file.

pymatgen/io/gaussian.py (6)

180-181: Use of the walrus operator enhances readability and reduces redundancy.


193-194: Refactoring to use the walrus operator in coordinate parsing improves code conciseness.


296-298: Ensure that the match from the regex is not None before accessing groups to avoid potential errors.

- assert match is not None
+ if match is None:
+     raise ValueError("Expected pattern not found in line.")

1035-1036: Good use of the walrus operator in PCM energy parsing to streamline the code.


1038-1039: Efficient use of the walrus operator for parsing total energy in PCM calculations.


1041-1042: Effective use of the walrus operator for parsing PCM parameters, enhancing code clarity.

pymatgen/io/lobster/lobsterenv.py (1)

607-610: Refactor variable name and logic in _get_plot_label.

The renaming from plotlabel to label and the adjustment in concatenation logic when per_bond is True are clear and enhance readability. Ensure that all references to this variable are updated accordingly.

pymatgen/io/lammps/data.py (2)

219-219: Renaming m to matrix improves code readability.


220-220: Updating string formatting to use f-strings enhances readability and performance.

pymatgen/ext/matproj_legacy.py (1)

645-645: Optimization of selection process using min instead of sorted is efficient and correctly implemented.

pymatgen/core/lattice.py (4)

9-9: Replace collections.defaultdict with a direct import of defaultdict for improved readability and conciseness.


1320-1324: Update documentation to clarify the return values and parameter names, changing fcoord to frac_coord.


1378-1382: Update documentation to clarify the return values and parameter names, changing fcoord to frac_coord.


1435-1439: Update documentation to clarify the return values and parameter names, changing fcoord to frac_coord.

pymatgen/io/lobster/outputs.py (1)

1334-1350: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [1337-1359]

Optimize the initialization of dictionaries with defaultdict.

- eigenvals[Spin.up] = [[defaultdict(float) for _ in range(self.number_kpts)] for _ in range(self.nbands)]
+ eigenvals[Spin.up] = [[defaultdict(float) for _ in range(self.number_kpts)] for _ in range(self.nbands)]
- p_eigenvals[Spin.up] = [
-     [
-         {
-             str(elem): {str(orb): defaultdict(float) for orb in atom_orbital_dict[elem]}
-             for elem in atom_names
-         }
-         for _ in range(self.number_kpts)
-     ]
-     for _ in range(self.nbands)
- ]
+ p_eigenvals[Spin.up] = [
+     [
+         {
+             str(elem): {str(orb): defaultdict(float) for orb in atom_orbital_dict[elem]}
+             for elem in atom_names
+         }
+         for _ in range(self.number_kpts)
+     ]
+     for _ in range(self.nbands)
+ ]
pymatgen/core/surface.py (1)

1908-1908: The change from sorted to max in the build_slabs method is not visible in the provided code. Please ensure that the intended change is correctly implemented in the codebase.

pymatgen/electronic_structure/boltztrap.py (1)

376-391: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [379-425]

Variable renaming enhances clarity and consistency.

Consider refactoring this method to improve readability and maintainability, possibly by breaking it down into smaller, more focused methods.

pymatgen/io/vasp/inputs.py (1)

2611-2611: Ensure proper error handling in from_file method.

Consider adding error handling for file operations and parsing to ensure robustness, especially given the complexity of POSCAR file formats.

pymatgen/core/interface.py (1)

2784-2784: Use max instead of sorted for optimization.

Ensure that the renaming of variables is consistent across the entire codebase.

pymatgen/electronic_structure/plotter.py (7)

Line range hint 53-66: Initialization of DosPlotter looks good with appropriate defaults and clear documentation.


Line range hint 68-86: Method add_dos is well-implemented with considerations for different plotting configurations.


Line range hint 88-98: Method add_dos_dict effectively handles adding multiple DOS objects with optional sorting.


Line range hint 100-106: Method get_dos_dict correctly ensures JSON serialization of DOS data using jsanitize.


Line range hint 108-204: Method get_plot is comprehensive and well-implemented, providing extensive configurability and consistent aesthetics for DOS plots.


Line range hint 206-211: Method save_plot effectively uses get_plot and matplotlib functionality to save DOS plots.


Line range hint 213-218: Method show correctly uses get_plot and matplotlib functionality to display DOS plots.

pymatgen/core/structure.py (1)

21-21: Direct import of defaultdict used as per summary.

pymatgen/io/vasp/outputs.py (1)

2425-2434: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [2430-2440]

Optimize the parsing of unsymmetrized tensors.

The current implementation for parsing unsymmetrized tensors involves multiple nested loops and regex searches which can be inefficient. Consider using vectorized operations or more efficient data structures to improve the performance of this section.

- for mt in micro_table_pattern.finditer(table_text):
-     table_body_text = mt.group("table_body")
-     tensor_matrix = []
-     for line in table_body_text.rstrip().split("\n"):
-         ml = row_pat.search(line)
-         processed_line = [float(v) for v in ml.groups()]
-         tensor_matrix.append(processed_line)
-     unsym_tensors.append(tensor_matrix)
+ # Example refactored code using more efficient operations

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@janosh janosh merged commit ff94faa into master Apr 25, 2024
22 checks passed
@janosh janosh deleted the fix-ruff-FURB192 branch April 25, 2024 19:17
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 15

Out of diff range and nitpick comments (2)
pymatgen/io/abinit/inputs.py (1)

872-872: Consider adding a brief comment explaining the purpose of the psp_dict dictionary.

This would improve the readability and maintainability of the code by making the intentions behind the code clearer to other developers.

pymatgen/io/vasp/outputs.py (1)

3572-3572: Clarify the purpose of the fft_mesh method in the documentation.

The documentation for the fft_mesh method could be improved to better explain its purpose and usage. Consider adding more details about how it interacts with other components of the system and any expected inputs or outputs.

@@ -205,7 +206,7 @@ def __add__(self, other: object) -> Composition:
if not isinstance(other, (Composition, dict)):
return NotImplemented

new_el_map: dict[SpeciesLike, float] = collections.defaultdict(float)
new_el_map: dict[SpeciesLike, float] = defaultdict(float)
Copy link

Choose a reason for hiding this comment

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

Replace defaultdict with a direct import to enhance code clarity and consistency.

- from collections import defaultdict
+ from collections import defaultdict

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
new_el_map: dict[SpeciesLike, float] = defaultdict(float)
new_el_map: dict[SpeciesLike, float] = defaultdict(float)

@@ -534,7 +535,7 @@ def _parse_formula(self, formula: str, strict: bool = True) -> dict[str, float]:
formula = formula.replace("]", ")")

def get_sym_dict(form: str, factor: float) -> dict[str, float]:
sym_dict: dict[str, float] = collections.defaultdict(float)
sym_dict: dict[str, float] = defaultdict(float)
Copy link

Choose a reason for hiding this comment

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

Consider using a direct import for defaultdict to align with changes made in other parts of the codebase.

- from collections import defaultdict
+ from collections import defaultdict

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
sym_dict: dict[str, float] = defaultdict(float)
sym_dict: dict[str, float] = defaultdict(float)

@@ -638,7 +639,7 @@ def get_el_amt_dict(self) -> dict[str, float]:
dict[str, float]: element symbol and (unreduced) amount. E.g.
{"Fe": 4.0, "O": 6.0}.
"""
dct: dict[str, float] = collections.defaultdict(float)
dct: dict[str, float] = defaultdict(float)
Copy link

Choose a reason for hiding this comment

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

Maintain consistency in the import of defaultdict to improve code readability.

- from collections import defaultdict
+ from collections import defaultdict

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
dct: dict[str, float] = defaultdict(float)
dct: dict[str, float] = defaultdict(float)

@@ -651,7 +652,7 @@ def as_dict(self) -> dict[str, float]:
dict[str, float]: element symbol and (unreduced) amount. E.g.
{"Fe": 4.0, "O": 6.0} or {"Fe3+": 4.0, "O2-": 6.0}
"""
dct: dict[str, float] = collections.defaultdict(float)
dct: dict[str, float] = defaultdict(float)
Copy link

Choose a reason for hiding this comment

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

Use a direct import for defaultdict to align with the refactoring strategy applied in other parts of the project.

- from collections import defaultdict
+ from collections import defaultdict

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
dct: dict[str, float] = defaultdict(float)
dct: dict[str, float] = defaultdict(float)

@@ -873,7 +874,7 @@ def remove_charges(self) -> Composition:
Composition object without charge decoration, for example
{"Fe3+": 2.0, "O2-":3.0} becomes {"Fe": 2.0, "O":3.0}
"""
dct: dict[Element, float] = collections.defaultdict(float)
dct: dict[Element, float] = defaultdict(float)
Copy link

Choose a reason for hiding this comment

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

Adopt a direct import of defaultdict to ensure consistency and clarity in the codebase.

- from collections import defaultdict
+ from collections import defaultdict

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
dct: dict[Element, float] = defaultdict(float)
dct: dict[Element, float] = defaultdict(float)

Comment on lines +707 to +713
match = coord_patt.search(line)
if match:
sites.append([match.groups()[0], list(map(float, match.groups()[2:]))])
else:
m = final_energy_patt.search(line)
if m:
self.final_energy = float(m.group(1))
match = final_energy_patt.search(line)
if match:
self.final_energy = float(match.group(1))
Copy link

Choose a reason for hiding this comment

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

Optimize the structure parsing for 'SinglePoint' run type.

-                    match = coord_patt.search(line)
-                    if match:
-                        sites.append([match.groups()[0], list(map(float, match.groups()[2:]))])
-                    else:
-                        match = final_energy_patt.search(line)
-                        if match:
-                            self.final_energy = float(match.group(1))
-                            self.final_structure = self._sites_to_mol(sites)
+                    if (match := coord_patt.search(line)):
+                        sites.append([match.groups()[0], list(map(float, match.groups()[2:]))])
+                    elif (match := final_energy_patt.search(line)):
+                        self.final_energy, self.final_structure = float(match.group(1)), self._sites_to_mol(sites)

This refactoring uses the walrus operator to simplify the logic, making the code more concise and easier to read.


Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
match = coord_patt.search(line)
if match:
sites.append([match.groups()[0], list(map(float, match.groups()[2:]))])
else:
m = final_energy_patt.search(line)
if m:
self.final_energy = float(m.group(1))
match = final_energy_patt.search(line)
if match:
self.final_energy = float(match.group(1))
if (match := coord_patt.search(line)):
sites.append([match.groups()[0], list(map(float, match.groups()[2:]))])
elif (match := final_energy_patt.search(line)):
self.final_energy, self.final_structure = float(match.group(1)), self._sites_to_mol(sites)

@@ -270,7 +270,7 @@ def write_lobsterin(self, path="lobsterin", overwritedict=None):
# checks if entry is True or False
for key_here in self:
if key.lower() == key_here.lower():
file.write(key + "\n")
file.write(f"{key}\n")
Copy link

Choose a reason for hiding this comment

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

Use f-strings consistently for file writing.

-                                file.write(f"{key}\n")
+                                file.write(f"{key_here}\n")

This change ensures that the actual key used in the dictionary (which might have different casing) is written to the file, maintaining consistency with the internal data representation.


Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
file.write(f"{key}\n")
file.write(f"{key_here}\n")

Comment on lines +602 to +651
for key, setting in settings.items():
if key == "MAGMOM":
mag = []
for site in structure:
if hasattr(site, "magmom"):
mag.append(site.magmom)
elif getattr(site.specie, "spin", None) is not None:
mag.append(site.specie.spin)
elif str(site.specie) in v:
if site.specie.symbol == "Co" and v[str(site.specie)] <= 1.0:
elif str(site.specie) in setting:
if site.specie.symbol == "Co" and setting[str(site.specie)] <= 1.0:
warnings.warn(
"Co without an oxidation state is initialized as low spin by default in Pymatgen. "
"If this default behavior is not desired, please set the spin on the magmom on the "
"site directly to ensure correct initialization."
)
mag.append(v.get(str(site.specie)))
mag.append(setting.get(str(site.specie)))
else:
if site.specie.symbol == "Co":
warnings.warn(
"Co without an oxidation state is initialized as low spin by default in Pymatgen. "
"If this default behavior is not desired, please set the spin on the magmom on the "
"site directly to ensure correct initialization."
)
mag.append(v.get(site.specie.symbol, 0.6))
incar[k] = mag
elif k in ("LDAUU", "LDAUJ", "LDAUL"):
mag.append(setting.get(site.specie.symbol, 0.6))
incar[key] = mag
elif key in ("LDAUU", "LDAUJ", "LDAUL"):
if hubbard_u:
if hasattr(structure[0], k.lower()):
m = {site.specie.symbol: getattr(site, k.lower()) for site in structure}
incar[k] = [m[sym] for sym in poscar.site_symbols]
if hasattr(structure[0], key.lower()):
m = {site.specie.symbol: getattr(site, key.lower()) for site in structure}
incar[key] = [m[sym] for sym in poscar.site_symbols]
# lookup specific LDAU if specified for most_electroneg atom
elif most_electro_neg in v and isinstance(v[most_electro_neg], dict):
incar[k] = [v[most_electro_neg].get(sym, 0) for sym in poscar.site_symbols]
elif most_electro_neg in setting and isinstance(setting[most_electro_neg], dict):
incar[key] = [setting[most_electro_neg].get(sym, 0) for sym in poscar.site_symbols]
# else, use fallback LDAU value if it exists
else:
incar[k] = [
v.get(sym, 0) if isinstance(v.get(sym, 0), (float, int)) else 0
incar[key] = [
setting.get(sym, 0) if isinstance(setting.get(sym, 0), (float, int)) else 0
for sym in poscar.site_symbols
]
elif k.startswith("EDIFF") and k != "EDIFFG":
if "EDIFF" not in settings and k == "EDIFF_PER_ATOM":
incar["EDIFF"] = float(v) * len(structure)
elif key.startswith("EDIFF") and key != "EDIFFG":
if "EDIFF" not in settings and key == "EDIFF_PER_ATOM":
incar["EDIFF"] = float(setting) * len(structure)
else:
incar["EDIFF"] = float(settings["EDIFF"])
elif k == "KSPACING" and v == "auto":
elif key == "KSPACING" and setting == "auto":
# default to metal if no prev calc available
bandgap = 0 if self.bandgap is None else self.bandgap
incar[k] = auto_kspacing(bandgap, self.bandgap_tol)
incar[key] = auto_kspacing(bandgap, self.bandgap_tol)
else:
incar[k] = v
incar[key] = setting
Copy link

Choose a reason for hiding this comment

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

Refactor the incar property to improve readability and maintainability.

-        for key, setting in settings.items():
-            if key == "MAGMOM":
-                mag = []
-                for site in structure:
-                    if hasattr(site, "magmom"):
-                        mag.append(site.magmom)
-                    elif getattr(site.specie, "spin", None) is not None:
-                        mag.append(site.specie.spin)
-                    elif str(site.specie) in setting:
-                        if site.specie.symbol == "Co" and setting[str(site.specie)] <= 1.0:
-                            warnings.warn(
-                                "Co without an oxidation state is initialized as low spin by default in Pymatgen. "
-                                "If this default behavior is not desired, please set the spin on the magmom on the "
-                                "site directly to ensure correct initialization."
-                            )
-                        mag.append(setting.get(str(site.specie)))
-                    else:
-                        if site.specie.symbol == "Co":
-                            warnings.warn(
-                                "Co without an oxidation state is initialized as low spin by default in Pymatgen. "
-                                "If this default behavior is not desired, please set the spin on the magmom on the "
-                                "site directly to ensure correct initialization."
-                            )
-                        mag.append(setting.get(site.specie.symbol, 0.6))
-                incar[key] = mag
-            elif key in ("LDAUU", "LDAUJ", "LDAUL"):
-                if hubbard_u:
-                    if hasattr(structure[0], key.lower()):
-                        m = {site.specie.symbol: getattr(site, key.lower()) for site in structure}
-                        incar[key] = [m[sym] for sym in poscar.site_symbols]
-                    elif most_electro_neg in setting and isinstance(setting[most_electro_neg], dict):
-                        incar[key] = [setting[most_electro_neg].get(sym, 0) for sym in poscar.site_symbols]
-                    else:
-                        incar[key] = [
-                            setting.get(sym, 0) if isinstance(setting.get(sym, 0), (float, int)) else 0
-                            for sym in poscar.site_symbols
-                        ]
-            elif key.startswith("EDIFF") and key != "EDIFFG":
-                if "EDIFF" not in settings and key == "EDIFF_PER_ATOM":
-                    incar["EDIFF"] = float(setting) * len(structure)
-                else:
-                    incar["EDIFF"] = float(settings["EDIFF"])
-            elif key == "KSPACING" and setting == "auto":
-                bandgap = 0 if self.bandgap is None else self.bandgap
-                incar[key] = auto_kspacing(bandgap, self.bandgap_tol)
-            else:
-                incar[key] = setting
+        _apply_incar_updates(incar, settings, structure, poscar, hubbard_u, most_electro_neg)

This refactoring suggestion aims to extract the complex logic inside the incar property into a separate function _apply_incar_updates. This will make the incar property cleaner and the logic more reusable and testable.


Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
for key, setting in settings.items():
if key == "MAGMOM":
mag = []
for site in structure:
if hasattr(site, "magmom"):
mag.append(site.magmom)
elif getattr(site.specie, "spin", None) is not None:
mag.append(site.specie.spin)
elif str(site.specie) in v:
if site.specie.symbol == "Co" and v[str(site.specie)] <= 1.0:
elif str(site.specie) in setting:
if site.specie.symbol == "Co" and setting[str(site.specie)] <= 1.0:
warnings.warn(
"Co without an oxidation state is initialized as low spin by default in Pymatgen. "
"If this default behavior is not desired, please set the spin on the magmom on the "
"site directly to ensure correct initialization."
)
mag.append(v.get(str(site.specie)))
mag.append(setting.get(str(site.specie)))
else:
if site.specie.symbol == "Co":
warnings.warn(
"Co without an oxidation state is initialized as low spin by default in Pymatgen. "
"If this default behavior is not desired, please set the spin on the magmom on the "
"site directly to ensure correct initialization."
)
mag.append(v.get(site.specie.symbol, 0.6))
incar[k] = mag
elif k in ("LDAUU", "LDAUJ", "LDAUL"):
mag.append(setting.get(site.specie.symbol, 0.6))
incar[key] = mag
elif key in ("LDAUU", "LDAUJ", "LDAUL"):
if hubbard_u:
if hasattr(structure[0], k.lower()):
m = {site.specie.symbol: getattr(site, k.lower()) for site in structure}
incar[k] = [m[sym] for sym in poscar.site_symbols]
if hasattr(structure[0], key.lower()):
m = {site.specie.symbol: getattr(site, key.lower()) for site in structure}
incar[key] = [m[sym] for sym in poscar.site_symbols]
# lookup specific LDAU if specified for most_electroneg atom
elif most_electro_neg in v and isinstance(v[most_electro_neg], dict):
incar[k] = [v[most_electro_neg].get(sym, 0) for sym in poscar.site_symbols]
elif most_electro_neg in setting and isinstance(setting[most_electro_neg], dict):
incar[key] = [setting[most_electro_neg].get(sym, 0) for sym in poscar.site_symbols]
# else, use fallback LDAU value if it exists
else:
incar[k] = [
v.get(sym, 0) if isinstance(v.get(sym, 0), (float, int)) else 0
incar[key] = [
setting.get(sym, 0) if isinstance(setting.get(sym, 0), (float, int)) else 0
for sym in poscar.site_symbols
]
elif k.startswith("EDIFF") and k != "EDIFFG":
if "EDIFF" not in settings and k == "EDIFF_PER_ATOM":
incar["EDIFF"] = float(v) * len(structure)
elif key.startswith("EDIFF") and key != "EDIFFG":
if "EDIFF" not in settings and key == "EDIFF_PER_ATOM":
incar["EDIFF"] = float(setting) * len(structure)
else:
incar["EDIFF"] = float(settings["EDIFF"])
elif k == "KSPACING" and v == "auto":
elif key == "KSPACING" and setting == "auto":
# default to metal if no prev calc available
bandgap = 0 if self.bandgap is None else self.bandgap
incar[k] = auto_kspacing(bandgap, self.bandgap_tol)
incar[key] = auto_kspacing(bandgap, self.bandgap_tol)
else:
incar[k] = v
incar[key] = setting
_apply_incar_updates(incar, settings, structure, poscar, hubbard_u, most_electro_neg)

@@ -1013,7 +1013,7 @@ def override_from_prev_calc(self, prev_calc_dir="."):

if getattr(self, "copy_wavecar", False):
for fname in ("WAVECAR", "WAVEDER", "WFULL"):
wavecar_files = sorted(glob(str(Path(prev_calc_dir) / (fname + "*"))))
wavecar_files = sorted(glob(str(Path(prev_calc_dir) / (f"{fname}*"))))
Copy link

Choose a reason for hiding this comment

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

Ensure file existence checks before attempting to copy in override_from_prev_calc.

+                if os.path.exists(wavecar_file):
+                    files_to_transfer[fname] = str(wavecar_files[-1])

Before attempting to copy the WAVECAR files, it's crucial to check if the files exist to avoid runtime errors. This change ensures that the file exists before it's added to the files_to_transfer dictionary.


Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
wavecar_files = sorted(glob(str(Path(prev_calc_dir) / (f"{fname}*"))))
wavecar_files = sorted(glob(str(Path(prev_calc_dir) / (f"{fname}*"))))
if os.path.exists(wavecar_file):
files_to_transfer[fname] = str(wavecar_files[-1])

Comment on lines +2754 to +2755
vsfile = vsfile_fullpath if vsfile_fullpath in vruns else max(vruns)
outcarfile = outcarfile_fullpath if outcarfile_fullpath in outcars else max(outcars)
Copy link

Choose a reason for hiding this comment

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

Handle potential exceptions when accessing files in get_vasprun_outcar.

-    vsfile = vsfile_fullpath if vsfile_fullpath in vruns else max(vruns)
-    outcarfile = outcarfile_fullpath if outcarfile_fullpath in outcars else max(outcars)
+    try:
+        vsfile = vsfile_fullpath if vsfile_fullpath in vruns else max(vruns)
+        outcarfile = outcarfile_fullpath if outcarfile_fullpath in outcars else max(outcars)
+    except ValueError:
+        raise FileNotFoundError("Could not find vasprun.xml or OUTCAR in the specified directory.")

This change adds error handling to manage the case where vasprun.xml or OUTCAR files are not found in the specified directory, thus preventing the function from raising an unhandled ValueError.


Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
vsfile = vsfile_fullpath if vsfile_fullpath in vruns else max(vruns)
outcarfile = outcarfile_fullpath if outcarfile_fullpath in outcars else max(outcars)
try:
vsfile = vsfile_fullpath if vsfile_fullpath in vruns else max(vruns)
outcarfile = outcarfile_fullpath if outcarfile_fullpath in outcars else max(outcars)
except ValueError:
raise FileNotFoundError("Could not find vasprun.xml or OUTCAR in the specified directory.")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
linting Linting and quality assurance
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant