OGRePy 1.2.0__tar.gz → 1.3.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.
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2024 Barak Shoshany
3
+ Copyright (c) 2025 Barak Shoshany
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
1
1
  r"""
2
2
  # OGRePy: An Object-Oriented General Relativity Package for Python
3
- v1.2.0 (2024-09-15)
3
+ v1.3.0 (2025-02-04)
4
4
 
5
5
  By **Barak Shoshany**\
6
6
  Email: <baraksh@gmail.com>\
@@ -12,7 +12,7 @@ PyPi project: <https://pypi.org/project/OGRePy/>
12
12
 
13
13
  Based on the Mathematica package [OGRe](https://github.com/bshoshany/OGRe) by Barak Shoshany.
14
14
 
15
- Copyright (c) 2024 [Barak Shoshany](https://baraksh.com/). Licensed under the [MIT license](https://github.com/bshoshany/OGRePy/blob/master/LICENSE.txt).
15
+ Copyright (c) 2025 [Barak Shoshany](https://baraksh.com/). Licensed under the [MIT license](https://github.com/bshoshany/OGRePy/blob/master/LICENSE.txt).
16
16
 
17
17
  If you use this package in software of any kind, please provide a link to [the GitHub repository](https://github.com/bshoshany/OGRePy) in the source code and documentation.
18
18
 
@@ -43,4 +43,4 @@ import sympy as s
43
43
  from ._core import Coordinates, CovariantD, Metric, OGRePyError, PartialD, Tensor, __version__, calc, cite, compare, diag, doc, func, info, options, release_date, sym, syms, update_check, welcome
44
44
 
45
45
  # The names that will be exported if using `from OGRePy import *`. Contains exactly all the names imported above.
46
- __all__: list[str] = ["s", "Coordinates", "CovariantD", "Metric", "OGRePyError", "PartialD", "Tensor", "__version__", "calc", "cite", "compare", "diag", "doc", "func", "info", "options", "release_date", "sym", "syms", "update_check", "welcome"]
46
+ __all__: list[str] = ["Coordinates", "CovariantD", "Metric", "OGRePyError", "PartialD", "Tensor", "__version__", "calc", "cite", "compare", "diag", "doc", "func", "info", "options", "release_date", "s", "sym", "syms", "update_check", "welcome"]
@@ -1,6 +1,6 @@
1
1
  r"""
2
2
  # OGRePy: An Object-Oriented General Relativity Package for Python
3
- v1.2.0 (2024-09-15)
3
+ v1.3.0 (2025-02-04)
4
4
 
5
5
  By **Barak Shoshany**\
6
6
  Email: <baraksh@gmail.com>\
@@ -12,7 +12,7 @@ PyPi project: <https://pypi.org/project/OGRePy/>
12
12
 
13
13
  Based on the Mathematica package [OGRe](https://github.com/bshoshany/OGRe) by Barak Shoshany.
14
14
 
15
- Copyright (c) 2024 [Barak Shoshany](https://baraksh.com/). Licensed under the [MIT license](https://github.com/bshoshany/OGRePy/blob/master/LICENSE.txt).
15
+ Copyright (c) 2025 [Barak Shoshany](https://baraksh.com/). Licensed under the [MIT license](https://github.com/bshoshany/OGRePy/blob/master/LICENSE.txt).
16
16
 
17
17
  If you use this package in software of any kind, please provide a link to [the GitHub repository](https://github.com/bshoshany/OGRePy) in the source code and documentation.
18
18
 
@@ -56,6 +56,7 @@ import inspect
56
56
  import itertools
57
57
  import json
58
58
  import os
59
+ import pathlib
59
60
  import re
60
61
  import sys
61
62
  import urllib.request
@@ -106,8 +107,8 @@ class OGRePyError(Exception):
106
107
  ####################
107
108
 
108
109
 
109
- __version__: str = "1.2.0"
110
- release_date: str = "2024-09-15"
110
+ __version__: str = "1.3.0"
111
+ release_date: str = "2025-02-04"
111
112
 
112
113
 
113
114
  ####################
@@ -250,11 +251,11 @@ def doc(
250
251
  try:
251
252
  signature: str = str(inspect.signature(obj)).replace("'", "")
252
253
  except (ValueError, TypeError):
253
- _handle_error(f"Could not find call signature for `{name if name != "" else "this object"}`.")
254
+ _handle_error(f"Could not find call signature for `{name if name != '' else 'this object'}`.")
254
255
  # Print the object's name, then its signature, then the docstring itself. Types in the signature will be surrounded by single quotes, so we eliminate those before printing.
255
256
  _display_markdown('<div style="border: 1px solid; margin: auto; padding: 1em; width: 90%">\n\n`' + name + signature + "`\n\n" + docs + "\n\n</div>")
256
257
  else:
257
- _handle_error(f"Could not find documentation for `{name if name != "" else "this object"}`.")
258
+ _handle_error(f"Could not find documentation for `{name if name != '' else 'this object'}`.")
258
259
 
259
260
 
260
261
  def func(
@@ -378,10 +379,13 @@ def welcome() -> None:
378
379
  Print the welcome message.
379
380
  """
380
381
  with importlib.resources.as_file(importlib.resources.files().joinpath("docs/OGRePy_Documentation")) as file:
381
- # Create links to the bundled documentation files.
382
- ipynb_link: str = f"""<a href="{file.with_suffix(".ipynb").as_posix()}">.ipynb</a>"""
383
- pdf_link: str = f"""<a href="{file.with_suffix(".pdf").as_posix()}">.pdf</a>"""
384
- html_link: str = f"""<a href="#" onclick="window.open('{file.with_suffix(".html").as_uri()}', '_blank')">.html</a>"""
382
+ # Create links to the bundled documentation files. However, if the files cannot be found, link to the files on the GitHub repository instead.
383
+ ipynb_file: pathlib.Path = file.with_suffix(".ipynb")
384
+ ipynb_link: str = f"""<a href="{ipynb_file.as_posix() if ipynb_file.exists() else "https://github.com/bshoshany/OGRePy/blob/master/OGRePy/docs/OGRePy_Documentation.ipynb"}">.ipynb</a>"""
385
+ pdf_file: pathlib.Path = file.with_suffix(".pdf")
386
+ pdf_link: str = f"""<a href="{pdf_file.as_posix() if pdf_file.exists() else "https://github.com/bshoshany/OGRePy/blob/master/OGRePy/docs/OGRePy_Documentation.pdf"}">.pdf</a>"""
387
+ html_file: pathlib.Path = file.with_suffix(".html")
388
+ html_link: str = f"""<a href="#" onclick="window.open('{html_file.as_uri() if html_file.exists() else "https://raw.githack.com/bshoshany/OGRePy/master/OGRePy/docs/OGRePy_Documentation.html"}', '_blank')">.html</a>"""
385
389
  # Display the welcome message.
386
390
  _display_markdown(
387
391
  inspect.cleandoc(rf"""
@@ -537,7 +541,7 @@ class Coordinates:
537
541
  text: str = f"* **Name**: {_lookup_names_string(self)}\n"
538
542
  text += f"* **Class**: {type(self).__name__}\n"
539
543
  text += f"* **Dimensions**: {self.dim()}\n"
540
- text += f"* **Default Coordinates For**: {", ".join(_using_coords(self))}\n"
544
+ text += f"* **Default Coordinates For**: {', '.join(_using_coords(self))}\n"
541
545
  _display_markdown(text)
542
546
 
543
547
  def inverse_jacobian(
@@ -1053,14 +1057,14 @@ class Tensor:
1053
1057
  calc_letters: IndexSpecification = _collect_tex_symbols(*letters)
1054
1058
  # Check that the index specification matches the rank of the tensor.
1055
1059
  if len(calc_letters) != self.rank():
1056
- _handle_error(f"{f"The index specification\n${"".join(calc_letters)}$\n" if len(calc_letters) > 0 else "The empty index specification "}does not match the rank of the tensor. The number of indices should be {self.rank()}.")
1060
+ _handle_error(f"{f'The index specification\n${"".join(calc_letters)}$\n' if len(calc_letters) > 0 else 'The empty index specification '}does not match the rank of the tensor. The number of indices should be {self.rank()}.")
1057
1061
  # Check for duplicate index letters.
1058
1062
  tally: dict[str, int] = {letter: calc_letters.count(letter) for letter in set(calc_letters)}
1059
1063
  max_duplicates: int = max(tally.values()) if len(tally) > 0 else 0
1060
1064
  if max_duplicates > 2:
1061
1065
  # We can't have more than 2 instances of the same index.
1062
1066
  invalid_indices: IndexSpecification = [letter for letter, count in tally.items() if count > 2]
1063
- _handle_error(f"The index specification\n${"".join(calc_letters)}$\nis invalid, as it contains more than two instances of the {"index" if len(invalid_indices) == 1 else "indices"} \n${", ".join(invalid_indices)}$\n.") # noqa: RET503
1067
+ _handle_error(f"The index specification\n${''.join(calc_letters)}$\nis invalid, as it contains more than two instances of the {'index' if len(invalid_indices) == 1 else 'indices'} \n${', '.join(invalid_indices)}$\n.") # noqa: RET503
1064
1068
  elif max_duplicates == 2:
1065
1069
  # If any indices appear exactly twice, we need to trace them.
1066
1070
  trace_letters: IndexSpecification = [letter for letter, count in tally.items() if count == 2]
@@ -1161,7 +1165,7 @@ class Tensor:
1161
1165
  # Count how many summation indices there already are in the first tensor's symbol (from previous contractions).
1162
1166
  contract_count: int = len(_unique_summation_placeholders(self._symbol))
1163
1167
  # Increase the numbering of the summation indices as well.
1164
- second_symbol = _summation_pattern.sub(lambda match: f"[{match[1] if match[1] else ""}{int(match[2]) + contract_count}{match[3] if match[3] else ""}]", second_symbol)
1168
+ second_symbol = _summation_pattern.sub(lambda match: f"[{match[1] if match[1] else ''}{int(match[2]) + contract_count}{match[3] if match[3] else ''}]", second_symbol)
1165
1169
  # Add the number of contractions in the second symbol to the total count.
1166
1170
  contract_count += len(_unique_summation_placeholders(second_symbol))
1167
1171
  # Join the symbols of the two tensors to create a new symbol for the output tensor, with consecutive summation index placeholders.
@@ -1420,7 +1424,7 @@ class Tensor:
1420
1424
  if coords is None:
1421
1425
  warning = f"Using default coordinate system {_lookup_names_string(use_coords)}"
1422
1426
  if indices is None:
1423
- warning += f"{"Using" if warning == "" else " and"} default index configuration {use_indices}"
1427
+ warning += f"{'Using' if warning == '' else ' and'} default index configuration {use_indices}"
1424
1428
  if warning != "":
1425
1429
  _display_markdown(f"**OGRePy**: {warning}.")
1426
1430
  # Retrieve the components, calculating them if they have not already been calculated.
@@ -1469,7 +1473,7 @@ class Tensor:
1469
1473
  text += f"* **Metric**: {_lookup_names_string(self._metric)}\n"
1470
1474
  else:
1471
1475
  used_by: list[str] = _using_metric(self)
1472
- text += f"* **Associated Metric For**: {", ".join(used_by) if len(used_by) > 0 else "None"}\n"
1476
+ text += f"* **Associated Metric For**: {', '.join(used_by) if len(used_by) > 0 else 'None'}\n"
1473
1477
  _display_markdown(text)
1474
1478
 
1475
1479
  def list(
@@ -1715,7 +1719,7 @@ class Tensor:
1715
1719
  out: str = r"\begin{align*}" + "\n"
1716
1720
  # Create an equation for each unique element. Note that in an {align*} environment, \\ indicates the end of a line and & indicates the position where the equations will be vertically aligned.
1717
1721
  for key, value in non_zero.items():
1718
- out += rf" {" = ".join(value)} &= {_to_tex(key)} \\" + "\n"
1722
+ out += rf" {' = '.join(value)} &= {_to_tex(key)} \\" + "\n"
1719
1723
  # Remove the last end of line indicator (otherwise there will be an extra empty line) and end the {align*} environment, then return the generated TeX code.
1720
1724
  return out[:-3] + "\n" + r"\end{align*}"
1721
1725
 
@@ -1831,9 +1835,10 @@ class Tensor:
1831
1835
  # Replace any derivative with respect to the curve parameter with a more compact partial derivative symbol, and enclose the argument in parentheses (which SymPy doesn't do for some reason).
1832
1836
  components = _array_subs(components, {f: sym(r"\partial_{" + _to_tex(param) + r"} \left(" + _to_tex(f.args[0]) + r"\right)") for f in components.atoms(s.Derivative) if f.args[1] == (param, 1)})
1833
1837
  # For all tensors, replace any derivative with respect to the coordinate symbols with a more compact partial derivative symbol.
1834
- for x in coord_symbols:
1835
- components = _array_subs(components, {f: sym(r"\partial_{" + _to_tex(x) + r"} " + _to_tex(f.args[0])) for f in components.atoms(s.Derivative) if f.args[1] == (x, 1)})
1836
- return components
1838
+ return _array_subs(
1839
+ components,
1840
+ {f: sym(r"\partial_{" + _to_tex(x) + ((r"^{" + str(f.args[1][1]) + r"}") if f.args[1][1] > 1 else "") + r"} " + _to_tex(f.args[0])) for x in coord_symbols for f in components.atoms(s.Derivative) if f.args[1][0] == x and f.args[1][1] > 0},
1841
+ )
1837
1842
 
1838
1843
  def _get_components(
1839
1844
  self: Self,
@@ -3389,7 +3394,7 @@ def _list_aliases(
3389
3394
  return f"`{names[0]}`"
3390
3395
  if len(names) == 2:
3391
3396
  return f"`{names[0]}` (alias: `{names[1]}`)"
3392
- return f"`{names[0]}` (aliases: `{"`, `".join(names[1:])}`)"
3397
+ return f"`{names[0]}` (aliases: `{'`, `'.join(names[1:])}`)"
3393
3398
 
3394
3399
 
3395
3400
  def _list_references(
@@ -3412,11 +3417,11 @@ def _list_references(
3412
3417
  if isinstance(ref, Coordinates):
3413
3418
  using: list[str] = _using_coords(ref)
3414
3419
  if len(using) > 0:
3415
- text += f", default for: `{"`, `".join(using)}`"
3420
+ text += f", default for: `{'`, `'.join(using)}`"
3416
3421
  elif isinstance(ref, Metric):
3417
3422
  using: list[str] = _using_metric(ref)
3418
3423
  if len(using) > 0:
3419
- text += f", used by: `{"`, `".join(using)}`"
3424
+ text += f", used by: `{'`, `'.join(using)}`"
3420
3425
  text += "\n"
3421
3426
  return text
3422
3427
 
@@ -3624,7 +3629,7 @@ def _using_object(
3624
3629
  # Create a list of relevant tensors, including aliases if any.
3625
3630
  using: list[str] = []
3626
3631
  for tensor, names in tensor_reverse.items():
3627
- if isinstance(obj, Coordinates) and obj is tensor.default_coords or isinstance(obj, Metric) and obj is tensor.metric():
3632
+ if (isinstance(obj, Coordinates) and obj is tensor.default_coords) or (isinstance(obj, Metric) and obj is tensor.metric()):
3628
3633
  using.append(_list_aliases(names))
3629
3634
  return using
3630
3635
 
@@ -3734,13 +3739,13 @@ def _validate_permutation(
3734
3739
  letters: IndexSpecification = _collect_tex_symbols(*index_spec)
3735
3740
  # Check that the index specifications matches the rank of the tensor.
3736
3741
  if len(letters) != rank:
3737
- _handle_error(f"The index specification\n${"".join(letters)}$\ndoes not match the rank of the tensor. The number of indices should be {rank}.")
3742
+ _handle_error(f"The index specification\n${''.join(letters)}$\ndoes not match the rank of the tensor. The number of indices should be {rank}.")
3738
3743
  # Check for duplicate index letters.
3739
3744
  tally: dict[str, int] = {letter: letters.count(letter) for letter in set(letters)}
3740
3745
  max_duplicates: int = max(tally.values()) if len(tally) > 0 else 0
3741
3746
  if max_duplicates > 1:
3742
3747
  invalid_indices: IndexSpecification = [letter for letter, count in tally.items() if count > 1]
3743
- _handle_error(f"The index specification\n${"".join(letters)}$\nis invalid, as it contains more than one instance of the {"index" if len(invalid_indices) == 1 else "indices"} \n${", ".join(invalid_indices)}$\n.")
3748
+ _handle_error(f"The index specification\n${''.join(letters)}$\nis invalid, as it contains more than one instance of the {'index' if len(invalid_indices) == 1 else 'indices'} \n${', '.join(invalid_indices)}$\n.")
3744
3749
  # Return the letters as a list of TeX strings.
3745
3750
  return letters
3746
3751
 
@@ -1,6 +1,6 @@
1
1
  r"""
2
2
  # OGRePy: An Object-Oriented General Relativity Package for Python
3
- v1.2.0 (2024-09-15)
3
+ v1.3.0 (2025-02-04)
4
4
 
5
5
  By **Barak Shoshany**\
6
6
  Email: <baraksh@gmail.com>\
@@ -12,7 +12,7 @@ PyPi project: <https://pypi.org/project/OGRePy/>
12
12
 
13
13
  Based on the Mathematica package [OGRe](https://github.com/bshoshany/OGRe) by Barak Shoshany.
14
14
 
15
- Copyright (c) 2024 [Barak Shoshany](https://baraksh.com/). Licensed under the [MIT license](https://github.com/bshoshany/OGRePy/blob/master/LICENSE.txt).
15
+ Copyright (c) 2025 [Barak Shoshany](https://baraksh.com/). Licensed under the [MIT license](https://github.com/bshoshany/OGRePy/blob/master/LICENSE.txt).
16
16
 
17
17
  If you use this package in software of any kind, please provide a link to [the GitHub repository](https://github.com/bshoshany/OGRePy) in the source code and documentation.
18
18