pyEQL 1.0.1__tar.gz → 1.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. {pyeql-1.0.1 → pyeql-1.1.0}/CHANGELOG.md +9 -0
  2. {pyeql-1.0.1/src/pyEQL.egg-info → pyeql-1.1.0}/PKG-INFO +1 -1
  3. {pyeql-1.0.1 → pyeql-1.1.0}/docs/changelog.md +9 -0
  4. {pyeql-1.0.1 → pyeql-1.1.0}/pyproject.toml +1 -1
  5. {pyeql-1.0.1 → pyeql-1.1.0}/src/pyEQL/engines.py +3 -3
  6. {pyeql-1.0.1 → pyeql-1.1.0}/src/pyEQL/salt_ion_match.py +1 -1
  7. {pyeql-1.0.1 → pyeql-1.1.0}/src/pyEQL/solute.py +1 -1
  8. {pyeql-1.0.1 → pyeql-1.1.0}/src/pyEQL/solution.py +6 -6
  9. {pyeql-1.0.1 → pyeql-1.1.0}/src/pyEQL/utils.py +38 -5
  10. {pyeql-1.0.1 → pyeql-1.1.0/src/pyEQL.egg-info}/PKG-INFO +1 -1
  11. {pyeql-1.0.1 → pyeql-1.1.0}/tests/test_utils.py +13 -0
  12. {pyeql-1.0.1 → pyeql-1.1.0}/.coveragerc +0 -0
  13. {pyeql-1.0.1 → pyeql-1.1.0}/.gitattributes +0 -0
  14. {pyeql-1.0.1 → pyeql-1.1.0}/.github/dependabot.yml +0 -0
  15. {pyeql-1.0.1 → pyeql-1.1.0}/.github/pull_request_template.md +0 -0
  16. {pyeql-1.0.1 → pyeql-1.1.0}/.github/release.yml +0 -0
  17. {pyeql-1.0.1 → pyeql-1.1.0}/.github/workflows/post-process.yml +0 -0
  18. {pyeql-1.0.1 → pyeql-1.1.0}/.github/workflows/release.yml +0 -0
  19. {pyeql-1.0.1 → pyeql-1.1.0}/.github/workflows/testing.yaml +0 -0
  20. {pyeql-1.0.1 → pyeql-1.1.0}/.github/workflows/upgrade_dependencies.yml +0 -0
  21. {pyeql-1.0.1 → pyeql-1.1.0}/.gitignore +0 -0
  22. {pyeql-1.0.1 → pyeql-1.1.0}/.pre-commit-config.yaml +0 -0
  23. {pyeql-1.0.1 → pyeql-1.1.0}/.readthedocs.yml +0 -0
  24. {pyeql-1.0.1 → pyeql-1.1.0}/.zenodo.json +0 -0
  25. {pyeql-1.0.1 → pyeql-1.1.0}/AUTHORS.md +0 -0
  26. {pyeql-1.0.1 → pyeql-1.1.0}/CITATION.cff +0 -0
  27. {pyeql-1.0.1 → pyeql-1.1.0}/COPYING +0 -0
  28. {pyeql-1.0.1 → pyeql-1.1.0}/LICENSE.txt +0 -0
  29. {pyeql-1.0.1 → pyeql-1.1.0}/MANIFEST.in +0 -0
  30. {pyeql-1.0.1 → pyeql-1.1.0}/README.md +0 -0
  31. {pyeql-1.0.1 → pyeql-1.1.0}/docs/Makefile +0 -0
  32. {pyeql-1.0.1 → pyeql-1.1.0}/docs/_static/.gitignore +0 -0
  33. {pyeql-1.0.1 → pyeql-1.1.0}/docs/amounts.md +0 -0
  34. {pyeql-1.0.1 → pyeql-1.1.0}/docs/arithmetic.md +0 -0
  35. {pyeql-1.0.1 → pyeql-1.1.0}/docs/authors.md +0 -0
  36. {pyeql-1.0.1 → pyeql-1.1.0}/docs/chemistry.md +0 -0
  37. {pyeql-1.0.1 → pyeql-1.1.0}/docs/class_solution.md +0 -0
  38. {pyeql-1.0.1 → pyeql-1.1.0}/docs/conf.py +0 -0
  39. {pyeql-1.0.1 → pyeql-1.1.0}/docs/contributing.md +0 -0
  40. {pyeql-1.0.1 → pyeql-1.1.0}/docs/creating.md +0 -0
  41. {pyeql-1.0.1 → pyeql-1.1.0}/docs/database.md +0 -0
  42. {pyeql-1.0.1 → pyeql-1.1.0}/docs/engines.md +0 -0
  43. {pyeql-1.0.1 → pyeql-1.1.0}/docs/examples/.ipynb_checkpoints/pyEQL_demo_1-checkpoint.ipynb +0 -0
  44. {pyeql-1.0.1 → pyeql-1.1.0}/docs/examples/.ipynb_checkpoints/pyeql_demo-checkpoint.ipynb +0 -0
  45. {pyeql-1.0.1 → pyeql-1.1.0}/docs/examples/.ipynb_checkpoints/pyeql_tutorial_database-checkpoint.ipynb +0 -0
  46. {pyeql-1.0.1 → pyeql-1.1.0}/docs/examples/.ipynb_checkpoints/pyeql_tutorial_osmotic_pressure-checkpoint.ipynb +0 -0
  47. {pyeql-1.0.1 → pyeql-1.1.0}/docs/examples/.ipynb_checkpoints/speedup-checkpoint.ipynb +0 -0
  48. {pyeql-1.0.1 → pyeql-1.1.0}/docs/examples/pyEQL_demo_1.ipynb +0 -0
  49. {pyeql-1.0.1 → pyeql-1.1.0}/docs/examples/pyeql_demo.ipynb +0 -0
  50. {pyeql-1.0.1 → pyeql-1.1.0}/docs/examples/pyeql_tutorial_database.ipynb +0 -0
  51. {pyeql-1.0.1 → pyeql-1.1.0}/docs/examples/pyeql_tutorial_osmotic_pressure.ipynb +0 -0
  52. {pyeql-1.0.1 → pyeql-1.1.0}/docs/examples/speedup.ipynb +0 -0
  53. {pyeql-1.0.1 → pyeql-1.1.0}/docs/index.md +0 -0
  54. {pyeql-1.0.1 → pyeql-1.1.0}/docs/installation.md +0 -0
  55. {pyeql-1.0.1 → pyeql-1.1.0}/docs/internal.md +0 -0
  56. {pyeql-1.0.1 → pyeql-1.1.0}/docs/license.md +0 -0
  57. {pyeql-1.0.1 → pyeql-1.1.0}/docs/mixing.md +0 -0
  58. {pyeql-1.0.1 → pyeql-1.1.0}/docs/quickstart.md +0 -0
  59. {pyeql-1.0.1 → pyeql-1.1.0}/docs/readme.md +0 -0
  60. {pyeql-1.0.1 → pyeql-1.1.0}/docs/requirements.txt +0 -0
  61. {pyeql-1.0.1 → pyeql-1.1.0}/docs/serialization.md +0 -0
  62. {pyeql-1.0.1 → pyeql-1.1.0}/docs/tutorials.md +0 -0
  63. {pyeql-1.0.1 → pyeql-1.1.0}/docs/units.md +0 -0
  64. {pyeql-1.0.1 → pyeql-1.1.0}/pyeql-logo.png +0 -0
  65. {pyeql-1.0.1 → pyeql-1.1.0}/pyeql-logo.svg +0 -0
  66. {pyeql-1.0.1 → pyeql-1.1.0}/requirements/macos-latest_py3.10.txt +0 -0
  67. {pyeql-1.0.1 → pyeql-1.1.0}/requirements/macos-latest_py3.10_extras.txt +0 -0
  68. {pyeql-1.0.1 → pyeql-1.1.0}/requirements/macos-latest_py3.11.txt +0 -0
  69. {pyeql-1.0.1 → pyeql-1.1.0}/requirements/macos-latest_py3.11_extras.txt +0 -0
  70. {pyeql-1.0.1 → pyeql-1.1.0}/requirements/macos-latest_py3.12.txt +0 -0
  71. {pyeql-1.0.1 → pyeql-1.1.0}/requirements/macos-latest_py3.12_extras.txt +0 -0
  72. {pyeql-1.0.1 → pyeql-1.1.0}/requirements/macos-latest_py3.9.txt +0 -0
  73. {pyeql-1.0.1 → pyeql-1.1.0}/requirements/macos-latest_py3.9_extras.txt +0 -0
  74. {pyeql-1.0.1 → pyeql-1.1.0}/requirements/ubuntu-latest_py3.10.txt +0 -0
  75. {pyeql-1.0.1 → pyeql-1.1.0}/requirements/ubuntu-latest_py3.10_extras.txt +0 -0
  76. {pyeql-1.0.1 → pyeql-1.1.0}/requirements/ubuntu-latest_py3.11.txt +0 -0
  77. {pyeql-1.0.1 → pyeql-1.1.0}/requirements/ubuntu-latest_py3.11_extras.txt +0 -0
  78. {pyeql-1.0.1 → pyeql-1.1.0}/requirements/ubuntu-latest_py3.12.txt +0 -0
  79. {pyeql-1.0.1 → pyeql-1.1.0}/requirements/ubuntu-latest_py3.12_extras.txt +0 -0
  80. {pyeql-1.0.1 → pyeql-1.1.0}/requirements/ubuntu-latest_py3.9.txt +0 -0
  81. {pyeql-1.0.1 → pyeql-1.1.0}/requirements/ubuntu-latest_py3.9_extras.txt +0 -0
  82. {pyeql-1.0.1 → pyeql-1.1.0}/requirements/windows-latest_py3.10.txt +0 -0
  83. {pyeql-1.0.1 → pyeql-1.1.0}/requirements/windows-latest_py3.10_extras.txt +0 -0
  84. {pyeql-1.0.1 → pyeql-1.1.0}/requirements/windows-latest_py3.11.txt +0 -0
  85. {pyeql-1.0.1 → pyeql-1.1.0}/requirements/windows-latest_py3.11_extras.txt +0 -0
  86. {pyeql-1.0.1 → pyeql-1.1.0}/requirements/windows-latest_py3.12.txt +0 -0
  87. {pyeql-1.0.1 → pyeql-1.1.0}/requirements/windows-latest_py3.12_extras.txt +0 -0
  88. {pyeql-1.0.1 → pyeql-1.1.0}/requirements/windows-latest_py3.9.txt +0 -0
  89. {pyeql-1.0.1 → pyeql-1.1.0}/requirements/windows-latest_py3.9_extras.txt +0 -0
  90. {pyeql-1.0.1 → pyeql-1.1.0}/setup.cfg +0 -0
  91. {pyeql-1.0.1 → pyeql-1.1.0}/setup.py +0 -0
  92. {pyeql-1.0.1 → pyeql-1.1.0}/src/pyEQL/__init__.py +0 -0
  93. {pyeql-1.0.1 → pyeql-1.1.0}/src/pyEQL/activity_correction.py +0 -0
  94. {pyeql-1.0.1 → pyeql-1.1.0}/src/pyEQL/database/geothermal.dat +0 -0
  95. {pyeql-1.0.1 → pyeql-1.1.0}/src/pyEQL/database/llnl.dat +0 -0
  96. {pyeql-1.0.1 → pyeql-1.1.0}/src/pyEQL/database/phreeqc_license.txt +0 -0
  97. {pyeql-1.0.1 → pyeql-1.1.0}/src/pyEQL/database/pyeql_db.json +0 -0
  98. {pyeql-1.0.1 → pyeql-1.1.0}/src/pyEQL/equilibrium.py +0 -0
  99. {pyeql-1.0.1 → pyeql-1.1.0}/src/pyEQL/functions.py +0 -0
  100. {pyeql-1.0.1 → pyeql-1.1.0}/src/pyEQL/pint_custom_units.txt +0 -0
  101. {pyeql-1.0.1 → pyeql-1.1.0}/src/pyEQL/presets/Ringers lactate.yaml +0 -0
  102. {pyeql-1.0.1 → pyeql-1.1.0}/src/pyEQL/presets/normal saline.yaml +0 -0
  103. {pyeql-1.0.1 → pyeql-1.1.0}/src/pyEQL/presets/rainwater.yaml +0 -0
  104. {pyeql-1.0.1 → pyeql-1.1.0}/src/pyEQL/presets/seawater.yaml +0 -0
  105. {pyeql-1.0.1 → pyeql-1.1.0}/src/pyEQL/presets/urine.yaml +0 -0
  106. {pyeql-1.0.1 → pyeql-1.1.0}/src/pyEQL/presets/wastewater.yaml +0 -0
  107. {pyeql-1.0.1 → pyeql-1.1.0}/src/pyEQL.egg-info/SOURCES.txt +0 -0
  108. {pyeql-1.0.1 → pyeql-1.1.0}/src/pyEQL.egg-info/dependency_links.txt +0 -0
  109. {pyeql-1.0.1 → pyeql-1.1.0}/src/pyEQL.egg-info/not-zip-safe +0 -0
  110. {pyeql-1.0.1 → pyeql-1.1.0}/src/pyEQL.egg-info/requires.txt +0 -0
  111. {pyeql-1.0.1 → pyeql-1.1.0}/src/pyEQL.egg-info/top_level.txt +0 -0
  112. {pyeql-1.0.1 → pyeql-1.1.0}/tests/conftest.py +0 -0
  113. {pyeql-1.0.1 → pyeql-1.1.0}/tests/test_activity.py +0 -0
  114. {pyeql-1.0.1 → pyeql-1.1.0}/tests/test_bulk_properties.py +0 -0
  115. {pyeql-1.0.1 → pyeql-1.1.0}/tests/test_debye_length.py +0 -0
  116. {pyeql-1.0.1 → pyeql-1.1.0}/tests/test_density.py +0 -0
  117. {pyeql-1.0.1 → pyeql-1.1.0}/tests/test_dielectric.py +0 -0
  118. {pyeql-1.0.1 → pyeql-1.1.0}/tests/test_effective_pitzer.py +0 -0
  119. {pyeql-1.0.1 → pyeql-1.1.0}/tests/test_equilibrium.py +0 -0
  120. {pyeql-1.0.1 → pyeql-1.1.0}/tests/test_functions.py +0 -0
  121. {pyeql-1.0.1 → pyeql-1.1.0}/tests/test_logging.py +0 -0
  122. {pyeql-1.0.1 → pyeql-1.1.0}/tests/test_mixed_electrolyte_activity.py +0 -0
  123. {pyeql-1.0.1 → pyeql-1.1.0}/tests/test_osmotic_coeff.py +0 -0
  124. {pyeql-1.0.1 → pyeql-1.1.0}/tests/test_phreeqc.py +0 -0
  125. {pyeql-1.0.1 → pyeql-1.1.0}/tests/test_salt_matching.py +0 -0
  126. {pyeql-1.0.1 → pyeql-1.1.0}/tests/test_solute.py +0 -0
  127. {pyeql-1.0.1 → pyeql-1.1.0}/tests/test_solute_properties.py +0 -0
  128. {pyeql-1.0.1 → pyeql-1.1.0}/tests/test_solution.py +0 -0
  129. {pyeql-1.0.1 → pyeql-1.1.0}/tests/test_volume_concentration.py +0 -0
  130. {pyeql-1.0.1 → pyeql-1.1.0}/tox.ini +0 -0
@@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.0.2] - 2024-07-09
9
+
10
+ ### Fixed
11
+
12
+ - `standardize_formula`: Fix incorrect display of ammonium/ammonia. Previously, their formulas
13
+ were shown as "H4N[+1]" and "H3N(aq)", respectively. They now correctly display as NH4 and NH3.
14
+ Similar fixes were implemented for HPO4[-2] / H2PO4[-1] / H3PO4, formate (HCOO[-1]), oxalate (C2O4[-2]), thicyanate (SCN[-1]), and triiodide (I3[-1]).
15
+ Fixes #136 (@xiaoxiaozhu123)
16
+
8
17
  ## [1.0.1] - 2024-06-17
9
18
 
10
19
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pyEQL
3
- Version: 1.0.1
3
+ Version: 1.1.0
4
4
  Summary: Python tools for solution chemistry
5
5
  Home-page: https://github.com/KingsburyLab/pyEQL
6
6
  Author: Ryan Kingsbury
@@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.0.2] - 2024-07-09
9
+
10
+ ### Fixed
11
+
12
+ - `standardize_formula`: Fix incorrect display of ammonium/ammonia. Previously, their formulas
13
+ were shown as "H4N[+1]" and "H3N(aq)", respectively. They now correctly display as NH4 and NH3.
14
+ Similar fixes were implemented for HPO4[-2] / H2PO4[-1] / H3PO4, formate (HCOO[-1]), oxalate (C2O4[-2]), thicyanate (SCN[-1]), and triiodide (I3[-1]).
15
+ Fixes #136 (@xiaoxiaozhu123)
16
+
8
17
  ## [1.0.1] - 2024-06-17
9
18
 
10
19
  ### Added
@@ -104,5 +104,5 @@ enable_error_code = ["ignore-without-code", "redundant-expr", "truthy-bool"]
104
104
  warn_unreachable = true
105
105
 
106
106
  [tool.codespell]
107
- ignore-words-list = "nd"
107
+ ignore-words-list = "nd,formate"
108
108
  skip = "tests/test_files/*,src/pyEQL/database/*"
@@ -139,7 +139,7 @@ class NativeEOS(EOS):
139
139
  def __init__(
140
140
  self,
141
141
  phreeqc_db: Literal["vitens.dat", "wateq4f_PWN.dat", "pitzer.dat", "llnl.dat", "geothermal.dat"] = "llnl.dat",
142
- ):
142
+ ) -> None:
143
143
  """
144
144
  Args:
145
145
  phreeqc_db: Name of the PHREEQC database file to use for solution thermodynamics
@@ -712,7 +712,7 @@ class NativeEOS(EOS):
712
712
  # call to equilibrate can thus result in a slight change in the Solution mass.
713
713
  solution.components[solution.solvent] = orig_solvent_moles
714
714
 
715
- def __deepcopy__(self, memo):
715
+ def __deepcopy__(self, memo) -> "NativeEOS":
716
716
  # custom deepcopy required because the PhreeqPython instance used by the Native and Phreeqc engines
717
717
  # is not pickle-able.
718
718
  import copy
@@ -736,7 +736,7 @@ class PhreeqcEOS(NativeEOS):
736
736
  phreeqc_db: Literal[
737
737
  "vitens.dat", "wateq4f_PWN.dat", "pitzer.dat", "llnl.dat", "geothermal.dat"
738
738
  ] = "phreeqc.dat",
739
- ):
739
+ ) -> None:
740
740
  """
741
741
  Args:
742
742
  phreeqc_db: Name of the PHREEQC database file to use for solution thermodynamics
@@ -21,7 +21,7 @@ from pyEQL.utils import standardize_formula
21
21
  class Salt(MSONable):
22
22
  """Class to represent a salt."""
23
23
 
24
- def __init__(self, cation, anion):
24
+ def __init__(self, cation, anion) -> None:
25
25
  """
26
26
  Create a Salt object based on its component ions.
27
27
 
@@ -150,7 +150,7 @@ class Solute:
150
150
  return dict(asdict(self).items())
151
151
 
152
152
  # set output of the print() statement
153
- def __str__(self):
153
+ def __str__(self) -> str:
154
154
  return (
155
155
  "Species "
156
156
  + str(self.formula)
@@ -57,7 +57,7 @@ class Solution(MSONable):
57
57
  database: str | Path | Store | None = None,
58
58
  default_diffusion_coeff: float = 1.6106e-9,
59
59
  log_level: Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"] | None = "ERROR",
60
- ):
60
+ ) -> None:
61
61
  """
62
62
  Instantiate a Solution from a composition.
63
63
 
@@ -2512,7 +2512,7 @@ class Solution(MSONable):
2512
2512
  return loadfn(filename)
2513
2513
 
2514
2514
  # arithmetic operations
2515
- def __add__(self, other: Solution):
2515
+ def __add__(self, other: Solution) -> Solution:
2516
2516
  """
2517
2517
  Solution addition: mix two solutions together.
2518
2518
 
@@ -2600,10 +2600,10 @@ class Solution(MSONable):
2600
2600
  pE=mix_pE,
2601
2601
  )
2602
2602
 
2603
- def __sub__(self, other: Solution):
2603
+ def __sub__(self, other: Solution) -> None:
2604
2604
  raise NotImplementedError("Subtraction of solutions is not implemented.")
2605
2605
 
2606
- def __mul__(self, factor: float):
2606
+ def __mul__(self, factor: float) -> None:
2607
2607
  """
2608
2608
  Solution multiplication: scale all components by a factor. For example, Solution * 2 will double the moles of
2609
2609
  every component (including solvent). No other properties will change.
@@ -2611,7 +2611,7 @@ class Solution(MSONable):
2611
2611
  self.volume *= factor
2612
2612
  return self
2613
2613
 
2614
- def __truediv__(self, factor: float):
2614
+ def __truediv__(self, factor: float) -> None:
2615
2615
  """
2616
2616
  Solution division: scale all components by a factor. For example, Solution / 2 will remove half of the moles
2617
2617
  of every compoonents (including solvent). No other properties will change.
@@ -2657,7 +2657,7 @@ class Solution(MSONable):
2657
2657
 
2658
2658
  print(f"{i}:\t {amt:0.{places}f}")
2659
2659
 
2660
- def __str__(self):
2660
+ def __str__(self) -> str:
2661
2661
  # set output of the print() statement for the solution
2662
2662
  l1 = f"Volume: {self.volume:.3f~}"
2663
2663
  l2 = f"Temperature: {self.temperature:.3f~}"
@@ -9,6 +9,7 @@ pyEQL utilities
9
9
  import logging
10
10
  from collections import UserDict
11
11
  from functools import lru_cache
12
+ from typing import Any
12
13
 
13
14
  from iapws import IAPWS95, IAPWS97
14
15
  from pymatgen.core.ion import Ion
@@ -59,7 +60,39 @@ def standardize_formula(formula: str):
59
60
  be enclosed in square brackets to remove any ambiguity in the meaning of the formula. For example, 'Na+',
60
61
  'Na+1', and 'Na[+]' will all standardize to "Na[+1]"
61
62
  """
62
- return Ion.from_formula(formula).reduced_formula
63
+ sform = Ion.from_formula(formula).reduced_formula
64
+
65
+ # TODO - manual formula adjustments. May be implemented upstream in pymatgen in the future
66
+ # thanks to @xiaoxiaozhu123 for pointing out these issues in
67
+ # https://github.com/KingsburyLab/pyEQL/issues/136
68
+
69
+ # ammonia
70
+ if sform == "H4N[+1]":
71
+ sform = "NH4[+1]"
72
+ elif sform == "H3N(aq)":
73
+ sform = "NH3(aq)"
74
+ # phosphoric acid system
75
+ elif sform == "PH3O4(aq)":
76
+ sform = "H3PO4(aq)"
77
+ elif sform == "PHO4[-2]":
78
+ sform = "HPO4[-2]"
79
+ elif sform == "P(HO2)2[-1]":
80
+ sform = "H2PO4[-1]"
81
+ # thiocyanate
82
+ elif sform == "CSN[-1]":
83
+ sform = "SCN[-1]"
84
+ # triiodide
85
+ elif sform == "I[-0.33333333]":
86
+ sform = "I3[-1]"
87
+ # formate
88
+ elif sform == "HCOO[-1]":
89
+ sform = "HCO2[-1]"
90
+ # oxalate
91
+ elif sform == "CO2[-1]":
92
+ sform = "C2O4[-2]"
93
+
94
+ # TODO - consider adding recognition of special formulas like MeOH for methanol or Cit for citrate
95
+ return sform
63
96
 
64
97
 
65
98
  def format_solutes_dict(solute_dict: dict, units: str):
@@ -115,18 +148,18 @@ class FormulaDict(UserDict):
115
148
  formula notation (e.g., "Na+", "Na+1", "Na[+]" all have the same effect)
116
149
  """
117
150
 
118
- def __getitem__(self, key):
151
+ def __getitem__(self, key) -> Any:
119
152
  return super().__getitem__(standardize_formula(key))
120
153
 
121
- def __setitem__(self, key, value):
154
+ def __setitem__(self, key, value) -> None:
122
155
  super().__setitem__(standardize_formula(key), value)
123
156
  # sort contents anytime an item is set
124
157
  self.data = dict(sorted(self.items(), key=lambda x: x[1], reverse=True))
125
158
 
126
159
  # Necessary to define this so that .get() works properly in python 3.12+
127
160
  # see https://github.com/python/cpython/issues/105524
128
- def __contains__(self, key):
161
+ def __contains__(self, key) -> bool:
129
162
  return standardize_formula(key) in self.data
130
163
 
131
- def __delitem__(self, key):
164
+ def __delitem__(self, key) -> None:
132
165
  super().__delitem__(standardize_formula(key))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pyEQL
3
- Version: 1.0.1
3
+ Version: 1.1.0
4
4
  Summary: Python tools for solution chemistry
5
5
  Home-page: https://github.com/KingsburyLab/pyEQL
6
6
  Author: Ryan Kingsbury
@@ -2,6 +2,7 @@
2
2
  Tests of pyEQL.utils module
3
3
 
4
4
  """
5
+
5
6
  from iapws import IAPWS95, IAPWS97
6
7
  from pytest import raises
7
8
 
@@ -19,6 +20,18 @@ def test_standardize_formula():
19
20
  assert standardize_formula("SO4--") == "SO4[-2]"
20
21
  assert standardize_formula("Mg+2") == "Mg[+2]"
21
22
  assert standardize_formula("O2") == "O2(aq)"
23
+ assert standardize_formula("NH4+") == "NH4[+1]"
24
+ assert standardize_formula("NH3") == "NH3(aq)"
25
+ assert standardize_formula("HPO4--") == "HPO4[-2]"
26
+ assert standardize_formula("H2PO4-") == "H2PO4[-1]"
27
+ assert standardize_formula("SCN-") == "SCN[-1]"
28
+ assert standardize_formula("I3-") == "I3[-1]"
29
+ assert standardize_formula("HCOO-") == "HCO2[-1]"
30
+ assert standardize_formula("CO2-1") == "C2O4[-2]"
31
+ assert standardize_formula("C2O4--") == "C2O4[-2]"
32
+ assert standardize_formula("H3PO4") == "H3PO4(aq)"
33
+ assert standardize_formula("H2SO4") == "H2SO4(aq)"
34
+ assert standardize_formula("HClO4") == "HClO4(aq)"
22
35
 
23
36
 
24
37
  def test_formula_dict():
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes