You're Invited:Meet the Socket Team at RSAC and BSidesSF 2026, March 23–26.RSVP
Socket
Book a DemoSign in
Socket

basilisp

Package Overview
Dependencies
Maintainers
1
Versions
40
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

basilisp - pypi Package Compare versions

Comparing version
0.4.0
to
0.5.0.dev2
+211
src/basilisp/lang/numbers.py
import decimal
import fractions
import functools
import math
from fractions import Fraction
from typing import Callable, TypeVar
from basilisp.lang.typing import LispNumber
T_num = TypeVar("T_num", bound=LispNumber)
def _normalize_fraction_result(
f: Callable[[T_num, LispNumber], LispNumber],
) -> Callable[[T_num, LispNumber], LispNumber]:
"""
Decorator for arithmetic operations to simplify `fractions.Fraction` values with
a denominator of 1 to an integer.
"""
@functools.wraps(f)
def _normalize(x: T_num, y: LispNumber) -> LispNumber:
result = f(x, y)
# fractions.Fraction.is_integer() wasn't added until 3.12
return (
result.numerator
if isinstance(result, fractions.Fraction) and result.denominator == 1
else result
)
return _normalize
def _to_decimal(x: LispNumber) -> decimal.Decimal:
"""Coerce the input Lisp number to a `decimal.Decimal`.
`fractions.Fraction` types are not accepted as direct inputs, so this is a utility
to simplify that coercion.."""
if isinstance(x, Fraction):
numerator, denominator = x.as_integer_ratio()
return decimal.Decimal(numerator) / decimal.Decimal(denominator)
return decimal.Decimal(x)
# All the arithmetic helpers below downcast `decimal.Decimal` values down to floats
# in any binary arithmetic operation which involves one `float` and one `decimal.Decimal`.
# This perhaps peculiar behavior, but it is what Clojure does. I suspect that is due
# to the potential loss of precision with any calculation between these two types, so
# Clojure errs on the side of returning the less precise type to indicate the potential
# lossiness of the calculation.
@functools.singledispatch
@_normalize_fraction_result
def add(x: LispNumber, y: LispNumber) -> LispNumber:
"""Add two numbers together and return the result."""
return x + y # type: ignore[operator]
@add.register(float)
@_normalize_fraction_result
def _add_float(x: float, y: LispNumber) -> LispNumber:
if isinstance(y, decimal.Decimal):
return float(decimal.Decimal(x) + y)
return x + y
@add.register(decimal.Decimal)
@_normalize_fraction_result
def _add_decimal(x: decimal.Decimal, y: LispNumber) -> LispNumber:
v = x + _to_decimal(y)
return float(v) if isinstance(y, float) else v
@add.register(Fraction)
@_normalize_fraction_result
def _add_fraction(x: Fraction, y: LispNumber) -> LispNumber:
if isinstance(y, decimal.Decimal):
return _to_decimal(x) + y
return x + y
@functools.singledispatch
@_normalize_fraction_result
def subtract(x: LispNumber, y: LispNumber) -> LispNumber:
"""Subtract `y` from `x` and return the result."""
return x - y # type: ignore[operator]
@subtract.register(float)
@_normalize_fraction_result
def _subtract_float(x: float, y: LispNumber) -> LispNumber:
if isinstance(y, decimal.Decimal):
return float(decimal.Decimal(x) - y)
return x - y
@subtract.register(decimal.Decimal)
@_normalize_fraction_result
def _subtract_decimal(x: decimal.Decimal, y: LispNumber) -> LispNumber:
v = x - _to_decimal(y)
return float(v) if isinstance(y, float) else v
@subtract.register(Fraction)
@_normalize_fraction_result
def _subtract_fraction(x: Fraction, y: LispNumber) -> LispNumber:
if isinstance(y, decimal.Decimal):
return _to_decimal(x) - y
return x - y
@functools.singledispatch
@_normalize_fraction_result
def divide(x: LispNumber, y: LispNumber) -> LispNumber:
"""Division reducer. If both arguments are integers, return a Fraction.
Otherwise, return the true division of x and y."""
return x / y # type: ignore[operator]
@divide.register(int)
@_normalize_fraction_result
def _divide_ints(x: int, y: LispNumber) -> LispNumber:
if isinstance(y, int):
return Fraction(x, y)
return x / y
@divide.register(float)
@_normalize_fraction_result
def _divide_float(x: float, y: LispNumber) -> LispNumber:
if isinstance(y, decimal.Decimal):
return float(decimal.Decimal(x) / y)
try:
return x / y
except ZeroDivisionError:
if math.isnan(x):
return math.nan
elif x >= 0:
return math.inf
else:
return -math.inf
@divide.register(decimal.Decimal)
@_normalize_fraction_result
def _divide_decimal(x: decimal.Decimal, y: LispNumber) -> LispNumber:
v = x / _to_decimal(y)
return float(v) if isinstance(y, float) else v
@divide.register(Fraction)
@_normalize_fraction_result
def _divide_fraction(x: Fraction, y: LispNumber) -> LispNumber:
if isinstance(y, decimal.Decimal):
return _to_decimal(x) / y
return x / y
@functools.singledispatch
@_normalize_fraction_result
def multiply(x: LispNumber, y: LispNumber) -> LispNumber:
"""Multiply two numbers together and return the result."""
return x * y # type: ignore[operator]
@multiply.register(float)
@_normalize_fraction_result
def _multiply_float(x: float, y: LispNumber) -> LispNumber:
if isinstance(y, decimal.Decimal):
return float(decimal.Decimal(x) * y)
return x * y
@multiply.register(decimal.Decimal)
@_normalize_fraction_result
def _multiply_decimal(x: decimal.Decimal, y: LispNumber) -> LispNumber:
v = x * _to_decimal(y)
return float(v) if isinstance(y, float) else v
@multiply.register(Fraction)
@_normalize_fraction_result
def _multiply_fraction(x: Fraction, y: LispNumber) -> LispNumber:
if isinstance(y, decimal.Decimal):
return _to_decimal(x) * y
return x * y
@functools.singledispatch
def trunc(x: LispNumber) -> LispNumber:
"""Truncate any fractional part of the input value, preserving the input type.
Truncation is effectively rounding towards 0."""
return math.trunc(x)
@trunc.register(float)
def _trunc_float(x: float) -> LispNumber:
return float(math.trunc(x))
@trunc.register(decimal.Decimal)
def _trunc_decimal(x: decimal.Decimal) -> LispNumber:
return decimal.Decimal(math.trunc(x))
@trunc.register(Fraction)
def _trunc_fraction(x: Fraction) -> LispNumber:
v = fractions.Fraction(math.trunc(x))
return v.numerator if v.denominator == 1 else v
+9
-12

@@ -1,16 +0,14 @@

Metadata-Version: 2.3
Metadata-Version: 2.4
Name: basilisp
Version: 0.4.0
Version: 0.5.0.dev2
Summary: A Clojure-like lisp written for Python
License: Eclipse Public License 1.0 (EPL-1.0)
License-Expression: EPL-1.0
License-File: LICENSE
Author: Christopher Rink
Author-email: chrisrink10@gmail.com
Requires-Python: >=3.9,<4.0
Author-email: chris@crink.dev
Requires-Python: >=3.10
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Eclipse Public License 1.0 (EPL-1.0)
Classifier: License :: Other/Proprietary License
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10

@@ -20,2 +18,3 @@ Classifier: Programming Language :: Python :: 3.11

Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Programming Language :: Python :: Implementation :: CPython

@@ -33,4 +32,2 @@ Classifier: Programming Language :: Python :: Implementation :: PyPy

Requires-Dist: typing-extensions (>=4.7.0,<5.0.0)
Project-URL: Documentation, https://basilisp.readthedocs.io/
Project-URL: Repository, https://github.com/basilisp-lang/basilisp
Description-Content-Type: text/markdown

@@ -40,5 +37,5 @@

A Clojure-compatible(-ish) Lisp dialect targeting Python 3.9+.
A Clojure-compatible(-ish) Lisp dialect targeting Python 3.10+.
[![PyPI](https://img.shields.io/pypi/v/basilisp.svg?style=flat-square)](https://pypi.org/project/basilisp/) [![python](https://img.shields.io/pypi/pyversions/basilisp.svg?style=flat-square)](https://pypi.org/project/basilisp/) [![pyimpl](https://img.shields.io/pypi/implementation/basilisp.svg?style=flat-square)](https://pypi.org/project/basilisp/) [![readthedocs](https://img.shields.io/readthedocs/basilisp.svg?style=flat-square)](https://basilisp.readthedocs.io/) [![Run tests](https://github.com/basilisp-lang/basilisp/actions/workflows/run-tests.yml/badge.svg?branch=main)](https://github.com/basilisp-lang/basilisp/actions/workflows/run-tests.yml) [![Coveralls github](https://img.shields.io/coveralls/github/basilisp-lang/basilisp.svg?style=flat-square)](https://coveralls.io/github/basilisp-lang/basilisp) [![license](https://img.shields.io/github/license/basilisp-lang/basilisp.svg?style=flat-square)](https://github.com/basilisp-lang/basilisp/blob/master/LICENSE)
[![PyPI](https://img.shields.io/pypi/v/basilisp.svg?style=flat-square)](https://pypi.org/project/basilisp/) [![python](https://img.shields.io/pypi/pyversions/basilisp.svg?style=flat-square)](https://pypi.org/project/basilisp/) [![pyimpl](https://img.shields.io/pypi/implementation/basilisp.svg?style=flat-square)](https://pypi.org/project/basilisp/) [![readthedocs](https://img.shields.io/readthedocs/basilisp.svg?style=flat-square)](https://basilisp.readthedocs.io/) [![Run tests](https://github.com/basilisp-lang/basilisp/actions/workflows/run-tests.yml/badge.svg?branch=main)](https://github.com/basilisp-lang/basilisp/actions/workflows/run-tests.yml) [![Coveralls github](https://img.shields.io/coveralls/github/basilisp-lang/basilisp.svg?style=flat-square)](https://coveralls.io/github/basilisp-lang/basilisp) [![license](https://img.shields.io/github/license/basilisp-lang/basilisp.svg?style=flat-square)](https://github.com/basilisp-lang/basilisp/blob/master/LICENSE) [![Slack](https://img.shields.io/badge/Slack-Clojurians-green?style=flat-square)](https://clojurians.slack.com/archives/C071RFV2Z1D)

@@ -45,0 +42,0 @@ ## Getting Started

@@ -1,8 +0,11 @@

[tool.poetry]
[project]
name = "basilisp"
version = "0.4.0"
version = "0.5.0.dev2"
description = "A Clojure-like lisp written for Python"
authors = ["Christopher Rink <chrisrink10@gmail.com>"]
license = "Eclipse Public License 1.0 (EPL-1.0)"
authors = [
{ name = "Christopher Rink", email = "chris@crink.dev" },
]
license = "EPL-1.0"
readme = "README.md"
requires-python = ">=3.10"
packages = [

@@ -18,6 +21,4 @@ { include = "basilisp", from = "src" },

"Intended Audience :: Developers",
"License :: OSI Approved :: Eclipse Public License 1.0 (EPL-1.0)",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",

@@ -27,2 +28,3 @@ "Programming Language :: Python :: 3.11",

"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Programming Language :: Python :: Implementation :: CPython",

@@ -33,44 +35,44 @@ "Programming Language :: Python :: Implementation :: PyPy",

include = ["README.md", "LICENSE"]
dependencies = [
"attrs >=22.2.0",
"immutables (>=0.20,<1.0.0)",
"prompt-toolkit (>=3.0.0,<4.0.0)",
"pyrsistent (>=0.18.0,<1.0.0)",
"typing-extensions (>=4.7.0,<5.0.0)",
]
[tool.poetry.dependencies]
python = "^3.9"
attrs = ">=22.2.0"
immutables = ">=0.20,<1.0.0"
prompt-toolkit = ">=3.0.0,<4.0.0"
pyrsistent = ">=0.18.0,<1.0.0"
typing-extensions = ">=4.7.0,<5.0.0"
pytest = { version = ">=7.0.0,<9.0.0", optional = true }
pygments = { version = ">=2.9.0,<3.0.0", optional = true }
[tool.poetry.group.dev.dependencies]
black = ">=24.0.0"
docutils = "*"
isort = "*"
pygments = "*"
pytest = ">=7.0.0,<9.0.0"
pytest-pycharm = "*"
[dependency-groups]
dev = [
"black >=24.0.0",
"docutils",
"isort",
"pygments",
"pytest (>=7.0.0,<9.0.0)",
"pytest-pycharm",
"tox",
]
# Ensure the Sphinx version remains synchronized with docs/requirements.txt
# to maintain consistent output during both development and publishing on
# Read The Docs.
sphinx = "^7.1.0"
sphinx-autobuild = { version = "^2024.04.16", python = ">=3.9" }
sphinx-copybutton = "^0.5.2"
sphinxext-opengraph = "^v0.9.1"
furo = "^2023.08.19"
tox = "*"
docs = [
"furo >=2023.08.19",
"sphinx (>=7.1.0,<8.0.0)",
"sphinx-autobuild >=2024.04.16",
"sphinx-copybutton (>=0.5.2,<6.0.0)",
"sphinxext-opengraph (>=v0.9.1,<1.0.0)",
]
[tool.poetry.extras]
pygments = ["pygments"]
pytest = ["pytest"]
[project.optional-dependencies]
pygments = ["pygments (>=2.9.0,<3.0.0)"]
pytest = ["pytest (>=7.0.0,<9.0.0)"]
[tool.poetry.scripts]
[project.scripts]
basilisp = "basilisp.cli:invoke_cli"
basilisp-run = "basilisp.cli:run_script"
[tool.poetry.plugins.pytest11]
[project.entry-points.pytest11]
basilisp_test_runner = "basilisp.contrib.pytest.testrunner"
[build-system]
requires = ["poetry-core>=1.0.0"]
requires = ["poetry-core>=2.0.0"]
build-backend = "poetry.core.masonry.api"

@@ -112,2 +114,3 @@

]
patch = ["subprocess"]

@@ -243,3 +246,2 @@ [tool.coverage.paths]

module = [
"astor.*",
"prompt_toolkit.*",

@@ -246,0 +248,0 @@ "pygments.*",

# 🐍 basilisp 🐍
A Clojure-compatible(-ish) Lisp dialect targeting Python 3.9+.
A Clojure-compatible(-ish) Lisp dialect targeting Python 3.10+.
[![PyPI](https://img.shields.io/pypi/v/basilisp.svg?style=flat-square)](https://pypi.org/project/basilisp/) [![python](https://img.shields.io/pypi/pyversions/basilisp.svg?style=flat-square)](https://pypi.org/project/basilisp/) [![pyimpl](https://img.shields.io/pypi/implementation/basilisp.svg?style=flat-square)](https://pypi.org/project/basilisp/) [![readthedocs](https://img.shields.io/readthedocs/basilisp.svg?style=flat-square)](https://basilisp.readthedocs.io/) [![Run tests](https://github.com/basilisp-lang/basilisp/actions/workflows/run-tests.yml/badge.svg?branch=main)](https://github.com/basilisp-lang/basilisp/actions/workflows/run-tests.yml) [![Coveralls github](https://img.shields.io/coveralls/github/basilisp-lang/basilisp.svg?style=flat-square)](https://coveralls.io/github/basilisp-lang/basilisp) [![license](https://img.shields.io/github/license/basilisp-lang/basilisp.svg?style=flat-square)](https://github.com/basilisp-lang/basilisp/blob/master/LICENSE)
[![PyPI](https://img.shields.io/pypi/v/basilisp.svg?style=flat-square)](https://pypi.org/project/basilisp/) [![python](https://img.shields.io/pypi/pyversions/basilisp.svg?style=flat-square)](https://pypi.org/project/basilisp/) [![pyimpl](https://img.shields.io/pypi/implementation/basilisp.svg?style=flat-square)](https://pypi.org/project/basilisp/) [![readthedocs](https://img.shields.io/readthedocs/basilisp.svg?style=flat-square)](https://basilisp.readthedocs.io/) [![Run tests](https://github.com/basilisp-lang/basilisp/actions/workflows/run-tests.yml/badge.svg?branch=main)](https://github.com/basilisp-lang/basilisp/actions/workflows/run-tests.yml) [![Coveralls github](https://img.shields.io/coveralls/github/basilisp-lang/basilisp.svg?style=flat-square)](https://coveralls.io/github/basilisp-lang/basilisp) [![license](https://img.shields.io/github/license/basilisp-lang/basilisp.svg?style=flat-square)](https://github.com/basilisp-lang/basilisp/blob/master/LICENSE) [![Slack](https://img.shields.io/badge/Slack-Clojurians-green?style=flat-square)](https://clojurians.slack.com/archives/C071RFV2Z1D)

@@ -7,0 +7,0 @@ ## Getting Started

@@ -9,5 +9,5 @@ import argparse

import types
from collections.abc import Sequence
from collections.abc import Callable, Sequence
from pathlib import Path
from typing import Any, Callable, Optional, Union
from typing import Any, Union

@@ -101,3 +101,3 @@ from basilisp import main as basilisp

def _to_bool(v: Optional[str]) -> Optional[bool]:
def _to_bool(v: str | None) -> bool | None:
"""Coerce a string argument to a boolean value, if possible."""

@@ -394,4 +394,4 @@ if v is None:

*,
help: Optional[str] = None, # pylint: disable=redefined-builtin
description: Optional[str] = None,
help: str | None = None, # pylint: disable=redefined-builtin
description: str | None = None,
handler: Handler,

@@ -751,2 +751,12 @@ allows_extra: bool = False,

else:
# `basilisp` declares the testrunner as a pytest plugin, so
# pytest tries to import it for assertion rewriting. Since
# it's already imported, pytest emits a warning. As rewriting
# isn't needed, we ignore it. (Requires pytest >=8.4.0 to take
# effect)
extra = [
"-W",
"ignore:Module already imported so cannot be rewritten; basilisp:pytest.PytestAssertRewriteWarning",
] + extra
sys.exit(pytest.main(args=list(extra)))

@@ -758,4 +768,3 @@

help="run tests in a Basilisp project",
description=textwrap.dedent(
"""Run tests in a Basilisp project.
description=textwrap.dedent("""Run tests in a Basilisp project.

@@ -778,4 +787,3 @@ Any options not recognized by Basilisp and all positional arguments will

Returns the PyTest exit code as the exit code."""
),
Returns the PyTest exit code as the exit code."""),
handler=test,

@@ -819,3 +827,3 @@ allows_extra=True,

def invoke_cli(args: Optional[Sequence[str]] = None) -> None:
def invoke_cli(args: Sequence[str] | None = None) -> None:
"""Entrypoint to run the Basilisp CLI."""

@@ -822,0 +830,0 @@ parser = argparse.ArgumentParser(

import importlib.util
import inspect
import os
import re
import sys
import traceback
from collections.abc import Iterable, Iterator
from collections.abc import Callable, Iterable, Iterator
from functools import cache
from pathlib import Path
from types import GeneratorType
from typing import Callable, Optional

@@ -61,7 +62,33 @@ import pytest

@cache
def _get_test_file_path() -> list[str] | None:
"""Return a list of string paths which should be searched for test files.
If `None`, use PyTest's normal collection heuristics."""
_test_path = os.getenv("BASILISP_TEST_PATH", "").strip()
return (
[str(Path(p).absolute()) for p in _test_path.split(os.pathsep)]
if _test_path
else None
)
@cache
def _get_test_file_pattern() -> re.Pattern:
"""Return a regular expression pattern which can be used to match test files."""
_test_file_pattern = os.getenv(
"BASILISP_TEST_FILE_PATTERN", r"(test_[^.]*|.*_test)\.(lpy|cljc)"
)
return re.compile(_test_file_pattern)
def pytest_collect_file(file_path: Path, parent):
"""Primary PyTest hook to identify Basilisp test files."""
if file_path.suffix == ".lpy":
if file_path.name.startswith("test_") or file_path.stem.endswith("_test"):
return BasilispFile.from_parent(parent, path=file_path)
test_paths = _get_test_file_path()
if test_paths and not any(str(file_path).startswith(p) for p in test_paths):
return None
if _get_test_file_pattern().fullmatch(file_path.name):
return BasilispFile.from_parent(parent, path=file_path)
return None

@@ -98,3 +125,3 @@

FixtureTeardown = Iterator[None]
FixtureFunction = Callable[[], Optional[FixtureTeardown]]
FixtureFunction = Callable[[], FixtureTeardown | None]

@@ -113,3 +140,3 @@

@staticmethod
def _run_fixture(fixture: FixtureFunction) -> Optional[Iterator[None]]:
def _run_fixture(fixture: FixtureFunction) -> Iterator[None] | None:
"""Run a fixture function. If the fixture is a generator function, return the

@@ -177,3 +204,7 @@ generator/coroutine. Otherwise, simply return the value from the function, if

for file in files:
if file in {"__init__.lpy", "__init__.py"} or file.endswith(".lpy"):
if (
file in {"__init__.lpy", "__init__.py"}
or file.endswith(".lpy")
or file.endswith(".cljc")
):
return True

@@ -206,3 +237,3 @@ return False

super().__init__(**kwargs)
self._fixture_manager: Optional[FixtureManager] = None
self._fixture_manager: FixtureManager | None = None

@@ -256,3 +287,3 @@ @staticmethod

exc: Optional[ModuleNotFoundError] = None
exc: ModuleNotFoundError | None = None
for modname in modnames:

@@ -369,3 +400,3 @@ try:

results: lmap.PersistentMap = self._run_test()
failures: Optional[vec.PersistentVector] = results.val_at(_FAILURES_KW)
failures: vec.PersistentVector | None = results.val_at(_FAILURES_KW)
if runtime.to_seq(failures):

@@ -401,3 +432,3 @@ raise TestFailuresInfo("Test failures", lmap.map(results))

def _error_msg(self, exc: Exception, line: Optional[int] = None) -> str:
def _error_msg(self, exc: Exception, line: int | None = None) -> str:
line_msg = Maybe(line).map(lambda l: f":{l}").or_else_get("")

@@ -404,0 +435,0 @@ messages = [f"ERROR in ({self.name}) ({self._filename}{line_msg})", "\n\n"]

@@ -6,3 +6,3 @@ import importlib

import types
from typing import Any, Optional, cast
from typing import Any, cast

@@ -55,3 +55,3 @@ from sphinx.ext.autodoc import (

def _get_doc(reference: IReference) -> Optional[list[list[str]]]:
def _get_doc(reference: IReference) -> list[list[str]] | None:
"""Return the docstring of an IReference type (e.g. Namespace or Var)."""

@@ -84,3 +84,3 @@ docstring = reference.meta and reference.meta.val_at(_DOC_KW)

object: Optional[runtime.Namespace]
object: runtime.Namespace | None

@@ -128,3 +128,3 @@ @classmethod

def get_doc(self) -> Optional[list[list[str]]]:
def get_doc(self) -> list[list[str]] | None:
assert self.object is not None

@@ -162,3 +162,3 @@ return _get_doc(self.object)

# Ignore undocumented members unless undoc_members is set
docstring: Optional[str] = val.meta.val_at(_DOC_KW)
docstring: str | None = val.meta.val_at(_DOC_KW)
if docstring is None and not self.options.undoc_members:

@@ -223,3 +223,3 @@ continue

object: Optional[runtime.Var]
object: runtime.Var | None

@@ -301,3 +301,3 @@ @classmethod

def get_doc(self) -> Optional[list[list[str]]]:
def get_doc(self) -> list[list[str]] | None:
assert self.object is not None

@@ -304,0 +304,0 @@ return _get_doc(self.object)

import logging
from collections import defaultdict
from collections.abc import Iterable
from typing import Any, NamedTuple, Optional, Union, cast
from typing import Any, NamedTuple, cast

@@ -319,3 +319,3 @@ from docutils import nodes

def generate( # pylint: disable=too-many-locals
self, docnames: Optional[Iterable[str]] = None
self, docnames: Iterable[str] | None = None
) -> tuple[list[tuple[str, list[IndexEntry]]], bool]:

@@ -552,6 +552,6 @@ content: dict[str, list[IndexEntry]] = defaultdict(list)

contnode: Element,
) -> Optional[Element]:
) -> Element | None:
nsname = node.get("lpy:namespace")
maybe_obj: Union[FormEntry, NamespaceEntry, VarEntry, None]
maybe_obj: FormEntry | NamespaceEntry | VarEntry | None
reftype = node.get("reftype")

@@ -558,0 +558,0 @@ if reftype == "ns":

@@ -12,3 +12,3 @@ import importlib.util

from importlib.machinery import ModuleSpec
from typing import Any, Optional, cast
from typing import Any, cast

@@ -148,5 +148,5 @@ from typing_extensions import TypedDict

fullname: str,
path: Optional[Sequence[str]],
target: Optional[types.ModuleType] = None,
) -> Optional[ModuleSpec]:
path: Sequence[str] | None,
target: types.ModuleType | None = None,
) -> ModuleSpec | None:
"""Find the ModuleSpec for the specified Basilisp module.

@@ -239,3 +239,3 @@

def get_code(self, fullname: str) -> Optional[types.CodeType]:
def get_code(self, fullname: str) -> types.CodeType | None:
"""Return code to load a Basilisp module.

@@ -291,4 +291,15 @@

def create_module(self, spec: ModuleSpec) -> BasilispModule:
logger.debug(f"Creating Basilisp module '{spec.name}'")
mod = BasilispModule(spec.name)
# If a namespace was created dynamically before being require'd, then
# a module will already exist for the namespace. References may already
# have been made to the contents of that module. Reusing it rather than
# starting new allows both dynamically created namespaces and namespaces
# defined in files to coexist.
if (ns := runtime.Namespace.get(sym.symbol(demunge(spec.name)))) is not None:
logger.debug(f"Reusing existing module for namespace '{ns}'")
mod = ns.module
assert isinstance(mod, BasilispModule)
else:
logger.debug(f"Creating Basilisp module '{spec.name}'")
mod = BasilispModule(spec.name)
mod.__file__ = spec.loader_state["filename"]

@@ -295,0 +306,0 @@ mod.__loader__ = spec.loader

import threading
from typing import Callable, Generic, Optional, TypeVar
from collections.abc import Callable
from typing import Concatenate, Generic, TypeVar
from typing_extensions import Concatenate, ParamSpec
from typing_extensions import ParamSpec

@@ -20,6 +21,6 @@ from basilisp.lang import map as lmap

state: T,
meta: Optional[IPersistentMap] = None,
validator: Optional[RefValidator] = None,
meta: IPersistentMap | None = None,
validator: RefValidator | None = None,
) -> None:
self._meta: Optional[IPersistentMap] = meta
self._meta: IPersistentMap | None = meta
self._state = state

@@ -26,0 +27,0 @@ self._lock = threading.RLock()

@@ -6,5 +6,5 @@ import ast

from ast import unparse
from collections.abc import Iterable
from collections.abc import Callable, Iterable
from pathlib import Path
from typing import Any, Callable, Optional
from typing import Any

@@ -64,3 +64,3 @@ from basilisp.lang import list as llist

def __init__(self, filename: str, opts: Optional[CompilerOpts] = None):
def __init__(self, filename: str, opts: CompilerOpts | None = None):
self._filename = filename

@@ -89,11 +89,11 @@ self._actx = AnalyzerContext(filename=filename, opts=opts)

def compiler_opts( # pylint: disable=too-many-arguments
generate_auto_inlines: Optional[bool] = None,
inline_functions: Optional[bool] = None,
warn_on_arity_mismatch: Optional[bool] = None,
warn_on_shadowed_name: Optional[bool] = None,
warn_on_shadowed_var: Optional[bool] = None,
warn_on_unused_names: Optional[bool] = None,
warn_on_non_dynamic_set: Optional[bool] = None,
use_var_indirection: Optional[bool] = None,
warn_on_var_indirection: Optional[bool] = None,
generate_auto_inlines: bool | None = None,
inline_functions: bool | None = None,
warn_on_arity_mismatch: bool | None = None,
warn_on_shadowed_name: bool | None = None,
warn_on_shadowed_var: bool | None = None,
warn_on_unused_names: bool | None = None,
warn_on_non_dynamic_set: bool | None = None,
use_var_indirection: bool | None = None,
warn_on_var_indirection: bool | None = None,
) -> CompilerOpts:

@@ -154,3 +154,3 @@ """Return a map of compiler options with defaults applied."""

wrapped_fn_name: str = _DEFAULT_FN,
collect_bytecode: Optional[BytecodeCollector] = None,
collect_bytecode: BytecodeCollector | None = None,
) -> Any:

@@ -211,3 +211,3 @@ """Compile and execute the given form. This function will be most useful

source_filename: str,
collect_bytecode: Optional[BytecodeCollector] = None,
collect_bytecode: BytecodeCollector | None = None,
) -> None:

@@ -240,3 +240,3 @@ """Incrementally compile a stream of AST nodes in module mod.

module: BasilispModule,
collect_bytecode: Optional[BytecodeCollector] = None,
collect_bytecode: BytecodeCollector | None = None,
) -> None:

@@ -258,3 +258,3 @@ """Bootstrap a new module with imports and other boilerplate."""

module: BasilispModule,
collect_bytecode: Optional[BytecodeCollector] = None,
collect_bytecode: BytecodeCollector | None = None,
) -> None:

@@ -308,3 +308,3 @@ """Compile an entire Basilisp module into Python bytecode which can be

ns: runtime.Namespace,
collect_bytecode: Optional[BytecodeCollector] = None,
collect_bytecode: BytecodeCollector | None = None,
) -> Any:

@@ -322,3 +322,3 @@ """Call :lpy:fn:`basilisp.core/load` with the given ``path``, returning the

ns: runtime.Namespace,
collect_bytecode: Optional[BytecodeCollector] = None,
collect_bytecode: BytecodeCollector | None = None,
) -> Any:

@@ -325,0 +325,0 @@ """Call :lpy:fn:`basilisp.core/load-file` with the given ``path``, returning the

@@ -5,3 +5,3 @@ import ast

from types import TracebackType
from typing import Any, Optional, Union
from typing import Any

@@ -46,6 +46,6 @@ import attr

class _loc:
line: Optional[int] = None
col: Optional[int] = None
end_line: Optional[int] = None
end_col: Optional[int] = None
line: int | None = None
col: int | None = None
end_line: int | None = None
end_col: int | None = None

@@ -66,5 +66,5 @@ def __bool__(self):

filename: str
form: Union[LispForm, None, ISeq] = None
lisp_ast: Optional[Node] = None
py_ast: Optional[Union[ast.expr, ast.stmt]] = None
form: LispForm | None | ISeq = None
lisp_ast: Node | None = None
py_ast: ast.expr | ast.stmt | None = None

@@ -118,5 +118,5 @@ @property

e: CompilerException,
tp: Optional[type[Exception]] = None,
tb: Optional[TracebackType] = None,
disable_color: Optional[bool] = None,
tp: type[Exception] | None = None,
tb: TracebackType | None = None,
disable_color: bool | None = None,
) -> list[str]:

@@ -127,5 +127,5 @@ """Format a compiler exception as a list of newline-terminated strings.

code."""
context_exc: Optional[BaseException] = e.__cause__
context_exc: BaseException | None = e.__cause__
lines = [os.linesep]
lines: list[str] = [os.linesep]
if context_exc is not None:

@@ -132,0 +132,0 @@ lines.append(f" exception: {type(context_exc)} from {type(e)}{os.linesep}")

from abc import ABC, abstractmethod
from collections.abc import Iterable, MutableMapping, Sequence
from collections.abc import Callable, Iterable, MutableMapping, Sequence
from enum import Enum
from typing import Any, Callable, Generic, Optional, TypeVar, Union
from typing import Any, Generic, Optional, TypeVar, Union

@@ -189,3 +189,3 @@ import attr

def fix_missing_locations(
self, form_loc: Optional[tuple[int, int, int, int]] = None
self, form_loc: tuple[int, int, int, int] | None = None
) -> "Node[T]":

@@ -211,3 +211,3 @@ """Return a transformed copy of this node with location in this node's

new_attrs: MutableMapping[str, Union[NodeEnv, Node, Iterable[Node]]] = {
new_attrs: MutableMapping[str, NodeEnv | Node | Iterable[Node]] = {
"env": attr.evolve(

@@ -335,8 +335,8 @@ self.env, line=loc[0], col=loc[1], end_line=loc[2], end_col=loc[3]

file: str
line: Optional[int] = None
col: Optional[int] = None
end_line: Optional[int] = None
end_col: Optional[int] = None
pos: Optional[NodeSyntacticPosition] = None
func_ctx: Optional[FunctionContext] = None
line: int | None = None
col: int | None = None
end_line: int | None = None
end_col: int | None = None
pos: NodeSyntacticPosition | None = None
func_ctx: FunctionContext | None = None

@@ -361,7 +361,7 @@

env: NodeEnv = attr.field(hash=False)
tag: Optional[Node] = None
arg_id: Optional[int] = None
tag: Node | None = None
arg_id: int | None = None
is_variadic: bool = False
is_assignable: bool = False
init: Optional[Node] = None
init: Node | None = None
meta: NodeMeta = None

@@ -406,6 +406,6 @@ children: Sequence[kw.Keyword] = vec.EMPTY

var: Var
init: Optional[Node]
doc: Optional[str]
init: Node | None
doc: str | None
env: NodeEnv = attr.field(hash=False)
tag: Optional[Node] = None
tag: Node | None = None
meta: NodeMeta = None

@@ -463,3 +463,3 @@ children: Sequence[kw.Keyword] = vec.EMPTY

is_variadic: bool = False
kwarg_support: Optional[KeywordArgSupport] = None
kwarg_support: KeywordArgSupport | None = None
children: Sequence[kw.Keyword] = vec.v(CLASS_LOCAL, PARAMS, BODY)

@@ -493,3 +493,3 @@ op: NodeOp = NodeOp.DEFTYPE_CLASSMETHOD

is_variadic: bool = False
kwarg_support: Optional[KeywordArgSupport] = None
kwarg_support: KeywordArgSupport | None = None
children: Sequence[kw.Keyword] = vec.v(THIS_LOCAL, PARAMS, BODY)

@@ -522,3 +522,3 @@ op: NodeOp = NodeOp.DEFTYPE_METHOD_ARITY

is_variadic: bool = False
kwarg_support: Optional[KeywordArgSupport] = None
kwarg_support: KeywordArgSupport | None = None
children: Sequence[kw.Keyword] = vec.v(PARAMS, BODY)

@@ -553,6 +553,6 @@ op: NodeOp = NodeOp.DEFTYPE_STATICMETHOD

env: NodeEnv = attr.field(hash=False)
local: Optional[Binding] = None
local: Binding | None = None
is_variadic: bool = False
is_async: bool = False
kwarg_support: Optional[KeywordArgSupport] = None
kwarg_support: KeywordArgSupport | None = None
inline_fn: Optional["Fn"] = None

@@ -573,3 +573,3 @@ children: Sequence[kw.Keyword] = vec.v(ARITIES)

env: NodeEnv = attr.field(hash=False)
tag: Optional[Node] = None
tag: Node | None = None
is_variadic: bool = False

@@ -598,3 +598,3 @@ children: Sequence[kw.Keyword] = vec.v(PARAMS, BODY)

class HostField(Node[Union[SpecialForm, sym.Symbol]], Assignable):
form: Union[SpecialForm, sym.Symbol]
form: SpecialForm | sym.Symbol
field: str

@@ -627,4 +627,2 @@ target: Node

aliases: Iterable["ImportAlias"]
refers: Iterable[str]
refer_all: bool
env: NodeEnv = attr.field(hash=False)

@@ -639,5 +637,7 @@ children: Sequence[kw.Keyword] = vec.EMPTY

class ImportAlias(Node[Union[sym.Symbol, vec.PersistentVector]]):
form: Union[sym.Symbol, vec.PersistentVector]
form: sym.Symbol | vec.PersistentVector
name: str
alias: Optional[str]
alias: str | None
refers: Iterable[str]
refer_all: bool
env: NodeEnv = attr.field(hash=False)

@@ -694,3 +694,3 @@ children: Sequence[kw.Keyword] = vec.EMPTY

is_assignable: bool = False
arg_id: Optional[int] = None
arg_id: int | None = None
is_variadic: bool = False

@@ -778,3 +778,3 @@ children: Sequence[kw.Keyword] = vec.EMPTY

class PySet(Node[Union[frozenset, set]]):
form: Union[frozenset, set]
form: frozenset | set
items: Iterable[Node]

@@ -857,5 +857,5 @@ env: NodeEnv = attr.field(hash=False)

class RequireAlias(Node[Union[sym.Symbol, vec.PersistentVector]]):
form: Union[sym.Symbol, vec.PersistentVector]
form: sym.Symbol | vec.PersistentVector
name: str
alias: Optional[str]
alias: str | None
env: NodeEnv = attr.field(hash=False)

@@ -893,3 +893,3 @@ children: Sequence[kw.Keyword] = vec.EMPTY

form: SpecialForm
target: Union[Assignable, Node]
target: Assignable | Node
val: Node

@@ -907,3 +907,3 @@ env: NodeEnv = attr.field(hash=False)

exception: Node
cause: Optional[Node]
cause: Node | None
env: NodeEnv = attr.field(hash=False)

@@ -923,3 +923,3 @@ children: Sequence[kw.Keyword] = vec.v(EXCEPTION)

env: NodeEnv = attr.field(hash=False)
finally_: Optional[Do] = None
finally_: Do | None = None
op: NodeOp = NodeOp.TRY

@@ -932,3 +932,3 @@ top_level: bool = False

class VarRef(Node[Union[sym.Symbol, ISeq]], Assignable):
form: Union[sym.Symbol, ISeq]
form: sym.Symbol | ISeq
var: Var

@@ -962,3 +962,3 @@ env: NodeEnv = attr.field(hash=False)

form: LispForm
meta: Union[Const, Map]
meta: Const | Map
expr: T_withmeta

@@ -975,3 +975,3 @@ env: NodeEnv = attr.field(hash=False)

form: SpecialForm
expr: Optional[Node]
expr: Node | None
env: NodeEnv = attr.field(hash=False)

@@ -978,0 +978,0 @@ children: Sequence[kw.Keyword] = vec.v(EXPR)

@@ -6,3 +6,3 @@ import ast

from contextlib import contextmanager
from typing import Deque, Optional
from typing import Deque

@@ -154,3 +154,3 @@ from basilisp.lang.compiler.constants import OPERATOR_ALIAS

def visit_ExceptHandler(self, node: ast.ExceptHandler) -> Optional[ast.AST]:
def visit_ExceptHandler(self, node: ast.ExceptHandler) -> ast.AST | None:
"""Eliminate dead code from except handler bodies."""

@@ -168,3 +168,3 @@ new_node = self.generic_visit(node)

def visit_Expr(self, node: ast.Expr) -> Optional[ast.Expr]:
def visit_Expr(self, node: ast.Expr) -> ast.Expr | None:
"""Eliminate no-op constant expressions which are in the tree

@@ -176,3 +176,3 @@ as standalone statements."""

def visit_FunctionDef(self, node: ast.FunctionDef) -> Optional[ast.AST]:
def visit_FunctionDef(self, node: ast.FunctionDef) -> ast.AST | None:
"""Eliminate dead code from function bodies."""

@@ -193,3 +193,3 @@ with self._new_global_context():

def visit_Global(self, node: ast.Global) -> Optional[ast.Global]:
def visit_Global(self, node: ast.Global) -> ast.Global | None:
"""Eliminate redundant name declarations inside a Python `global` statement.

@@ -209,3 +209,3 @@

def visit_If(self, node: ast.If) -> Optional[ast.AST]:
def visit_If(self, node: ast.If) -> ast.AST | None:
"""Eliminate dead code from if/elif bodies.

@@ -241,3 +241,3 @@

def visit_While(self, node: ast.While) -> Optional[ast.AST]:
def visit_While(self, node: ast.While) -> ast.AST | None:
"""Eliminate dead code from while bodies."""

@@ -255,3 +255,3 @@ new_node = self.generic_visit(node)

def visit_Try(self, node: ast.Try) -> Optional[ast.AST]:
def visit_Try(self, node: ast.Try) -> ast.AST | None:
"""Eliminate dead code from except try bodies."""

@@ -258,0 +258,0 @@ new_node = self.generic_visit(node)

@@ -1,2 +0,3 @@

from typing import Callable, Generic, Optional, TypeVar
from collections.abc import Callable
from typing import Generic, TypeVar

@@ -14,3 +15,3 @@ import attr

f: Callable[[], T]
value: Optional[T]
value: T | None
computed: bool = False

@@ -32,3 +33,3 @@

def deref(self) -> Optional[T]:
def deref(self) -> T | None:
return self._state.swap(self.__deref).value

@@ -35,0 +36,0 @@

@@ -5,3 +5,2 @@ import functools

from types import TracebackType
from typing import Optional

@@ -30,6 +29,6 @@ import attr

def format_exception( # pylint: disable=unused-argument
e: Optional[BaseException],
tp: Optional[type[BaseException]] = None,
tb: Optional[TracebackType] = None,
disable_color: Optional[bool] = None,
e: BaseException | None,
tp: type[BaseException] | None = None,
tb: TracebackType | None = None,
disable_color: bool | None = None,
) -> list[str]:

@@ -54,5 +53,5 @@ """Format an exception into something readable, returning a list of newline

def print_exception(
e: Optional[BaseException],
tp: Optional[type[BaseException]] = None,
tb: Optional[TracebackType] = None,
e: BaseException | None,
tp: type[BaseException] | None = None,
tb: TracebackType | None = None,
) -> None:

@@ -59,0 +58,0 @@ """Print the given exception `e` using Basilisp's own exception formatting.

@@ -0,1 +1,2 @@

from collections.abc import Callable
from concurrent.futures import Future as _Future # noqa # pylint: disable=unused-import

@@ -5,3 +6,3 @@ from concurrent.futures import ProcessPoolExecutor as _ProcessPoolExecutor

from concurrent.futures import TimeoutError as _TimeoutError
from typing import Callable, Optional, TypeVar
from typing import TypeVar

@@ -31,4 +32,4 @@ import attr

def deref(
self, timeout: Optional[float] = None, timeout_val: Optional[T] = None
) -> Optional[T]:
self, timeout: float | None = None, timeout_val: T | None = None
) -> T | None:
try:

@@ -48,3 +49,3 @@ return self._future.result(timeout=timeout)

# still work with this Future wrapper.
def result(self, timeout: Optional[float] = None) -> T:
def result(self, timeout: float | None = None) -> T:
return self._future.result(timeout=timeout)

@@ -59,3 +60,3 @@

class ProcessPoolExecutor(_ProcessPoolExecutor): # pragma: no cover
def __init__(self, max_workers: Optional[int] = None):
def __init__(self, max_workers: int | None = None):
super().__init__(max_workers=max_workers)

@@ -73,3 +74,3 @@

self,
max_workers: Optional[int] = None,
max_workers: int | None = None,
thread_name_prefix: str = "basilisp-futures",

@@ -76,0 +77,0 @@ ):

import itertools
from abc import ABC, abstractmethod
from collections.abc import Hashable, Iterable, Iterator, Mapping, Sequence, Sized
from collections.abc import (
Callable,
Hashable,
Iterable,
Iterator,
Mapping,
Sequence,
Sized,
)
from typing import (
AbstractSet,
Any,
Callable,
Final,

@@ -36,3 +43,3 @@ Generic,

@abstractmethod
def deref(self) -> Optional[T]:
def deref(self) -> T | None:
raise NotImplementedError()

@@ -54,4 +61,4 @@

def deref(
self, timeout: Optional[float] = None, timeout_val: Optional[T] = None
) -> Optional[T]:
self, timeout: float | None = None, timeout_val: T | None = None
) -> T | None:
raise NotImplementedError()

@@ -183,3 +190,3 @@

@abstractmethod
def ns(self) -> Optional[str]:
def ns(self) -> str | None:
raise NotImplementedError()

@@ -189,3 +196,3 @@

@abstractmethod
def with_name(cls, name: str, ns: Optional[str] = None) -> Self:
def with_name(cls, name: str, ns: str | None = None) -> Self:
"""Create a new instance of this INamed with `name` and optional `ns`."""

@@ -246,7 +253,7 @@ raise NotImplementedError()

@abstractmethod
def get_validator(self) -> Optional[RefValidator[T]]:
def get_validator(self) -> RefValidator[T] | None:
raise NotImplementedError()
@abstractmethod
def set_validator(self, vf: Optional[RefValidator[T]] = None) -> None:
def set_validator(self, vf: RefValidator[T] | None = None) -> None:
raise NotImplementedError()

@@ -312,3 +319,3 @@

@abstractmethod
def val_at(self, k: K, default: Optional[V] = None) -> Optional[V]:
def val_at(self, k: K, default: V | None = None) -> V | None:
raise NotImplementedError()

@@ -373,3 +380,3 @@

@abstractmethod
def entry(self, k: K) -> Optional[IMapEntry[K, V]]:
def entry(self, k: K) -> IMapEntry[K, V] | None:
raise NotImplementedError()

@@ -390,3 +397,3 @@

@abstractmethod
def peek(self) -> Optional[T]:
def peek(self) -> T | None:
raise NotImplementedError()

@@ -560,7 +567,7 @@

T_tcoll_co = TypeVar("T_tcoll_co", bound="ITransientCollection", covariant=True)
T_tcoll = TypeVar("T_tcoll", bound="ITransientCollection")
# Including ABC as a base seems to cause catastrophic meltdown.
class IEvolveableCollection(Generic[T_tcoll_co]):
class IEvolveableCollection(Generic[T_tcoll]):
"""``IEvolveableCollection`` types support creating transient variants of persistent

@@ -575,3 +582,3 @@ data structures which can be modified efficiently and then returned back into

@abstractmethod
def to_transient(self) -> T_tcoll_co:
def to_transient(self) -> T_tcoll:
raise NotImplementedError()

@@ -591,7 +598,7 @@

@abstractmethod
def cons_transient(self: T_tcoll_co, *elems: T) -> "T_tcoll_co":
def cons_transient(self: T_tcoll, *elems: T) -> "T_tcoll":
raise NotImplementedError()
@abstractmethod
def to_persistent(self: T_tcoll_co) -> "IPersistentCollection[T]":
def to_persistent(self: T_tcoll) -> "IPersistentCollection[T]":
raise NotImplementedError()

@@ -619,3 +626,3 @@

@abstractmethod
def entry_transient(self, k: K) -> Optional[IMapEntry[K, V]]:
def entry_transient(self, k: K) -> IMapEntry[K, V] | None:
raise NotImplementedError()

@@ -735,2 +742,5 @@

T_inner = TypeVar("T_inner")
class ISeq(ILispObject, IPersistentCollection[T]):

@@ -749,3 +759,3 @@ """``ISeq`` types represent a potentially infinite sequence of elements.

class _SeqIter(Iterator[T]):
class _SeqIter(Iterator[T_inner]):
"""Stateful iterator for sequence types.

@@ -759,3 +769,3 @@

def __init__(self, seq: "ISeq[T]"):
def __init__(self, seq: "ISeq[T_inner]"):
self._cur = seq

@@ -782,3 +792,3 @@

@abstractmethod
def first(self) -> Optional[T]:
def first(self) -> T | None:
raise NotImplementedError()

@@ -785,0 +795,0 @@

import threading
from collections.abc import Iterable
from functools import total_ordering
from typing import Optional, Union

@@ -26,3 +25,3 @@ from typing_extensions import Unpack

def __init__(self, name: str, ns: Optional[str] = None) -> None:
def __init__(self, name: str, ns: str | None = None) -> None:
self._name = name

@@ -37,7 +36,7 @@ self._ns = ns

@property
def ns(self) -> Optional[str]:
def ns(self) -> str | None:
return self._ns
@classmethod
def with_name(cls, name: str, ns: Optional[str] = None) -> "Keyword":
def with_name(cls, name: str, ns: str | None = None) -> "Keyword":
return keyword(name, ns=ns)

@@ -72,3 +71,3 @@

def __call__(self, m: Union[IAssociative, IPersistentSet], default=None):
def __call__(self, m: IAssociative | IPersistentSet, default=None):
if isinstance(m, IPersistentSet):

@@ -87,3 +86,3 @@ return self if self in m else default

text: str,
kw_cache: Optional[IPersistentMap[int, Keyword]] = None,
kw_cache: IPersistentMap[int, Keyword] | None = None,
) -> Iterable[str]:

@@ -114,3 +113,3 @@ """Return an iterable of possible completions for the given text."""

def hash_kw(name: str, ns: Optional[str] = None) -> int:
def hash_kw(name: str, ns: str | None = None) -> int:
"""Return the hash of a potential Keyword instance by its name and namespace."""

@@ -120,3 +119,3 @@ return hash((name, ns))

def keyword_from_hash(kw_hash: int, name: str, ns: Optional[str] = None) -> Keyword:
def keyword_from_hash(kw_hash: int, name: str, ns: str | None = None) -> Keyword:
"""Return the interned keyword with the hash `kw_hash` or create and intern a new

@@ -145,3 +144,3 @@ keyword with name `name` and optional namespace `ns`.

def find_keyword(name: str, ns: Optional[str] = None) -> Optional[Keyword]:
def find_keyword(name: str, ns: str | None = None) -> Keyword | None:
"""Return the already-interned keyword named by `name` and `ns`, if one exists.

@@ -153,3 +152,3 @@ If the keyword with that name is not interned, return None."""

def keyword(name: str, ns: Optional[str] = None) -> Keyword:
def keyword(name: str, ns: str | None = None) -> Keyword:
"""Return a keyword with name `name` and optional namespace `ns`.

@@ -156,0 +155,0 @@

@@ -1,2 +0,2 @@

from typing import Optional, TypeVar, cast
from typing import TypeVar, cast

@@ -45,6 +45,6 @@ from pyrsistent import PList, plist # noqa # pylint: disable=unused-import

@property
def meta(self) -> Optional[IPersistentMap]:
def meta(self) -> IPersistentMap | None:
return self._meta
def with_meta(self, meta: Optional[IPersistentMap]) -> "PersistentList":
def with_meta(self, meta: IPersistentMap | None) -> "PersistentList":
return list(self._inner, meta=meta)

@@ -78,3 +78,3 @@

def seq(self) -> Optional[ISeq[T]]:
def seq(self) -> ISeq[T] | None:
if len(self._inner) == 0:

@@ -81,0 +81,0 @@ return None

from builtins import map as pymap
from collections.abc import Iterable, Mapping
from collections.abc import Callable, Iterable, Mapping
from itertools import islice
from typing import Any, Callable, Optional, TypeVar, Union, cast
from typing import Any, TypeVar, cast

@@ -66,4 +66,10 @@ from immutables import Map as _Map

def assoc_transient(self, *kvs) -> "TransientMap":
for k, v in partition(kvs, 2):
self._inner[k] = v
for t in partition(kvs, 2):
# Clojure allows assoc! to have odd numbers of arguments, setting nil for
# the missing value.
if len(t) == 2:
k, v = t
self._inner[k] = v
else:
self._inner[t[0]] = None # type: ignore[assignment]
return self

@@ -82,3 +88,3 @@

def entry_transient(self, k: K) -> Optional[IMapEntry[K, V]]:
def entry_transient(self, k: K) -> IMapEntry[K, V] | None:
v = self._inner.get(k, cast("V", _ENTRY_SENTINEL))

@@ -94,8 +100,8 @@ if v is _ENTRY_SENTINEL:

self,
*elems: Union[
IPersistentMap[K, V],
IMapEntry[K, V],
IPersistentVector[Union[K, V]],
Mapping[K, V],
],
*elems: (
IPersistentMap[K, V]
| IMapEntry[K, V]
| IPersistentVector[K | V]
| Mapping[K, V]
),
) -> "TransientMap[K, V]":

@@ -129,3 +135,3 @@ try:

end: str,
meta: Optional[IPersistentMap] = None,
meta: IPersistentMap | None = None,
**kwargs: Unpack[PrintSettings],

@@ -227,3 +233,3 @@ ) -> str:

m: "_Map[K, V]",
meta: Optional[IPersistentMap] = None,
meta: IPersistentMap | None = None,
) -> None:

@@ -236,4 +242,4 @@ self._inner = m

cls,
members: Union[Mapping[K, V], Iterable[tuple[K, V]]],
meta: Optional[IPersistentMap] = None,
members: Mapping[K, V] | Iterable[tuple[K, V]],
meta: IPersistentMap | None = None,
) -> "PersistentMap[K, V]":

@@ -282,6 +288,6 @@ return PersistentMap(_Map(members), meta=meta)

@property
def meta(self) -> Optional[IPersistentMap]:
def meta(self) -> IPersistentMap | None:
return self._meta
def with_meta(self, meta: Optional[IPersistentMap]) -> "PersistentMap":
def with_meta(self, meta: IPersistentMap | None) -> "PersistentMap":
return PersistentMap(self._inner, meta=meta)

@@ -331,8 +337,8 @@

self,
*elems: Union[
IPersistentMap[K, V],
IMapEntry[K, V],
IPersistentVector[Union[K, V]],
Mapping[K, V],
],
*elems: (
IPersistentMap[K, V]
| IMapEntry[K, V]
| IPersistentVector[K | V]
| Mapping[K, V]
),
) -> "PersistentMap[K, V]":

@@ -362,3 +368,3 @@ with self._inner.mutate() as m:

def seq(self) -> Optional[ISeq[IMapEntry[K, V]]]:
def seq(self) -> ISeq[IMapEntry[K, V]] | None:
if len(self._inner) == 0:

@@ -383,3 +389,3 @@ return None

def map( # pylint:disable=redefined-builtin
kvs: Mapping[K, V], meta: Optional[IPersistentMap] = None
kvs: Mapping[K, V], meta: IPersistentMap | None = None
) -> PersistentMap[K, V]:

@@ -386,0 +392,0 @@ """Creates a new map."""

import threading
from typing import Any, Callable, Generic, Optional, TypeVar
from typing import Any, TypeVar
from typing_extensions import Generic, ParamSpec, Protocol
from basilisp.lang import map as lmap

@@ -11,6 +13,16 @@ from basilisp.lang import runtime

T = TypeVar("T")
DispatchFunction = Callable[..., T]
Method = Callable[..., Any]
P = ParamSpec("P")
class DispatchFunction(Protocol[T, P]):
def __call__(self, v: T, *args: P.args, **kwargs: P.kwargs) -> T: ...
T_contra = TypeVar("T_contra", contravariant=True)
class Method(Protocol[T_contra, P]):
def __call__(self, v: T_contra, *args: P.args, **kwargs: P.kwargs) -> Any: ...
_GLOBAL_HIERARCHY_SYM = sym.symbol("global-hierarchy", ns=runtime.CORE_NS)

@@ -20,3 +32,3 @@ _ISA_SYM = sym.symbol("isa?", ns=runtime.CORE_NS)

class MultiFunction(Generic[T]):
class MultiFunction(Generic[T, P]):
__slots__ = (

@@ -38,5 +50,5 @@ "_name",

name: sym.Symbol,
dispatch: DispatchFunction,
dispatch: DispatchFunction[T, P],
default: T,
hierarchy: Optional[IRef] = None,
hierarchy: IRef | None = None,
) -> None:

@@ -69,7 +81,7 @@ self._name = name

def __call__(self, *args, **kwargs):
key = self._dispatch(*args, **kwargs)
def __call__(self, v: T, *args: P.args, **kwargs: P.kwargs) -> Any:
key = self._dispatch(v, *args, **kwargs)
method = self.get_method(key)
if method is not None:
return method(*args, **kwargs)
return method(v, *args, **kwargs)
raise NotImplementedError

@@ -101,3 +113,3 @@

def add_method(self, key: T, method: Method) -> None:
def add_method(self, key: T, method: Method[T, P]) -> None:
"""Add a new method to this function which will respond for key returned from

@@ -109,7 +121,7 @@ the dispatch function."""

def _find_and_cache_method(self, key: T) -> Optional[Method]:
def _find_and_cache_method(self, key: T) -> Method[T, P] | None:
"""Find and cache the best method for dispatch value `key`."""
with self._lock:
best_key: Optional[T] = None
best_method: Optional[Method] = None
best_key: T | None = None
best_method: Method | None = None
for method_key, method in self._methods.items():

@@ -134,3 +146,3 @@ if self._is_a(key, method_key):

def get_method(self, key: T) -> Optional[Method]:
def get_method(self, key: T) -> Method[T, P] | None:
"""Return the method which would handle this dispatch key or None if no method

@@ -169,3 +181,3 @@ defined for this key and no default."""

def remove_method(self, key: T) -> Optional[Method]:
def remove_method(self, key: T) -> Method[T, P] | None:
"""Remove the method defined for this key and return it."""

@@ -190,3 +202,3 @@ with self._lock:

@property
def methods(self) -> IPersistentMap[T, Method]:
def methods(self) -> IPersistentMap[T, Method[T, P]]:
return self._methods

@@ -281,7 +281,10 @@ import datetime

@lrepr.register(float)
def _lrepr_float(o: float, **_) -> str:
def _lrepr_float(o: float, human_readable: bool = False, **_) -> str:
if math.isinf(o):
return "##Inf" if o > 0 else "##-Inf"
if o > 0:
return "Infinity" if human_readable else "##Inf"
else:
return "-Infinity" if human_readable else "##-Inf"
if math.isnan(o):
return "##NaN"
return "NaN" if human_readable else "##NaN"
return repr(o)

@@ -288,0 +291,0 @@

import threading
from typing import Optional, TypeVar
from typing import TypeVar

@@ -15,3 +15,3 @@ from basilisp.lang.interfaces import IBlockingDeref, IPending

self._is_delivered = False
self._value: Optional[T] = None
self._value: T | None = None

@@ -25,5 +25,7 @@ def deliver(self, value: T) -> None:

__call__ = deliver
def deref(
self, timeout: Optional[float] = None, timeout_val: Optional[T] = None
) -> Optional[T]:
self, timeout: float | None = None, timeout_val: T | None = None
) -> T | None:
with self._condition:

@@ -30,0 +32,0 @@ if self._condition.wait_for(lambda: self._is_delivered, timeout=timeout):

@@ -1,2 +0,2 @@

from typing import Optional, TypeVar
from typing import TypeVar

@@ -56,6 +56,6 @@ from pyrsistent import PDeque, pdeque # noqa # pylint: disable=unused-import

@property
def meta(self) -> Optional[IPersistentMap]:
def meta(self) -> IPersistentMap | None:
return self._meta
def with_meta(self, meta: Optional[IPersistentMap]) -> "PersistentQueue":
def with_meta(self, meta: IPersistentMap | None) -> "PersistentQueue":
return queue(self._inner, meta=meta)

@@ -80,3 +80,3 @@

def seq(self) -> Optional[ISeq[T]]:
def seq(self) -> ISeq[T] | None:
if len(self._inner) == 0:

@@ -83,0 +83,0 @@ return None

import threading
from typing import Any, Callable, Optional, TypeVar
from collections.abc import Callable
from typing import Any, Concatenate, Optional, TypeVar
from typing_extensions import Concatenate, ParamSpec
from typing_extensions import ParamSpec

@@ -31,10 +32,10 @@ from basilisp.lang import keyword as kw

_lock: threading.RLock
_meta: Optional[IPersistentMap]
_meta: IPersistentMap | None
@property
def meta(self) -> Optional[IPersistentMap]:
def meta(self) -> IPersistentMap | None:
with self._lock:
return self._meta
def alter_meta(self, f: AlterMeta, *args) -> Optional[IPersistentMap]:
def alter_meta(self, f: AlterMeta, *args) -> IPersistentMap | None:
with self._lock:

@@ -44,3 +45,3 @@ self._meta = f(self._meta, *args)

def reset_meta(self, meta: Optional[IPersistentMap]) -> Optional[IPersistentMap]:
def reset_meta(self, meta: IPersistentMap | None) -> IPersistentMap | None:
with self._lock:

@@ -64,3 +65,3 @@ self._meta = meta

_validator: Optional[RefValidator[T]]
_validator: RefValidator[T] | None
_watches: IPersistentMap[RefWatchKey, RefWatcher[T]]

@@ -82,6 +83,6 @@

def get_validator(self) -> Optional[RefValidator[T]]:
def get_validator(self) -> RefValidator[T] | None:
return self._validator
def set_validator(self, vf: Optional[RefValidator[T]] = None) -> None:
def set_validator(self, vf: RefValidator[T] | None = None) -> None:
with self._lock:

@@ -92,3 +93,3 @@ if vf is not None:

def _validate(self, val: Any, vf: Optional[RefValidator[T]] = None) -> None:
def _validate(self, val: Any, vf: RefValidator[T] | None = None) -> None:
vf = vf or self._validator

@@ -95,0 +96,0 @@ if vf is not None:

import functools
import threading
from collections.abc import Iterable
from typing import Callable, Optional, TypeVar, overload
from collections.abc import Callable, Iterable
from typing import Optional, TypeVar, overload

@@ -21,3 +21,3 @@ from basilisp.lang.interfaces import (

def __init__(self, meta: Optional[IPersistentMap] = None):
def __init__(self, meta: IPersistentMap | None = None):
self._meta = meta

@@ -31,10 +31,10 @@

def seq(self) -> Optional[ISeq[T]]:
def seq(self) -> ISeq[T] | None:
return None
@property
def meta(self) -> Optional[IPersistentMap]:
def meta(self) -> IPersistentMap | None:
return self._meta
def with_meta(self, meta: Optional[IPersistentMap]) -> "_EmptySequence[T]":
def with_meta(self, meta: IPersistentMap | None) -> "_EmptySequence[T]":
return _EmptySequence(meta=meta)

@@ -47,3 +47,3 @@

@property
def first(self) -> Optional[T]:
def first(self) -> T | None:
return None

@@ -74,4 +74,4 @@

first: T,
seq: Optional[ISeq[T]] = None,
meta: Optional[IPersistentMap] = None,
seq: ISeq[T] | None = None,
meta: IPersistentMap | None = None,
) -> None:

@@ -87,3 +87,3 @@ self._first = first

@property
def first(self) -> Optional[T]:
def first(self) -> T | None:
return self._first

@@ -105,6 +105,6 @@

@property
def meta(self) -> Optional[IPersistentMap]:
def meta(self) -> IPersistentMap | None:
return self._meta
def with_meta(self, meta: Optional[IPersistentMap]) -> "Cons[T]":
def with_meta(self, meta: IPersistentMap | None) -> "Cons[T]":
return Cons(self._first, seq=self._rest, meta=meta)

@@ -128,10 +128,10 @@

self,
gen: Optional[LazySeqGenerator],
seq: Optional[ISeq[T]] = None,
gen: LazySeqGenerator | None,
seq: ISeq[T] | None = None,
*,
meta: Optional[IPersistentMap] = None,
meta: IPersistentMap | None = None,
) -> None:
self._gen: Optional[LazySeqGenerator] = gen
self._obj: Optional[ISeq[T]] = None
self._seq: Optional[ISeq[T]] = seq
self._gen: LazySeqGenerator | None = gen
self._obj: ISeq[T] | None = None
self._seq: ISeq[T] | None = seq
self._lock = threading.RLock()

@@ -141,6 +141,6 @@ self._meta = meta

@property
def meta(self) -> Optional[IPersistentMap]:
def meta(self) -> IPersistentMap | None:
return self._meta
def with_meta(self, meta: Optional[IPersistentMap]) -> "LazySeq[T]":
def with_meta(self, meta: IPersistentMap | None) -> "LazySeq[T]":
return LazySeq(None, seq=self.seq(), meta=meta)

@@ -157,3 +157,3 @@

def _compute_seq(self) -> Optional[ISeq[T]]:
def _compute_seq(self) -> ISeq[T] | None:
if self._gen is not None:

@@ -180,3 +180,3 @@ # This local caching of the generator function and clearing of self._gen

def seq(self) -> Optional[ISeq[T]]:
def seq(self) -> ISeq[T] | None:
with self._lock:

@@ -205,3 +205,3 @@ self._compute_seq()

@property
def first(self) -> Optional[T]:
def first(self) -> T | None:
if self.is_empty:

@@ -267,3 +267,3 @@ return None

@overload
def _seq_or_nil(s: ISeq) -> Optional[ISeq]: ...
def _seq_or_nil(s: ISeq) -> ISeq | None: ...

@@ -279,3 +279,3 @@

@functools.singledispatch
def to_seq(o) -> Optional[ISeq]:
def to_seq(o) -> ISeq | None:
"""Coerce the argument o to a ISeq. If o is None, return None."""

@@ -291,3 +291,3 @@ return _seq_or_nil(sequence(o))

@to_seq.register(ISeq)
def _to_seq_iseq(o: ISeq) -> Optional[ISeq]:
def _to_seq_iseq(o: ISeq) -> ISeq | None:
return _seq_or_nil(o)

@@ -297,3 +297,3 @@

@to_seq.register(LazySeq)
def _to_seq_lazyseq(o: LazySeq) -> Optional[ISeq]:
def _to_seq_lazyseq(o: LazySeq) -> ISeq | None:
# Force evaluation of the LazySeq by calling o.seq() directly.

@@ -304,3 +304,3 @@ return o.seq()

@to_seq.register(ISeqable)
def _to_seq_iseqable(o: ISeqable) -> Optional[ISeq]:
def _to_seq_iseqable(o: ISeqable) -> ISeq | None:
return _seq_or_nil(o.seq())
from collections.abc import Iterable
from collections.abc import Set as _PySet
from typing import AbstractSet, Optional, TypeVar
from typing import AbstractSet, TypeVar

@@ -78,3 +78,3 @@ from immutables import Map as _Map

def __init__(self, m: "_Map[T, T]", meta: Optional[IPersistentMap] = None) -> None:
def __init__(self, m: "_Map[T, T]", meta: IPersistentMap | None = None) -> None:
self._inner = m

@@ -85,3 +85,3 @@ self._meta = meta

def from_iterable(
cls, members: Optional[Iterable[T]], meta: Optional[IPersistentMap] = None
cls, members: Iterable[T] | None, meta: IPersistentMap | None = None
) -> "PersistentSet":

@@ -150,6 +150,6 @@ return PersistentSet(_Map((m, m) for m in (members or ())), meta=meta)

@property
def meta(self) -> Optional[IPersistentMap]:
def meta(self) -> IPersistentMap | None:
return self._meta
def with_meta(self, meta: Optional[IPersistentMap]) -> "PersistentSet[T]":
def with_meta(self, meta: IPersistentMap | None) -> "PersistentSet[T]":
return set(self._inner, meta=meta)

@@ -175,3 +175,3 @@

def seq(self) -> Optional[ISeq[T]]:
def seq(self) -> ISeq[T] | None:
if len(self._inner) == 0:

@@ -189,3 +189,3 @@ return None

def set( # pylint:disable=redefined-builtin
members: Iterable[T], meta: Optional[IPersistentMap] = None
members: Iterable[T], meta: IPersistentMap | None = None
) -> PersistentSet[T]:

@@ -196,4 +196,4 @@ """Creates a new set."""

def s(*members: T, meta: Optional[IPersistentMap] = None) -> PersistentSet[T]:
def s(*members: T, meta: IPersistentMap | None = None) -> PersistentSet[T]:
"""Creates a new set from members."""
return PersistentSet.from_iterable(members, meta=meta)

@@ -5,3 +5,2 @@ import itertools

from collections.abc import Iterable
from typing import Optional

@@ -15,3 +14,3 @@ try:

def _format_source(
s: str, disable_color: Optional[bool] = None # pylint: disable=unused-argument
s: str, disable_color: bool | None = None # pylint: disable=unused-argument
) -> str:

@@ -23,4 +22,4 @@ return f"{s}{os.linesep}"

def _get_formatter_name(
disable_color: Optional[bool] = None,
) -> Optional[str]: # pragma: no cover
disable_color: bool | None = None,
) -> str | None: # pragma: no cover
"""Get the Pygments formatter name for formatting the source code by

@@ -43,3 +42,3 @@ inspecting various environment variables set by terminals.

def _format_source(
s: str, disable_color: Optional[bool] = None
s: str, disable_color: bool | None = None
) -> str: # pragma: no cover

@@ -63,6 +62,6 @@ """Format source code for terminal output.

line: int,
end_line: Optional[int] = None,
end_line: int | None = None,
num_context_lines: int = 5,
show_cause_marker: bool = True,
disable_color: Optional[bool] = None,
disable_color: bool | None = None,
) -> list[str]:

@@ -79,3 +78,3 @@ """Format source code context with line numbers and identifiers for the affected

if not filename.startswith("<") and not filename.endswith(">"):
cause_range: Optional[range]
cause_range: range | None
if not show_cause_marker:

@@ -82,0 +81,0 @@ cause_range = None

from functools import total_ordering
from typing import Optional, Union

@@ -23,3 +22,3 @@ from typing_extensions import Unpack

def __init__(
self, name: str, ns: Optional[str] = None, meta: Optional[IPersistentMap] = None
self, name: str, ns: str | None = None, meta: IPersistentMap | None = None
) -> None:

@@ -48,14 +47,14 @@ self._name = name

@property
def ns(self) -> Optional[str]:
def ns(self) -> str | None:
return self._ns
@classmethod
def with_name(cls, name: str, ns: Optional[str] = None) -> "Symbol":
def with_name(cls, name: str, ns: str | None = None) -> "Symbol":
return Symbol(name, ns=ns)
@property
def meta(self) -> Optional[IPersistentMap]:
def meta(self) -> IPersistentMap | None:
return self._meta
def with_meta(self, meta: Optional[IPersistentMap]) -> "Symbol":
def with_meta(self, meta: IPersistentMap | None) -> "Symbol":
return Symbol(self._name, self._ns, meta=meta)

@@ -89,3 +88,3 @@

def __call__(self, m: Union[IAssociative, IPersistentSet], default=None):
def __call__(self, m: IAssociative | IPersistentSet, default=None):
if isinstance(m, IPersistentSet):

@@ -100,5 +99,5 @@ return self if self in m else default

def symbol(
name: str, ns: Optional[str] = None, meta: Optional[IPersistentMap] = None
name: str, ns: str | None = None, meta: IPersistentMap | None = None
) -> Symbol:
"""Create a new symbol."""
return Symbol(name, ns=ns, meta=meta)

@@ -1,2 +0,2 @@

from typing import Optional, TypeVar, Union
from typing import TypeVar, Union

@@ -26,3 +26,3 @@ from typing_extensions import Unpack

self._form = form
self._hash: Optional[int] = None
self._hash: int | None = None

@@ -55,3 +55,3 @@ @property

def val_at(self, k: K, default: Optional[V] = None) -> T:
def val_at(self, k: K, default: V | None = None) -> T:
if k == _TAG_KW:

@@ -58,0 +58,0 @@ return self._tag

@@ -6,3 +6,3 @@ import uuid

from re import Pattern
from typing import Optional, Protocol, Union
from typing import Any, Protocol, Union

@@ -30,3 +30,3 @@ from basilisp.lang import keyword as kw

]
LispNumber = Union[int, float, Fraction]
LispNumber = Union[int, float, Decimal, Fraction]
LispForm = Union[

@@ -58,9 +58,13 @@ bool,

class Comparable(Protocol):
def __lt__(self, other: Any, /) -> bool: ...
class BasilispFunction(Protocol):
_basilisp_fn: bool
arities: IPersistentSet[Union[kw.Keyword, int]]
meta: Optional[IPersistentMap]
arities: IPersistentSet[kw.Keyword | int]
meta: IPersistentMap | None
def __call__(self, *args, **kwargs): ...
def with_meta(self, meta: Optional[IPersistentMap]) -> "BasilispFunction": ...
def with_meta(self, meta: IPersistentMap | None) -> "BasilispFunction": ...
from collections.abc import Iterable, Sequence
from functools import total_ordering
from typing import Optional, TypeVar, Union, cast, overload
from typing import Any, TypeVar, Union, cast, overload

@@ -60,4 +60,10 @@ from pyrsistent import PVector, pvector # noqa # pylint: disable=unused-import

def assoc_transient(self, *kvs: T) -> "TransientVector[T]":
for i, v in cast("Sequence[tuple[int, T]]", partition(kvs, 2)):
self._inner.set(i, v)
for t in cast("Sequence[tuple[int, T] | tuple[int]]", partition(kvs, 2)):
# Clojure allows assoc! to have odd numbers of arguments, setting nil for
# the missing value.
if len(t) == 2:
i, v = t
self._inner.set(i, v)
else:
self._inner.set(t[0], None) # type: ignore[arg-type]
return self

@@ -68,3 +74,3 @@

def entry_transient(self, k: int) -> Optional[IMapEntry[int, T]]:
def entry_transient(self, k: int) -> IMapEntry[int, T] | None:
try:

@@ -107,3 +113,3 @@ return MapEntry.of(k, self._inner[k])

def __init__(
self, wrapped: "PVector[T]", meta: Optional[IPersistentMap] = None
self, wrapped: "PVector[T]", meta: IPersistentMap | None = None
) -> None:

@@ -140,4 +146,4 @@ self._inner = wrapped

def __call__(self, k: int, default: Optional[T] = None) -> Optional[T]:
return self.val_at(k, default=default)
def __call__(self, k: int) -> T | None:
return self._inner[k]

@@ -171,6 +177,6 @@ def __lt__(self, other):

@property
def meta(self) -> Optional[IPersistentMap]:
def meta(self) -> IPersistentMap | None:
return self._meta
def with_meta(self, meta: Optional[IPersistentMap]) -> "PersistentVector[T]":
def with_meta(self, meta: IPersistentMap | None) -> "PersistentVector[T]":
return vector(self._inner, meta=meta)

@@ -187,6 +193,8 @@

def contains(self, k: int) -> bool:
def contains(self, k: Any) -> bool:
if not isinstance(k, int):
return False
return 0 <= k < len(self._inner)
def entry(self, k: int) -> Optional[IMapEntry[int, T]]:
def entry(self, k: int) -> IMapEntry[int, T] | None:
try:

@@ -197,3 +205,3 @@ return MapEntry.of(k, self._inner[k])

def val_at(self, k: int, default: Optional[T] = None) -> Optional[T]:
def val_at(self, k: int, default: T | None = None) -> T | None:
try:

@@ -207,3 +215,3 @@ return self._inner[k]

def seq(self) -> Optional[ISeq[T]]: # type: ignore[override]
def seq(self) -> ISeq[T] | None: # type: ignore[override]
if len(self._inner) == 0:

@@ -213,3 +221,3 @@ return None

def peek(self) -> Optional[T]:
def peek(self) -> T | None:
if len(self) == 0:

@@ -271,8 +279,3 @@ return None

def __init__(self, wrapped: "PVector[Union[K, V]]") -> None:
try:
if not len(wrapped) == 2:
raise ValueError("Vector arg to map conj must be a pair")
except TypeError as e:
raise TypeError(f"Cannot make map entry from {type(wrapped)}") from e
assert len(wrapped) == 2, "Vector arg to map conj must be a pair"
super().__init__(wrapped)

@@ -293,3 +296,8 @@

@staticmethod
def from_vec(v: Sequence[Union[K, V]]) -> "MapEntry[K, V]":
def from_vec(v: Sequence[K | V]) -> "MapEntry[K, V]":
try:
if len(v) != 2:
raise ValueError("Vector arg to map conj must be a pair")
except TypeError as e:
raise TypeError(f"Cannot make map entry from {type(v)}") from e
return MapEntry(pvector(v))

@@ -302,3 +310,3 @@

def vector(
members: Iterable[T], meta: Optional[IPersistentMap] = None
members: Iterable[T], meta: IPersistentMap | None = None
) -> PersistentVector[T]:

@@ -309,4 +317,4 @@ """Creates a new vector."""

def v(*members: T, meta: Optional[IPersistentMap] = None) -> PersistentVector[T]:
def v(*members: T, meta: IPersistentMap | None = None) -> PersistentVector[T]:
"""Creates a new vector from members."""
return PersistentVector(pvector(members), meta=meta)

@@ -1,5 +0,6 @@

from typing import Callable, Optional, TypeVar
from collections.abc import Callable
from typing import Concatenate, TypeVar
import attr
from typing_extensions import Concatenate, ParamSpec
from typing_extensions import ParamSpec

@@ -20,3 +21,3 @@ from basilisp.lang.interfaces import IDeref

def deref(self) -> Optional[T]:
def deref(self) -> T | None:
return self.value

@@ -23,0 +24,0 @@

import logging
import os
from typing import Optional

@@ -20,5 +19,3 @@ TRACE = 5

def get_handler(
level: Optional[str] = None, fmt: str = DEFAULT_FORMAT
) -> logging.Handler:
def get_handler(level: str | None = None, fmt: str = DEFAULT_FORMAT) -> logging.Handler:
"""Get the default logging handler for Basilisp."""

@@ -35,5 +32,3 @@ handler = (

def configure_root_logger(
level: Optional[str] = None, fmt: str = DEFAULT_FORMAT
) -> None:
def configure_root_logger(level: str | None = None, fmt: str = DEFAULT_FORMAT) -> None:
"""Configure the Basilisp root logger."""

@@ -40,0 +35,0 @@ level = level or get_level()

@@ -6,3 +6,2 @@ import importlib

from pathlib import Path
from typing import Optional

@@ -20,3 +19,3 @@ from basilisp import importer as importer

def init(opts: Optional[CompilerOpts] = None, force_reload: bool = False) -> None:
def init(opts: CompilerOpts | None = None, force_reload: bool = False) -> None:
"""

@@ -50,3 +49,3 @@ Initialize the runtime environment for Basilisp code evaluation.

def bootstrap(
target: str, opts: Optional[CompilerOpts] = None
target: str, opts: CompilerOpts | None = None
) -> None: # pragma: no cover

@@ -77,3 +76,3 @@ """

def bootstrap_python(site_packages: Optional[str] = None) -> str:
def bootstrap_python(site_packages: str | None = None) -> str:
"""Bootstrap a Python installation by installing a ``.pth`` file

@@ -98,3 +97,3 @@ in ``site-packages`` directory (corresponding to "purelib" in

def unbootstrap_python(site_packages: Optional[str] = None) -> Optional[str]:
def unbootstrap_python(site_packages: str | None = None) -> str | None:
"""Remove the `basilispbootstrap.pth` file found in the Python site-packages

@@ -101,0 +100,0 @@ directory (corresponding to "purelib" in :external:py:func:`sysconfig.get_paths`).

import contextlib
import time
from collections.abc import Iterable, Sequence
from typing import Callable, Generic, Optional, TypeVar
from collections.abc import Callable, Iterable, Sequence
from typing import Generic, TypeVar
@contextlib.contextmanager
def timed(f: Optional[Callable[[int], None]] = None):
def timed(f: Callable[[int], None] | None = None):
"""Time the execution of code in the with-block, calling the function

@@ -26,3 +26,3 @@ f (if it is given) with the resulting time in nanoseconds."""

def __init__(self, inner: Optional[T]) -> None:
def __init__(self, inner: T | None) -> None:
self._inner = inner

@@ -62,3 +62,3 @@

@property
def value(self) -> Optional[T]:
def value(self) -> T | None:
return self._inner

@@ -65,0 +65,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet