Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 20 additions & 14 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,62 +8,68 @@ all: venv format check test build

.PHONY: format
format: venv
.venv/bin/isort src tests tools examples $(FLAGS)
.venv/bin/black -tpy312 -tpy313 -tpy314 src tests tools examples $(FLAGS)
uv run isort src tests tools examples $(FLAGS)
uv run black -tpy312 src tests tools examples $(FLAGS)

.PHONY: check
check: venv
.venv/bin/pyright --pythonpath .venv/bin/python src tests tools examples
uv run pyright src tests tools examples

.PHONY: test
test: venv
.venv/bin/pytest $(FLAGS)
uv run pytest $(FLAGS)

.PHONY: coverage
coverage: venv
coverage erase
COVERAGE_PROCESS_START=.coveragerc .venv/bin/coverage run -m pytest $(FLAGS)
COVERAGE_PROCESS_START=.coveragerc uv run coverage run -m pytest $(FLAGS)
coverage combine
coverage report

.PHONY: demo
demo: venv
.venv/bin/python -m tools.query $(FLAGS)
uv run python -m tools.query $(FLAGS)

.PHONY: compare
compare: venv
.venv/bin/python -m tools.query --batch $(FLAGS)
uv run python -m tools.query --batch $(FLAGS)

.PHONY: eval
eval: venv
rm -f eval.db
uv run python tools/load_json.py --database eval.db tests/testdata/Episode_53_AdrianTchaikovsky_index
uv run python tools/query.py --batch --database eval.db --answer-results tests/testdata/Episode_53_Answer_results.json --search-results tests/testdata/Episode_53_Search_results.json $(FLAGS)

.PHONY: mcp
mcp: venv
.venv/bin/mcp dev src/typeagent/mcp/server.py
uv run mcp dev src/typeagent/mcp/server.py

.PHONY: profile
profile: venv
</dev/null .venv/bin/python -m cProfile -s ncalls -m test.cmpsearch --interactive --podcast ~/AISystems-Archive/data/knowpro/test/indexes/All_Episodes_index | head -60
</dev/null uv run python -m cProfile -s ncalls -m test.cmpsearch --interactive --podcast ~/AISystems-Archive/data/knowpro/test/indexes/All_Episodes_index | head -60

.PHONY: scaling
scaling: venv
</dev/null .venv/bin/python -m test.cmpsearch --interactive --podcast ~/AISystems-Archive/data/knowpro/test/indexes/All_Episodes_index
</dev/null uv run python -m test.cmpsearch --interactive --podcast ~/AISystems-Archive/data/knowpro/test/indexes/All_Episodes_index

.PHONY: build
build: venv
uv build

.PHONY: release
release: venv
.venv/bin/python tools/release.py $(VERSION)
uv run python tools/release.py $(VERSION)

.PHONY: venv
venv: .venv

.venv:
@echo "(If 'uv' fails with 'No such file or directory', try 'make install-uv')"
uv sync -q $(FLAGS)
.venv/bin/black --version
uv run black --version
@echo "(If 'pyright' fails with 'error while loading shared libraries: libatomic.so.1:', try 'make install-libatomic')"
.venv/bin/pyright --version
.venv/bin/pytest --version
uv run pyright --version
uv run pytest --version

.PHONY: sync
sync:
Expand Down
18 changes: 9 additions & 9 deletions make.bat
Original file line number Diff line number Diff line change
Expand Up @@ -27,26 +27,26 @@ goto help
:format
if not exist ".venv\" call make.bat venv
echo Formatting code...
.venv\Scripts\isort src tests tools examples
.venv\Scripts\black src tests tools examples
uv run isort src tests tools examples
uv run black -tpy312 src tests tools examples
goto end

:check
if not exist ".venv\" call make.bat venv
echo Running type checks...
.venv\Scripts\pyright --pythonpath .venv\Scripts\python src tests tools examples
uv run pyright src tests tools examples
goto end

:test
if not exist ".venv\" call make.bat venv
echo Running unit tests...
.venv\Scripts\python -m pytest
uv run pytest
goto end

:demo
if not exist ".venv\" call make.bat venv
echo Running query tool...
.venv\Scripts\python -m tools.query
uv run python -m tools.query
goto end

:build
Expand All @@ -58,10 +58,10 @@ goto end
:venv
echo Creating virtual environment...
uv sync -q
.venv\Scripts\python --version
.venv\Scripts\black --version
.venv\Scripts\pyright --version
.venv\Scripts\python -m pytest --version
uv run python --version
uv run black --version
uv run pyright --version
uv run pytest --version
goto end

:sync
Expand Down
9 changes: 7 additions & 2 deletions src/typeagent/aitools/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,20 +48,25 @@ def pretty_print(obj: object, prefix: str = "", suffix: str = "") -> None:
import pprint

line_width = min(200, shutil.get_terminal_size().columns)
print(pprint.pformat(obj, width=line_width))
print(prefix + pprint.pformat(obj, width=line_width) + suffix)


def format_code(text: str, line_width=None) -> str:
"""Format a Python literal expression using pprint.

NOTE: The text must be a valid Python literal expression (as produced by repr()).
Falls back to plain text formatting if the text is not a valid literal.
"""
import ast
import pprint

if line_width is None:
line_width = min(200, shutil.get_terminal_size().columns)
return pprint.pformat(ast.literal_eval(text), width=line_width)
try:
return pprint.pformat(ast.literal_eval(text), width=line_width)
except (ValueError, SyntaxError):
# Fall back to simple pprint of the string itself if it's not a valid literal
return pprint.pformat(text, width=line_width)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
return pprint.pformat(text, width=line_width)
return text

pprint.pformat on a plain string wraps it in quotes — returning text directly avoids that.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Let's put a pin in that until we see its effect. (In any case you would have to update the comment too.)



def reindent(text: str) -> str:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

pprint.pformat(text) on a plain string returns its repr() — e.g. '<CustomClass object at 0x...>' with surrounding quotes. Since text is already a repr string intended for terminal/diff output, returning it directly avoids the extra quoting:

Suggested change
def reindent(text: str) -> str:
except (ValueError, SyntaxError):
# Fall back to the raw text if it's not a valid literal
return text

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

That suggestion would make the code incorrect.

Expand Down
4 changes: 3 additions & 1 deletion src/typeagent/knowpro/conversation_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@
answer_response_schema,
answers,
convknowledge,
knowledge_schema as kplib,
)
from . import (
search_query_schema,
searchlang,
secindex,
)
from . import knowledge_schema as kplib
from ..aitools import model_adapters, utils
from ..storage.memory import semrefindex
from .convsettings import ConversationSettings
Expand Down
3 changes: 2 additions & 1 deletion src/typeagent/knowpro/knowledge.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@

from typechat import Result, TypeChatLanguageModel

from . import convknowledge, knowledge_schema as kplib
from . import convknowledge
from . import knowledge_schema as kplib
from ..aitools import model_adapters
from .interfaces import IKnowledgeExtractor

Expand Down
4 changes: 3 additions & 1 deletion src/typeagent/storage/memory/semrefindex.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@

from typechat import Failure

from ...knowpro import convknowledge, knowledge_schema as kplib, secindex
from ...knowpro import convknowledge
from ...knowpro import knowledge_schema as kplib
from ...knowpro import secindex
from ...knowpro.convsettings import ConversationSettings, SemanticRefIndexSettings
from ...knowpro.interfaces import ( # Interfaces.; Other imports.
IConversation,
Expand Down
11 changes: 8 additions & 3 deletions tests/benchmarks/test_benchmark_vectorbase.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,11 @@
import pytest

from typeagent.aitools.model_adapters import create_test_embedding_model
from typeagent.aitools.vectorbase import ScoredInt, TextEmbeddingIndexSettings, VectorBase

from typeagent.aitools.vectorbase import (
ScoredInt,
TextEmbeddingIndexSettings,
VectorBase,
)

# -- Helpers ------------------------------------------------------------------

Expand Down Expand Up @@ -61,7 +64,9 @@ def test_1k_vectors(self, benchmark, vb_1k: tuple[VectorBase, np.ndarray]) -> No
assert len(result) == 10
assert all(isinstance(r, ScoredInt) for r in result)

def test_10k_vectors(self, benchmark, vb_10k: tuple[VectorBase, np.ndarray]) -> None:
def test_10k_vectors(
self, benchmark, vb_10k: tuple[VectorBase, np.ndarray]
) -> None:
vb, query = vb_10k
result = benchmark(vb.fuzzy_lookup_embedding, query, max_hits=10, min_score=0.0)
assert len(result) == 10
Expand Down
3 changes: 2 additions & 1 deletion tests/test_knowledge.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@

from typechat import Failure, Result, Success

from typeagent.knowpro import convknowledge, knowledge_schema as kplib
from typeagent.knowpro import convknowledge
from typeagent.knowpro import knowledge_schema as kplib
from typeagent.knowpro.knowledge import (
create_knowledge_extractor,
extract_knowledge_from_text,
Expand Down
7 changes: 6 additions & 1 deletion tests/test_semrefindex.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,12 @@
ITermToSemanticRefIndex,
Topic,
)
from typeagent.knowpro.knowledge_schema import Action, ConcreteEntity, Facet, KnowledgeResponse
from typeagent.knowpro.knowledge_schema import (
Action,
ConcreteEntity,
Facet,
KnowledgeResponse,
)
from typeagent.storage import SqliteStorageProvider
from typeagent.storage.memory import MemoryStorageProvider
from typeagent.storage.memory.semrefindex import (
Expand Down
25 changes: 25 additions & 0 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,31 @@ def test_format_code_nested():
assert parsed == obj


def test_format_code_non_literal():
"""Test that format_code gracefully handles non-literal expressions.

Regression test for commit 59be9a5 which broke debug output when format_code()
was called on repr() of objects containing non-literal elements (e.g., AST nodes,
custom class instances).
"""

# Create a custom class instance (a non-literal object whose repr() can't be
# evaluated with ast.literal_eval)
class CustomClass:
pass

obj = CustomClass()
non_literal_repr = repr(obj)
# This repr looks like: <__main__.CustomClass object at 0x...>

# format_code() should handle this gracefully without raising ValueError
result = utils.format_code(non_literal_repr)
assert isinstance(result, str)
assert len(result) > 0
# The result should contain the non-literal repr (possibly wrapped in quotes)
assert "CustomClass object" in result or "CustomClass" in result


def test_load_dotenv(really_needs_auth):
# Call load_dotenv and check for at least one expected key
load_dotenv()
Expand Down
4 changes: 3 additions & 1 deletion tools/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,15 @@
from typeagent.knowpro import (
answer_response_schema,
answers,
knowledge_schema as kplib,
)
from typeagent.knowpro import (
query,
search,
search_query_schema,
searchlang,
serialization,
)
from typeagent.knowpro import knowledge_schema as kplib
from typeagent.knowpro.convsettings import ConversationSettings
from typeagent.knowpro.interfaces import (
IConversation,
Expand Down
10 changes: 8 additions & 2 deletions tools/release.py
Original file line number Diff line number Diff line change
Expand Up @@ -450,9 +450,15 @@ def main():

if exit_code != 0:
if args.force:
print("Warning: Failed to create PR -- you can create it yourself", file=sys.stderr)
print(
"Warning: Failed to create PR -- you can create it yourself",
file=sys.stderr,
)
else:
print("Error: Failed to create PR -- but you can create it yourself", file=sys.stderr)
print(
"Error: Failed to create PR -- but you can create it yourself",
file=sys.stderr,
)
return 1

if args.dry_run:
Expand Down
4 changes: 2 additions & 2 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading