Compare commits

..

19 Commits

Author SHA1 Message Date
ee04517e29 Moved PyQt-Plotter-Dialog to separate repository: https://git.dm1sh.ru/ADV/PyQt-Plotter-Dialog 2023-10-30 16:46:25 +03:00
3ad859e16c Update of readme 2023-10-30 10:55:01 +03:00
2d82aa2258 Updated parser syntax docs 2023-10-29 20:43:25 +03:00
89e12d250f Fixed incorrect dimensions plotting error 2023-10-29 20:23:38 +03:00
9ea4a29d2d Merge remote-tracking branch 'refs/remotes/origin/main' 2023-10-29 19:23:18 +03:00
c1f573298e Updated global readme 2023-10-29 19:17:43 +03:00
59bb5d901f Documented parser package files 2023-10-29 19:10:49 +03:00
02f17d2e51 Added default functions and their names layout in PlotterDialog 2023-10-29 19:08:04 +03:00
94b2d0eddc i hate my live and this shit 2023-10-29 17:33:27 +03:00
e2b9025bc5 Refactored project to remove poetry. Pure pip used instead 2023-10-24 13:48:24 +03:00
eb6309582e Moved PlotterDialog module to subdirectory, added poetry, added example, added FlowLayout for newlines, Added plot expression parsing and plotting with Parser and GraphWidget, added plots input reset, added first input auto focus 2023-10-19 03:28:29 +03:00
0b8647ccc4 Fixed tanh operation name 2023-10-19 03:25:51 +03:00
bb317c409f Moved GraphWidget module to subdirectory, added poetry 2023-10-19 03:25:34 +03:00
1436503454 Splited PlotterDialog into files, added buttons functionality, small UI improvements 2023-10-19 01:08:37 +03:00
e963806464 Applied formatter 2023-10-18 22:10:32 +03:00
6887247d8d Загрузить файлы в «GraphWidget» 2023-10-18 21:44:14 +03:00
f1ab7c2750 Работающая qtшка, сделанная под руководством Димы 2023-10-18 21:02:21 +03:00
dba43e3748 Created real graph builder and deleted example 2023-10-18 17:39:20 +03:00
ca29c3ff95 Объединение второго и третьего виджетов в один 2023-10-18 10:01:13 +03:00
22 changed files with 5 additions and 1105 deletions

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
__pycache__/
.vscode/
.venv/
*.egg-info/
build/

View File

@ -1,5 +0,0 @@
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg
class GraphWidget(FigureCanvasQTAgg):
def __init__(self, *args):
...

View File

@ -1,48 +0,0 @@
import numpy as np
import matplotlib.pyplot as plt
class GraphStatic:
@classmethod
def plot(cls, xs: np.ndarray, ys: np.ndarray, params: dict[str, str]) -> plt.Figure:
"""
строим график через
"""
ax, fig = plt.subplots(...)
""""
Все методы при этом статичные
"""
cls.__some_func(1, 2)
"""
И возвращаем Figure
"""
return fig
@staticmethod
def __some_func(arg1, agr2):
...
class GraphStatefull:
def __init__(self, xs: np.ndarray, ys: np.ndarray, params: dict[str, str]):
self.__xs = xs
self.__ys = ys
self.__params = params
ax, fig = plt.subplots(...)
self.__fig = fig
self.__ax = ax
"""
строим график
"""
def __some_func(self, arg1, arg2):
self.__ax.do_something(self.__params['something'])
def get_fig(self) -> plt.Figure:
return self.__fig

View File

@ -1,3 +0,0 @@
from .GraphWidget import GraphWidget
__all__ = ("GraphWidget",)

View File

@ -1,10 +0,0 @@
from PyQt5.QtWidgets import QDialog
class PlotterDIalog(QDialog):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
...

View File

@ -1,3 +0,0 @@
from .PlotterDialog import PlotterDialog
__all__ = ("PlotterDialog",)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 340 B

View File

@ -1,96 +0,0 @@
from PyQt5.QtWidgets import *
class Widget1(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent=parent)
layout = QFormLayout(self)
LineEditGraf = QLineEdit("график 1")
NameX=QGroupBox("X")
NameY = QGroupBox("Y")
LineEditX = QLineEdit()
LineEditY = QLineEdit()
layout.addWidget(LineEditGraf)
layout.addWidget(NameX)
layout.addWidget(LineEditX)
layout.addWidget(NameY)
layout.addWidget(LineEditY)
class Widget2(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent=parent)
layout = QHBoxLayout(self)
# Кнопки функций
VariabelsButton_t = QPushButton('t', self)
#VariabelsButton_t.clicked.connect(self.on_click)
layout.addWidget(VariabelsButton_t)
VariabelsButton_p = QPushButton('p', self)
# VariabelsButton_p.clicked.connect(self.on_click)
layout.addWidget(VariabelsButton_p)
VariabelsButton_f = QPushButton('f', self)
# VariabelsButton_f.clicked.connect(self.on_click)
layout.addWidget(VariabelsButton_f)
class Widget3(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent=parent)
layout = QHBoxLayout(self)
# Кнопки функций
FunctonButton_exp = QPushButton('exp', self)
#FunctonButton_exp.clicked.connect(self.on_click)
layout.addWidget(FunctonButton_exp)
FunctonButton_ln = QPushButton('ln', self)
#FunctonButton_ln.clicked.connect(self.on_click)
layout.addWidget(FunctonButton_ln)
FunctonButton_abs = QPushButton('abs', self)
#FunctonButton_abs.clicked.connect(self.on_click)
layout.addWidget(FunctonButton_abs)
FunctonButton_sin = QPushButton('sin', self)
#FunctonButton_sin.clicked.connect(self.on_click)
layout.addWidget(FunctonButton_sin)
FunctonButton_cos = QPushButton('cos', self)
#FunctonButton_cos.clicked.connect(self.on_click)
layout.addWidget(FunctonButton_cos)
FunctonButton_tg = QPushButton('tg', self)
#FunctonButton_tg.clicked.connect(self.on_click)
layout.addWidget(FunctonButton_tg)
class stackedExample(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent=parent)
lay = QVBoxLayout(self)
self.Stack = QStackedWidget()
self.Stack.addWidget(Widget1())
self.Stack.addWidget(Widget2())
self.Stack.addWidget(Widget3())
btnNext = QPushButton("Next")
btnNext.clicked.connect(self.onNext)
btnPrevious = QPushButton("Previous")
btnPrevious.clicked.connect(self.onPrevious)
btnLayout = QHBoxLayout()
btnLayout.addWidget(btnPrevious)
btnLayout.addWidget(btnNext)
lay.addWidget(self.Stack)
lay.addLayout(btnLayout)
def onNext(self):
self.Stack.setCurrentIndex((self.Stack.currentIndex()+1) % 3)
def onPrevious(self):
self.Stack.setCurrentIndex((self.Stack.currentIndex()-1) % 3)
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
w = stackedExample()
w.show()
sys.exit(app.exec_())

1
parser/.gitignore vendored
View File

@ -1 +0,0 @@
*.pyc

View File

@ -1,68 +0,0 @@
# Math expression parser
Math expression evaluation library. It supports most of useful math operations and functions. Expressions can contain variables which can be substituted with `int`s, `float`s or `numpy.ndarray`s.
## Example usage
```python
from parser import Parser
parser = Parser("(-b + sqrt(b^2-4a c))/(2a)")
parser.variables_names # {'c', 'a', 'b'}
parser.evaluate({"a": 1, "b": -3, "c": 2}) # 1.0
parser.evaluate({"a": [1, 1, 1], "b": [-5, -6, -9], "c": [6, 9, 20]}) # [2. 3. 4.]
```
## Expression syntax
Expression can contain numbers or variable names with functions applyed to them, separated with operators or united with braces.
Theese are supported:
Functions:
|name| math |
|--|--|
| `abs` | $\|x\|$ |
| `acos` | $\cos^{-1}(x)$ |
| `acosh` | $\cosh^{-1}(x)$ |
| `acot` | $\cot^{-1}(x)$ |
| `asin` | $\sin^{-1}(x)$ |
| `asinh` | $\sinh^{-1}(x)$ |
| `atan` | $\tan^{-1}(x)$ |
| `avg` | $\overline X$ |
| `cos` | $\cos(x)$ |
| `cosh` | $\cosh(x)$ |
| `cot` | $\cot(x)$ |
| `exp` | $\exp(x)$ |
| `inf` | $\inf(X)$ |
| `lg` | $\lg(x)$ |
| `ln` | $\ln(x)$ |
| `log10` | $\log_{10}(x)$ |
| `log2` | $\log_2(x)$ |
| `max` | $\sup(X)$ |
| `min` | $\inf(X)$ |
| `prod` | $\displaystyle \prod_{i=0}^n x_i$ |
| `sgn` | $sgn(x)$ |
| `sign` | $sgn(x)$ |
| `sin` | $\sin(x)$ |
| `sinh` | $\sinh(x)$ |
| `sqrt` | $\sqrt{x}$ |
| `sum` | $\displaystyle\sum_{i=0}^n x_i$ |
| `sup` | $\sup(X)$ |
| `tan` | $\tan(x)$ |
| `tanh` | $\tanh(x)$ |
Operators: `+`, `-`, `*`, `/`, `^`, `%`
Braces: `()`, `[]`, `{}`
Floating points: `.`, `,`
Functions have only one argument, provided in braces. Operators must have two operands except minus (if it is the first character of equation or braced expression).
`avg`, `sum`, `max`, `sup`, `min`, `inf` and `prod` applied on `numpy.ndarray` produce `float`.
**! There is no error handling yet !**

View File

@ -1,21 +0,0 @@
from .parser import (
BinaryExpression,
Expression,
Operation,
Parser,
Token,
Tokenizer,
UnaryExpression,
ValueExpression,
)
__all__ = (
"BinaryExpression",
"Expression",
"Operation",
"Parser",
"Token",
"Tokenizer",
"UnaryExpression",
"ValueExpression",
)

View File

@ -1,16 +0,0 @@
from parser import Parser
expression = input("Input math expression: ")
parser = Parser(expression)
print("Variables in your expression: " + ", ".join(parser.variables_names))
variables = {}
for key in parser.variables_names:
variables[key] = float(input(f"Input '{key}' variable value: "))
res = parser.evaluate(variables)
print(f"Evaluation result is: {res}")

View File

@ -1,6 +0,0 @@
import numpy as np
CONSTANTS = {
"e": np.e,
"pi": np.pi,
}

View File

@ -1,52 +0,0 @@
import abc
from collections.abc import Callable, Mapping
from .types import FunctionType, OperatorType, ValueType
class Expression(abc.ABC):
_evaluator: Callable[[Mapping[str, ValueType]], ValueType]
def evaluate(self, variables: Mapping[str, ValueType]):
return self._evaluator(variables)
class ValueExpression(Expression):
def __init__(self, a: str | ValueType):
self.__debug_a = a
if isinstance(a, str):
self._evaluator = lambda vars: vars[a]
else:
self._evaluator = lambda _: a
def __repr__(self):
return f"<{self.__debug_a}>"
class UnaryExpression(Expression):
def __init__(self, function: FunctionType, a: Expression):
self.__debug_f = function.__name__
self.__debug_a = repr(a)
self._evaluator = lambda vars: function(a.evaluate(vars))
def __repr__(self):
return f"<{self.__debug_f}({self.__debug_a})>"
class BinaryExpression(Expression):
def __init__(
self,
function: OperatorType,
a: Expression,
b: Expression,
):
self.__debug_f = function.__name__
self.__debug_a = repr(a)
self.__debug_b = repr(b)
self._evaluator = lambda vars: function(a.evaluate(vars), b.evaluate(vars))
def __repr__(self):
return f"<{self.__debug_a} {self.__debug_f} {self.__debug_b}>"

View File

@ -1,89 +0,0 @@
from dataclasses import dataclass
import numpy as np
from .types import FunctionType, OperatorType, ValueType
def acot(x: ValueType):
return np.arctan(1 / x)
def cot(x: ValueType):
return 1 / np.tan(x)
functions: dict[str, FunctionType] = {
"abs": np.abs,
"acos": np.arccos,
"acosh": np.arccosh,
"acot": acot,
"asin": np.arcsin,
"asinh": np.arcsinh,
"atan": np.arctan,
"avg": np.average,
"cos": np.cos,
"cosh": np.cosh,
"cot": cot,
"exp": np.exp,
"inf": np.inf,
"lg": np.log10,
"ln": np.log,
"log10": np.log10,
"log2": np.log2,
"max": np.max,
"min": np.min,
"prod": np.prod,
"sgn": np.sign,
"sign": np.sign,
"sin": np.sin,
"sinh": np.sinh,
"sqrt": np.sqrt,
"sum": np.sum,
"sup": np.max,
"tah": np.tanh,
"tan": np.tan,
}
operators: dict[str, OperatorType] = {
"+": np.add,
"-": np.subtract,
"*": np.multiply,
"/": np.divide,
"%": np.mod,
"^": np.float_power,
}
priorities: dict[str, int] = {
"(": 0,
"+": 1,
"-": 1,
"*": 2,
"/": 2,
"%": 2,
"^": 3,
"f": 4, # function
")": 5,
}
@dataclass
class Operation:
evaluator: (FunctionType | OperatorType | str)
priority: int
size: int
class FunctionOperation(Operation):
def __init__(self, name: str):
super().__init__(functions[name], priorities["f"], 1)
class BraceOperation(Operation):
def __init__(self, name: str):
super().__init__(name, priorities[name], 0)
class OperatorOperation(Operation):
def __init__(self, name: str):
super().__init__(operators[name], priorities[name], 2)

View File

@ -1,81 +0,0 @@
from .expression import BinaryExpression, Expression, UnaryExpression, ValueExpression
from .operation import (
BraceOperation,
FunctionOperation,
Operation,
OperatorOperation,
priorities,
)
from .tokenizer import Token, Tokenizer
from .types import ValueType
from .constants import CONSTANTS
class Parser:
def __init__(self, input_expr: str):
self.input_expr = input_expr
self.variables_names: set[str] = set()
self.tokenize()
self.parse()
def tokenize(self):
self.tokens = Tokenizer(self.input_expr)
def parse(self):
self.val_stack: list[Expression] = []
self.op_stack: list[Operation] = []
for t_val, t_type in self.tokens:
if t_type in (Token.Number, Token.Variable):
self.val_stack.append(ValueExpression(t_val))
if t_type == Token.Variable:
self.variables_names.add(t_val)
elif t_type == Token.Function:
self.op_stack.append(FunctionOperation(t_val))
elif t_type == Token.LBrace:
self.op_stack.append(BraceOperation("("))
elif t_type == Token.RBrace:
while len(self.op_stack) > 0 and not (
self.op_stack[-1].size == 0 and self.op_stack[-1].priority == 0
): # until next in stack is lbrace
self.do_one()
self.op_stack.pop() # pop lbrace
elif t_type == Token.Operator:
t_priority = priorities[t_val]
while (
len(self.op_stack) > 0 and self.op_stack[-1].priority > t_priority
):
self.do_one()
self.op_stack.append(OperatorOperation(t_val))
while len(self.op_stack) > 0:
self.do_one()
self._evaluator = self.val_stack[0].evaluate
self.__debug_expr = repr(self.val_stack)
def evaluate(self, variables: dict[str, ValueType]):
variables |= CONSTANTS
return self._evaluator(variables)
def do_one(self):
op = self.op_stack.pop()
if op.size == 1:
a = self.val_stack.pop()
self.val_stack.append(UnaryExpression(op.evaluator, a))
elif op.size == 2:
b, a = self.val_stack.pop(), self.val_stack.pop() # inversed pop order
self.val_stack.append(BinaryExpression(op.evaluator, a, b))
def __repr__(self):
return self.__debug_expr

View File

@ -1,108 +0,0 @@
from collections.abc import Generator
from dataclasses import dataclass
from typing import Optional
from .operation import functions, operators
from .types import Token, TokenType
@dataclass
class Tokenizer:
expression: str
def __iter__(self) -> Generator[TokenType, None, None]:
accumulator = ""
prev = None
for ch in self.expression:
if (breaker_type := Tokenizer.is_breaker(ch)) is not None:
if len(accumulator) > 0:
# ch is `(` after function name
if breaker_type == Token.LBrace and Tokenizer.is_function(
accumulator
):
yield accumulator, Token.Function
prev = Token.Function
accumulator = ""
else:
value, token_type = Tokenizer.detect_number(accumulator)
yield value, token_type
prev = token_type
accumulator = ""
# `(` after variable or number
if breaker_type == Token.LBrace:
yield "*", Token.Operator
prev = Token.Operator
# Unary minus case
if ch == "-" and (prev == Token.LBrace or prev is None):
yield 0, Token.Number
prev = Token.Number
# `(expr)(expr)` case
if breaker_type == Token.LBrace and prev == Token.RBrace:
yield "*", Token.Operator
prev = Token.Operator
if breaker_type != Token.Space:
yield ch, breaker_type
prev = breaker_type
else:
# Variable or function name after braced expr or variable and space
if prev == Token.RBrace or prev == Token.Variable:
yield "*", Token.Operator
prev = Token.Operator
# Floating point number
if ch in ",.":
accumulator += "."
continue
# Variable or function name after number
if (
not ch.isdecimal()
and (num := Tokenizer.is_number(accumulator)) is not None
):
yield num, Token.Number
yield "*", Token.Operator
prev = Token.Operator
accumulator = ""
accumulator += ch
if len(accumulator) > 0:
yield self.detect_number(accumulator)
@staticmethod
def is_breaker(character) -> Optional[Token]:
if character in operators:
return Token.Operator
if character in "([{":
return Token.LBrace
if character in ")]}":
return Token.RBrace
if character == " ":
return Token.Space
return None
@staticmethod
def is_number(string) -> Optional[float]:
try:
return float(string)
except ValueError:
return None
@staticmethod
def detect_number(string) -> TokenType:
if (num := Tokenizer.is_number(string)) is not None:
return num, Token.Number
else:
return string, Token.Variable
@staticmethod
def is_function(lexeme: str) -> bool:
if lexeme in functions:
return True
return False

View File

@ -1,23 +0,0 @@
from collections.abc import Callable
from enum import Enum, auto
import numpy as np
ValueType = int | float | np.ndarray
FunctionType = Callable[[ValueType], ValueType]
OperatorType = Callable[[ValueType, ValueType], ValueType]
class Token(Enum):
Variable = auto()
Number = auto()
Function = auto()
Operator = auto()
LBrace = auto()
RBrace = auto()
Space = auto()
TokenType = tuple[str | float, Token]

436
parser/poetry.lock generated
View File

@ -1,436 +0,0 @@
# This file is automatically @generated by Poetry and should not be changed by hand.
[[package]]
name = "attrs"
version = "23.1.0"
description = "Classes Without Boilerplate"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
{file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"},
{file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"},
]
[package.extras]
cov = ["attrs[tests]", "coverage[toml] (>=5.3)"]
dev = ["attrs[docs,tests]", "pre-commit"]
docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"]
tests = ["attrs[tests-no-zope]", "zope-interface"]
tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
[[package]]
name = "black"
version = "23.9.1"
description = "The uncompromising code formatter."
category = "dev"
optional = false
python-versions = ">=3.8"
files = [
{file = "black-23.9.1-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:d6bc09188020c9ac2555a498949401ab35bb6bf76d4e0f8ee251694664df6301"},
{file = "black-23.9.1-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:13ef033794029b85dfea8032c9d3b92b42b526f1ff4bf13b2182ce4e917f5100"},
{file = "black-23.9.1-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:75a2dc41b183d4872d3a500d2b9c9016e67ed95738a3624f4751a0cb4818fe71"},
{file = "black-23.9.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13a2e4a93bb8ca74a749b6974925c27219bb3df4d42fc45e948a5d9feb5122b7"},
{file = "black-23.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:adc3e4442eef57f99b5590b245a328aad19c99552e0bdc7f0b04db6656debd80"},
{file = "black-23.9.1-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:8431445bf62d2a914b541da7ab3e2b4f3bc052d2ccbf157ebad18ea126efb91f"},
{file = "black-23.9.1-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:8fc1ddcf83f996247505db6b715294eba56ea9372e107fd54963c7553f2b6dfe"},
{file = "black-23.9.1-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:7d30ec46de88091e4316b17ae58bbbfc12b2de05e069030f6b747dfc649ad186"},
{file = "black-23.9.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:031e8c69f3d3b09e1aa471a926a1eeb0b9071f80b17689a655f7885ac9325a6f"},
{file = "black-23.9.1-cp311-cp311-win_amd64.whl", hash = "sha256:538efb451cd50f43aba394e9ec7ad55a37598faae3348d723b59ea8e91616300"},
{file = "black-23.9.1-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:638619a559280de0c2aa4d76f504891c9860bb8fa214267358f0a20f27c12948"},
{file = "black-23.9.1-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:a732b82747235e0542c03bf352c126052c0fbc458d8a239a94701175b17d4855"},
{file = "black-23.9.1-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:cf3a4d00e4cdb6734b64bf23cd4341421e8953615cba6b3670453737a72ec204"},
{file = "black-23.9.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf99f3de8b3273a8317681d8194ea222f10e0133a24a7548c73ce44ea1679377"},
{file = "black-23.9.1-cp38-cp38-win_amd64.whl", hash = "sha256:14f04c990259576acd093871e7e9b14918eb28f1866f91968ff5524293f9c573"},
{file = "black-23.9.1-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:c619f063c2d68f19b2d7270f4cf3192cb81c9ec5bc5ba02df91471d0b88c4c5c"},
{file = "black-23.9.1-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:6a3b50e4b93f43b34a9d3ef00d9b6728b4a722c997c99ab09102fd5efdb88325"},
{file = "black-23.9.1-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:c46767e8df1b7beefb0899c4a95fb43058fa8500b6db144f4ff3ca38eb2f6393"},
{file = "black-23.9.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50254ebfa56aa46a9fdd5d651f9637485068a1adf42270148cd101cdf56e0ad9"},
{file = "black-23.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:403397c033adbc45c2bd41747da1f7fc7eaa44efbee256b53842470d4ac5a70f"},
{file = "black-23.9.1-py3-none-any.whl", hash = "sha256:6ccd59584cc834b6d127628713e4b6b968e5f79572da66284532525a042549f9"},
{file = "black-23.9.1.tar.gz", hash = "sha256:24b6b3ff5c6d9ea08a8888f6977eae858e1f340d7260cf56d70a49823236b62d"},
]
[package.dependencies]
click = ">=8.0.0"
mypy-extensions = ">=0.4.3"
packaging = ">=22.0"
pathspec = ">=0.9.0"
platformdirs = ">=2"
[package.extras]
colorama = ["colorama (>=0.4.3)"]
d = ["aiohttp (>=3.7.4)"]
jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"]
uvloop = ["uvloop (>=0.15.2)"]
[[package]]
name = "cattrs"
version = "23.1.2"
description = "Composable complex class support for attrs and dataclasses."
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
{file = "cattrs-23.1.2-py3-none-any.whl", hash = "sha256:b2bb14311ac17bed0d58785e5a60f022e5431aca3932e3fc5cc8ed8639de50a4"},
{file = "cattrs-23.1.2.tar.gz", hash = "sha256:db1c821b8c537382b2c7c66678c3790091ca0275ac486c76f3c8f3920e83c657"},
]
[package.dependencies]
attrs = ">=20"
[package.extras]
bson = ["pymongo (>=4.2.0,<5.0.0)"]
cbor2 = ["cbor2 (>=5.4.6,<6.0.0)"]
msgpack = ["msgpack (>=1.0.2,<2.0.0)"]
orjson = ["orjson (>=3.5.2,<4.0.0)"]
pyyaml = ["PyYAML (>=6.0,<7.0)"]
tomlkit = ["tomlkit (>=0.11.4,<0.12.0)"]
ujson = ["ujson (>=5.4.0,<6.0.0)"]
[[package]]
name = "click"
version = "8.1.7"
description = "Composable command line interface toolkit"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
{file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"},
{file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"},
]
[package.dependencies]
colorama = {version = "*", markers = "platform_system == \"Windows\""}
[[package]]
name = "colorama"
version = "0.4.6"
description = "Cross-platform colored terminal text."
category = "dev"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
files = [
{file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
]
[[package]]
name = "docstring-to-markdown"
version = "0.12"
description = "On the fly conversion of Python docstrings to markdown"
category = "dev"
optional = false
python-versions = ">=3.6"
files = [
{file = "docstring-to-markdown-0.12.tar.gz", hash = "sha256:40004224b412bd6f64c0f3b85bb357a41341afd66c4b4896709efa56827fb2bb"},
{file = "docstring_to_markdown-0.12-py3-none-any.whl", hash = "sha256:7df6311a887dccf9e770f51242ec002b19f0591994c4783be49d24cdc1df3737"},
]
[[package]]
name = "isort"
version = "5.12.0"
description = "A Python utility / library to sort Python imports."
category = "dev"
optional = false
python-versions = ">=3.8.0"
files = [
{file = "isort-5.12.0-py3-none-any.whl", hash = "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6"},
{file = "isort-5.12.0.tar.gz", hash = "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504"},
]
[package.extras]
colors = ["colorama (>=0.4.3)"]
pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"]
plugins = ["setuptools"]
requirements-deprecated-finder = ["pip-api", "pipreqs"]
[[package]]
name = "jedi"
version = "0.19.1"
description = "An autocompletion tool for Python that can be used for text editors."
category = "dev"
optional = false
python-versions = ">=3.6"
files = [
{file = "jedi-0.19.1-py2.py3-none-any.whl", hash = "sha256:e983c654fe5c02867aef4cdfce5a2fbb4a50adc0af145f70504238f18ef5e7e0"},
{file = "jedi-0.19.1.tar.gz", hash = "sha256:cf0496f3651bc65d7174ac1b7d043eff454892c708a87d1b683e57b569927ffd"},
]
[package.dependencies]
parso = ">=0.8.3,<0.9.0"
[package.extras]
docs = ["Jinja2 (==2.11.3)", "MarkupSafe (==1.1.1)", "Pygments (==2.8.1)", "alabaster (==0.7.12)", "babel (==2.9.1)", "chardet (==4.0.0)", "commonmark (==0.8.1)", "docutils (==0.17.1)", "future (==0.18.2)", "idna (==2.10)", "imagesize (==1.2.0)", "mock (==1.0.1)", "packaging (==20.9)", "pyparsing (==2.4.7)", "pytz (==2021.1)", "readthedocs-sphinx-ext (==2.1.4)", "recommonmark (==0.5.0)", "requests (==2.25.1)", "six (==1.15.0)", "snowballstemmer (==2.1.0)", "sphinx (==1.8.5)", "sphinx-rtd-theme (==0.4.3)", "sphinxcontrib-serializinghtml (==1.1.4)", "sphinxcontrib-websupport (==1.2.4)", "urllib3 (==1.26.4)"]
qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"]
testing = ["Django", "attrs", "colorama", "docopt", "pytest (<7.0.0)"]
[[package]]
name = "jedi-language-server"
version = "0.41.1"
description = "A language server for Jedi!"
category = "dev"
optional = false
python-versions = ">=3.8,<4.0"
files = [
{file = "jedi_language_server-0.41.1-py3-none-any.whl", hash = "sha256:ca9b3e7f48b70f0988d85ffde4f01dd1ab94c8e0f69e8c6424e6657117b44f91"},
{file = "jedi_language_server-0.41.1.tar.gz", hash = "sha256:3f15ca5cc28e728564f7d63583e171b418025582447ce023512e3f2b2d71ebae"},
]
[package.dependencies]
cattrs = ">=23.1.2"
docstring-to-markdown = "<1.0.0"
jedi = ">=0.19.0,<0.20.0"
lsprotocol = ">=2022.0.0a9"
pygls = ">=1.0.1,<2.0.0"
[[package]]
name = "lsprotocol"
version = "2023.0.0b1"
description = "Python implementation of the Language Server Protocol."
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
{file = "lsprotocol-2023.0.0b1-py3-none-any.whl", hash = "sha256:ade2cd0fa0ede7965698cb59cd05d3adbd19178fd73e83f72ef57a032fbb9d62"},
{file = "lsprotocol-2023.0.0b1.tar.gz", hash = "sha256:f7a2d4655cbd5639f373ddd1789807450c543341fa0a32b064ad30dbb9f510d4"},
]
[package.dependencies]
attrs = ">=21.3.0"
cattrs = "*"
[[package]]
name = "mypy"
version = "1.5.1"
description = "Optional static typing for Python"
category = "dev"
optional = false
python-versions = ">=3.8"
files = [
{file = "mypy-1.5.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f33592ddf9655a4894aef22d134de7393e95fcbdc2d15c1ab65828eee5c66c70"},
{file = "mypy-1.5.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:258b22210a4a258ccd077426c7a181d789d1121aca6db73a83f79372f5569ae0"},
{file = "mypy-1.5.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9ec1f695f0c25986e6f7f8778e5ce61659063268836a38c951200c57479cc12"},
{file = "mypy-1.5.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:abed92d9c8f08643c7d831300b739562b0a6c9fcb028d211134fc9ab20ccad5d"},
{file = "mypy-1.5.1-cp310-cp310-win_amd64.whl", hash = "sha256:a156e6390944c265eb56afa67c74c0636f10283429171018446b732f1a05af25"},
{file = "mypy-1.5.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6ac9c21bfe7bc9f7f1b6fae441746e6a106e48fc9de530dea29e8cd37a2c0cc4"},
{file = "mypy-1.5.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:51cb1323064b1099e177098cb939eab2da42fea5d818d40113957ec954fc85f4"},
{file = "mypy-1.5.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:596fae69f2bfcb7305808c75c00f81fe2829b6236eadda536f00610ac5ec2243"},
{file = "mypy-1.5.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:32cb59609b0534f0bd67faebb6e022fe534bdb0e2ecab4290d683d248be1b275"},
{file = "mypy-1.5.1-cp311-cp311-win_amd64.whl", hash = "sha256:159aa9acb16086b79bbb0016145034a1a05360626046a929f84579ce1666b315"},
{file = "mypy-1.5.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f6b0e77db9ff4fda74de7df13f30016a0a663928d669c9f2c057048ba44f09bb"},
{file = "mypy-1.5.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:26f71b535dfc158a71264e6dc805a9f8d2e60b67215ca0bfa26e2e1aa4d4d373"},
{file = "mypy-1.5.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fc3a600f749b1008cc75e02b6fb3d4db8dbcca2d733030fe7a3b3502902f161"},
{file = "mypy-1.5.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:26fb32e4d4afa205b24bf645eddfbb36a1e17e995c5c99d6d00edb24b693406a"},
{file = "mypy-1.5.1-cp312-cp312-win_amd64.whl", hash = "sha256:82cb6193de9bbb3844bab4c7cf80e6227d5225cc7625b068a06d005d861ad5f1"},
{file = "mypy-1.5.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4a465ea2ca12804d5b34bb056be3a29dc47aea5973b892d0417c6a10a40b2d65"},
{file = "mypy-1.5.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9fece120dbb041771a63eb95e4896791386fe287fefb2837258925b8326d6160"},
{file = "mypy-1.5.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d28ddc3e3dfeab553e743e532fb95b4e6afad51d4706dd22f28e1e5e664828d2"},
{file = "mypy-1.5.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:57b10c56016adce71fba6bc6e9fd45d8083f74361f629390c556738565af8eeb"},
{file = "mypy-1.5.1-cp38-cp38-win_amd64.whl", hash = "sha256:ff0cedc84184115202475bbb46dd99f8dcb87fe24d5d0ddfc0fe6b8575c88d2f"},
{file = "mypy-1.5.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8f772942d372c8cbac575be99f9cc9d9fb3bd95c8bc2de6c01411e2c84ebca8a"},
{file = "mypy-1.5.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5d627124700b92b6bbaa99f27cbe615c8ea7b3402960f6372ea7d65faf376c14"},
{file = "mypy-1.5.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:361da43c4f5a96173220eb53340ace68cda81845cd88218f8862dfb0adc8cddb"},
{file = "mypy-1.5.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:330857f9507c24de5c5724235e66858f8364a0693894342485e543f5b07c8693"},
{file = "mypy-1.5.1-cp39-cp39-win_amd64.whl", hash = "sha256:c543214ffdd422623e9fedd0869166c2f16affe4ba37463975043ef7d2ea8770"},
{file = "mypy-1.5.1-py3-none-any.whl", hash = "sha256:f757063a83970d67c444f6e01d9550a7402322af3557ce7630d3c957386fa8f5"},
{file = "mypy-1.5.1.tar.gz", hash = "sha256:b031b9601f1060bf1281feab89697324726ba0c0bae9d7cd7ab4b690940f0b92"},
]
[package.dependencies]
mypy-extensions = ">=1.0.0"
typing-extensions = ">=4.1.0"
[package.extras]
dmypy = ["psutil (>=4.0)"]
install-types = ["pip"]
reports = ["lxml"]
[[package]]
name = "mypy-extensions"
version = "1.0.0"
description = "Type system extensions for programs checked with the mypy type checker."
category = "dev"
optional = false
python-versions = ">=3.5"
files = [
{file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"},
{file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"},
]
[[package]]
name = "numpy"
version = "1.26.0"
description = "Fundamental package for array computing in Python"
category = "main"
optional = false
python-versions = "<3.13,>=3.9"
files = [
{file = "numpy-1.26.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f8db2f125746e44dce707dd44d4f4efeea8d7e2b43aace3f8d1f235cfa2733dd"},
{file = "numpy-1.26.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0621f7daf973d34d18b4e4bafb210bbaf1ef5e0100b5fa750bd9cde84c7ac292"},
{file = "numpy-1.26.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:51be5f8c349fdd1a5568e72713a21f518e7d6707bcf8503b528b88d33b57dc68"},
{file = "numpy-1.26.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:767254ad364991ccfc4d81b8152912e53e103ec192d1bb4ea6b1f5a7117040be"},
{file = "numpy-1.26.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:436c8e9a4bdeeee84e3e59614d38c3dbd3235838a877af8c211cfcac8a80b8d3"},
{file = "numpy-1.26.0-cp310-cp310-win32.whl", hash = "sha256:c2e698cb0c6dda9372ea98a0344245ee65bdc1c9dd939cceed6bb91256837896"},
{file = "numpy-1.26.0-cp310-cp310-win_amd64.whl", hash = "sha256:09aaee96c2cbdea95de76ecb8a586cb687d281c881f5f17bfc0fb7f5890f6b91"},
{file = "numpy-1.26.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:637c58b468a69869258b8ae26f4a4c6ff8abffd4a8334c830ffb63e0feefe99a"},
{file = "numpy-1.26.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:306545e234503a24fe9ae95ebf84d25cba1fdc27db971aa2d9f1ab6bba19a9dd"},
{file = "numpy-1.26.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c6adc33561bd1d46f81131d5352348350fc23df4d742bb246cdfca606ea1208"},
{file = "numpy-1.26.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e062aa24638bb5018b7841977c360d2f5917268d125c833a686b7cbabbec496c"},
{file = "numpy-1.26.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:546b7dd7e22f3c6861463bebb000646fa730e55df5ee4a0224408b5694cc6148"},
{file = "numpy-1.26.0-cp311-cp311-win32.whl", hash = "sha256:c0b45c8b65b79337dee5134d038346d30e109e9e2e9d43464a2970e5c0e93229"},
{file = "numpy-1.26.0-cp311-cp311-win_amd64.whl", hash = "sha256:eae430ecf5794cb7ae7fa3808740b015aa80747e5266153128ef055975a72b99"},
{file = "numpy-1.26.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:166b36197e9debc4e384e9c652ba60c0bacc216d0fc89e78f973a9760b503388"},
{file = "numpy-1.26.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f042f66d0b4ae6d48e70e28d487376204d3cbf43b84c03bac57e28dac6151581"},
{file = "numpy-1.26.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5e18e5b14a7560d8acf1c596688f4dfd19b4f2945b245a71e5af4ddb7422feb"},
{file = "numpy-1.26.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f6bad22a791226d0a5c7c27a80a20e11cfe09ad5ef9084d4d3fc4a299cca505"},
{file = "numpy-1.26.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4acc65dd65da28060e206c8f27a573455ed724e6179941edb19f97e58161bb69"},
{file = "numpy-1.26.0-cp312-cp312-win32.whl", hash = "sha256:bb0d9a1aaf5f1cb7967320e80690a1d7ff69f1d47ebc5a9bea013e3a21faec95"},
{file = "numpy-1.26.0-cp312-cp312-win_amd64.whl", hash = "sha256:ee84ca3c58fe48b8ddafdeb1db87388dce2c3c3f701bf447b05e4cfcc3679112"},
{file = "numpy-1.26.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4a873a8180479bc829313e8d9798d5234dfacfc2e8a7ac188418189bb8eafbd2"},
{file = "numpy-1.26.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:914b28d3215e0c721dc75db3ad6d62f51f630cb0c277e6b3bcb39519bed10bd8"},
{file = "numpy-1.26.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c78a22e95182fb2e7874712433eaa610478a3caf86f28c621708d35fa4fd6e7f"},
{file = "numpy-1.26.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86f737708b366c36b76e953c46ba5827d8c27b7a8c9d0f471810728e5a2fe57c"},
{file = "numpy-1.26.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b44e6a09afc12952a7d2a58ca0a2429ee0d49a4f89d83a0a11052da696440e49"},
{file = "numpy-1.26.0-cp39-cp39-win32.whl", hash = "sha256:5671338034b820c8d58c81ad1dafc0ed5a00771a82fccc71d6438df00302094b"},
{file = "numpy-1.26.0-cp39-cp39-win_amd64.whl", hash = "sha256:020cdbee66ed46b671429c7265cf00d8ac91c046901c55684954c3958525dab2"},
{file = "numpy-1.26.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0792824ce2f7ea0c82ed2e4fecc29bb86bee0567a080dacaf2e0a01fe7654369"},
{file = "numpy-1.26.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d484292eaeb3e84a51432a94f53578689ffdea3f90e10c8b203a99be5af57d8"},
{file = "numpy-1.26.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:186ba67fad3c60dbe8a3abff3b67a91351100f2661c8e2a80364ae6279720299"},
{file = "numpy-1.26.0.tar.gz", hash = "sha256:f93fc78fe8bf15afe2b8d6b6499f1c73953169fad1e9a8dd086cdff3190e7fdf"},
]
[[package]]
name = "packaging"
version = "23.2"
description = "Core utilities for Python packages"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
{file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"},
{file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"},
]
[[package]]
name = "parso"
version = "0.8.3"
description = "A Python Parser"
category = "dev"
optional = false
python-versions = ">=3.6"
files = [
{file = "parso-0.8.3-py2.py3-none-any.whl", hash = "sha256:c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75"},
{file = "parso-0.8.3.tar.gz", hash = "sha256:8c07be290bb59f03588915921e29e8a50002acaf2cdc5fa0e0114f91709fafa0"},
]
[package.extras]
qa = ["flake8 (==3.8.3)", "mypy (==0.782)"]
testing = ["docopt", "pytest (<6.0.0)"]
[[package]]
name = "pathspec"
version = "0.11.2"
description = "Utility library for gitignore style pattern matching of file paths."
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
{file = "pathspec-0.11.2-py3-none-any.whl", hash = "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20"},
{file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"},
]
[[package]]
name = "platformdirs"
version = "3.11.0"
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
{file = "platformdirs-3.11.0-py3-none-any.whl", hash = "sha256:e9d171d00af68be50e9202731309c4e658fd8bc76f55c11c7dd760d023bda68e"},
{file = "platformdirs-3.11.0.tar.gz", hash = "sha256:cf8ee52a3afdb965072dcc652433e0c7e3e40cf5ea1477cd4b3b1d2eb75495b3"},
]
[package.extras]
docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"]
test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"]
[[package]]
name = "pygls"
version = "1.1.1"
description = "A pythonic generic language server (pronounced like 'pie glass')"
category = "dev"
optional = false
python-versions = ">=3.7.9,<4"
files = [
{file = "pygls-1.1.1-py3-none-any.whl", hash = "sha256:330704551a335b443bf1cdfb0507f121608591095898d451f0007eeb1510067c"},
{file = "pygls-1.1.1.tar.gz", hash = "sha256:b1b4ddd6f800a5573f61f0ec2cd3bc7a859d171f48142b46e1de35a1357c00fe"},
]
[package.dependencies]
lsprotocol = "2023.0.0b1"
typeguard = ">=3.0.0,<4.0.0"
[package.extras]
ws = ["websockets (>=11.0.3,<12.0.0)"]
[[package]]
name = "ruff"
version = "0.0.292"
description = "An extremely fast Python linter, written in Rust."
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
{file = "ruff-0.0.292-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:02f29db018c9d474270c704e6c6b13b18ed0ecac82761e4fcf0faa3728430c96"},
{file = "ruff-0.0.292-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:69654e564342f507edfa09ee6897883ca76e331d4bbc3676d8a8403838e9fade"},
{file = "ruff-0.0.292-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c3c91859a9b845c33778f11902e7b26440d64b9d5110edd4e4fa1726c41e0a4"},
{file = "ruff-0.0.292-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f4476f1243af2d8c29da5f235c13dca52177117935e1f9393f9d90f9833f69e4"},
{file = "ruff-0.0.292-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:be8eb50eaf8648070b8e58ece8e69c9322d34afe367eec4210fdee9a555e4ca7"},
{file = "ruff-0.0.292-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:9889bac18a0c07018aac75ef6c1e6511d8411724d67cb879103b01758e110a81"},
{file = "ruff-0.0.292-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6bdfabd4334684a4418b99b3118793f2c13bb67bf1540a769d7816410402a205"},
{file = "ruff-0.0.292-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aa7c77c53bfcd75dbcd4d1f42d6cabf2485d2e1ee0678da850f08e1ab13081a8"},
{file = "ruff-0.0.292-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e087b24d0d849c5c81516ec740bf4fd48bf363cfb104545464e0fca749b6af9"},
{file = "ruff-0.0.292-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:f160b5ec26be32362d0774964e218f3fcf0a7da299f7e220ef45ae9e3e67101a"},
{file = "ruff-0.0.292-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:ac153eee6dd4444501c4bb92bff866491d4bfb01ce26dd2fff7ca472c8df9ad0"},
{file = "ruff-0.0.292-py3-none-musllinux_1_2_i686.whl", hash = "sha256:87616771e72820800b8faea82edd858324b29bb99a920d6aa3d3949dd3f88fb0"},
{file = "ruff-0.0.292-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:b76deb3bdbea2ef97db286cf953488745dd6424c122d275f05836c53f62d4016"},
{file = "ruff-0.0.292-py3-none-win32.whl", hash = "sha256:e854b05408f7a8033a027e4b1c7f9889563dd2aca545d13d06711e5c39c3d003"},
{file = "ruff-0.0.292-py3-none-win_amd64.whl", hash = "sha256:f27282bedfd04d4c3492e5c3398360c9d86a295be00eccc63914438b4ac8a83c"},
{file = "ruff-0.0.292-py3-none-win_arm64.whl", hash = "sha256:7f67a69c8f12fbc8daf6ae6d36705037bde315abf8b82b6e1f4c9e74eb750f68"},
{file = "ruff-0.0.292.tar.gz", hash = "sha256:1093449e37dd1e9b813798f6ad70932b57cf614e5c2b5c51005bf67d55db33ac"},
]
[[package]]
name = "typeguard"
version = "3.0.2"
description = "Run-time type checker for Python"
category = "dev"
optional = false
python-versions = ">=3.7.4"
files = [
{file = "typeguard-3.0.2-py3-none-any.whl", hash = "sha256:bbe993854385284ab42fd5bd3bee6f6556577ce8b50696d6cb956d704f286c8e"},
{file = "typeguard-3.0.2.tar.gz", hash = "sha256:fee5297fdb28f8e9efcb8142b5ee219e02375509cd77ea9d270b5af826358d5a"},
]
[package.extras]
doc = ["packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"]
test = ["mypy (>=0.991)", "pytest (>=7)"]
[[package]]
name = "typing-extensions"
version = "4.8.0"
description = "Backported and Experimental Type Hints for Python 3.8+"
category = "dev"
optional = false
python-versions = ">=3.8"
files = [
{file = "typing_extensions-4.8.0-py3-none-any.whl", hash = "sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0"},
{file = "typing_extensions-4.8.0.tar.gz", hash = "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef"},
]
[metadata]
lock-version = "2.0"
python-versions = ">=3.11,<3.13"
content-hash = "3180680d07071b1bed28aa242a0feb41baa73446b6edfefab15e2252da5dfdbf"

View File

@ -1,25 +0,0 @@
[tool.poetry]
name = "parser"
version = "0.1.0"
description = ""
authors = ["dm1sh <me@dmitriy.icu>"]
readme = "README.md"
[tool.poetry.dependencies]
python = ">=3.11,<3.13"
numpy = "^1.26.0"
[tool.poetry.group.dev.dependencies]
black = "^23.9.1"
mypy = "^1.5.1"
ruff = "^0.0.292"
jedi-language-server = "^0.41.1"
isort = "^5.12.0"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
[tool.isort]
profile = "black"

View File

@ -1,14 +0,0 @@
from parser import Parser
def test_Parser():
parser = Parser("(-b + sqrt(b^2-4a c))/(2a)")
assert parser.variables_names == {"c", "a", "b"}
assert parser.evaluate({"a": 1, "b": -3, "c": 2}) == 1.0
assert all(
parser.evaluate({"a": [1, 1, 1], "b": [-5, -6, -9], "c": [6, 9, 20]})
== [2.0, 3.0, 4.0]
)