Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: example & changes to show autocomplete for st.chat_input #1

Merged
merged 2 commits into from
Jul 21, 2024
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
22 changes: 22 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Lint
on: [push, pull_request]
jobs:
ruff:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: chartboost/ruff-action@v1
with:
args: 'format --check'
sonarcloud:
name: SonarCloud
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
- name: SonarCloud Scan
uses: SonarSource/sonarcloud-github-action@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
28 changes: 28 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Release

on:
push:
tags:
- 'v*'

jobs:
build-and-publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2

- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.10

- name: Install Poetry
run: |
pip install poetry
poetry install

- name: Build and Publish
env:
POETRY_PYPI_TOKEN_PYPI: ${{ secrets.PYPI_API_TOKEN }}
run: |
poetry publish --build
34 changes: 34 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: Pytest with Playwright

on:
pull_request:
branches:
- main

jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.10.12, 3.11]

steps:
- uses: actions/checkout@v2

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: |
pip install poetry
poetry install

- name: Install Playwright browsers
run: |
poetry run playwright install

- name: Run pytest with Playwright
run: |
poetry run pytest e2e/
4 changes: 0 additions & 4 deletions .lintstagedrc.json

This file was deleted.

10 changes: 10 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.5.4
hooks:
# Run the linter.
- id: ruff
args: [ --fix ]
# Run the formatter.
- id: ruff-format
23 changes: 2 additions & 21 deletions .renovaterc.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,10 @@
"extends": [
"config:base",
"group:all",
"monorepo:angular",
"schedule:monthly",
":maintainLockFilesMonthly"
],
"ignoreDeps": [
"typescript",
"semantic-release",
"@semantic-release/git",
"@semantic-release/changelog"
],
"ignoreDeps": [],
"pinVersions": false,
"separatePatchReleases": false,
"ignoreUnstable": true,
Expand All @@ -23,18 +17,5 @@
"peerDependencies": {
"versionStrategy": "widen"
},
"packageRules": [
{
"sourceUrlPrefixes": ["https://github.com/babel/babel"],
"groupName": "babel monorepo"
},
{
"packagePatterns": ["^eslint"],
"groupName": "eslint"
},
{
"packagePatterns": ["jest"],
"groupName": "jest"
}
]
"packageRules": []
}
10 changes: 7 additions & 3 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,25 @@
"request": "launch",
"module": "pytest",
"args": [
"${file}"
"${file}",
// "-vv",
// "--headed"
],
"env": {
"PYTHONPATH": "${workspaceFolder}"
},
"console": "integratedTerminal"
"console": "integratedTerminal",
"justMyCode": true
},

{
"name": "Python: Debug Streamlit",
"type": "debugpy",
"request": "launch",
"module": "streamlit",
"args": [
"run",
"example.py",
"${workspaceFolder}/textcomplete/example.py",
"--server.headless=true",
"--browser.gatherUsageStats=false"
],
Expand Down
8 changes: 6 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,12 @@
"statusBarItem.remoteForeground": "#e7e7e7"
},
"peacock.color": "#631661",
"python.defaultInterpreterPath": "/home/voznik/.cache/pypoetry/virtualenvs/streamlit-rxdb-dataframe-zuiqvGqO-py3.10",
"flake8.args": ["--max-line-length=100"],
"flake8.importStrategy": "fromEnvironment",
"black-formatter.args": ["--line-length=100"]
"black-formatter.args": [
"--line-length=100"
],
"python.analysis.extraPaths": [
"./e2e"
]
}
4 changes: 3 additions & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
Copyright (c) 2018-2021 Streamlit Inc.
MIT License

Copyright (c) 2024 VoiceAPI.ai

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ pip install streamlit-textcomplete
To use Streamlit Textcomplete in your Streamlit application, follow these steps:

1. Import the [`textcomplete`] function from the package.
2. Define your autocomplete strategies.
2. Define your autocomplete (multiple) strategies.
3. Define standard streamlit textarea but give it a defined label
4. Initialize the textcomplete component with this label & your strategies.

Expand Down
13 changes: 7 additions & 6 deletions e2e/e2e_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@

import requests


LOGGER = logging.getLogger(__file__)


Expand All @@ -27,8 +26,12 @@ def _find_free_port():
class AsyncSubprocess:
"""A context manager. Wraps subprocess. Popen to capture output safely."""

def __init__(self, args: typing.List[str], cwd: typing.Optional[str] = None,
env: typing.Optional[typing.Dict[str, str]] = None):
def __init__(
self,
args: typing.List[str],
cwd: typing.Optional[str] = None,
env: typing.Optional[typing.Dict[str, str]] = None,
):
"""Initialize an AsyncSubprocess instance.

Args:
Expand Down Expand Up @@ -97,9 +100,7 @@ def stop(self):
class StreamlitRunner:
"""A context manager for running Streamlit scripts."""

def __init__(
self, script_path: os.PathLike, server_port: typing.Optional[int] = None
):
def __init__(self, script_path: os.PathLike, server_port: typing.Optional[int] = None):
"""Initialize a StreamlitRunner instance.

Args:
Expand Down
36 changes: 0 additions & 36 deletions e2e/test_rxdb_dataframe.py

This file was deleted.

52 changes: 52 additions & 0 deletions e2e/test_rxdb_textcomplete.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import json
from pathlib import Path

import pytest
from e2e_utils import StreamlitRunner
from playwright.sync_api import Page, expect

ROOT_DIRECTORY = Path(__file__).parent.parent.absolute()
BASIC_EXAMPLE_FILE = ROOT_DIRECTORY / "textcomplete" / "example.py"


@pytest.fixture(autouse=True, scope="module")
def streamlit_app():
with StreamlitRunner(BASIC_EXAMPLE_FILE, 8502) as runner:
yield runner


@pytest.fixture(autouse=True, scope="function")
def go_to_app(page: Page, streamlit_app: StreamlitRunner):
page.goto(streamlit_app.server_url)
# Wait for app to load
page.get_by_role("img", name="Running...").is_hidden()


def test_should_render_textcomplete(page: Page):
st_text_area = page.get_by_label("Streamlit Autocomplete")
expect(st_text_area).to_be_visible()
# Retrieve the value of the "data-textcomplete" attribute
data_textcomplete_value = st_text_area.get_attribute("data-textcomplete")

# Parse the JSON value
assert isinstance(
json.loads(data_textcomplete_value), dict
), "'data-textcomplete' is not a valid JSON object"

# Append "s" to the textarea to trigger the dropdown
st_text_area.focus()
st_text_area.evaluate("e => e.setSelectionRange(-1, -1)")
st_text_area.type("s")
# Wait for the dropdown to become visible
dropdown = page.query_selector("ul.textcomplete-dropdown")
dropdown.wait_for_element_state("visible")
# Find li element in dropdown
dropdown_li = dropdown.query_selector("li.textcomplete-item")
assert dropdown_li.inner_text() == "🧑🏻 Mrs. Dennis Schulist"
dropdown_li.press("Enter")
dropdown.wait_for_element_state("hidden")
assert st_text_area.input_value() == "Hello, this is textcomplete demo Mrs. Dennis Schulist"
# Append space to the textarea to make original react component state updated
st_text_area.type(" ")
st_text_area.blur()
assert st_text_area.input_value() == "Hello, this is textcomplete demo Mrs. Dennis Schulist "
Loading
Loading