1
0
Fork 0

Adding upstream version 1.13.2.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-09 17:56:09 +01:00
parent 277294eb9f
commit 0982975b25
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
6 changed files with 146 additions and 30 deletions

View file

@ -1,3 +1,15 @@
## 1.13.2 - 2024-11-24
### Internal
* Read the version from the git tag using setuptools-scm
## 1.13.0 - 2024-11-23
### Features
* Add `\pipe_once` / `\|` commands for sending output to a command
## 1.12.4 - 2024-11-11
### Bug Fixes

View file

@ -1 +1,3 @@
__version__ = "1.12.4"
import importlib.metadata
__version__ = importlib.metadata.version("litecli")

View file

@ -472,6 +472,7 @@ class LiteCli(object):
result_count += 1
mutating = mutating or is_mutating(status)
special.unset_once_if_written()
special.unset_pipe_once_if_written()
except EOFError as e:
raise e
except KeyboardInterrupt:
@ -658,6 +659,7 @@ class LiteCli(object):
self.log_output(line)
special.write_tee(line)
special.write_once(line)
special.write_pipe_once(line)
if fits or output_via_pager:
# buffering
@ -824,7 +826,7 @@ class LiteCli(object):
@click.command()
@click.option("-V", "--version", is_flag=True, help="Output litecli's version.")
@click.version_option(__version__, "-V", "--version")
@click.option("-D", "--database", "dbname", help="Database to use.")
@click.option(
"-R",
@ -857,7 +859,6 @@ class LiteCli(object):
def cli(
database,
dbname,
version,
prompt,
logfile,
auto_vertical_output,
@ -874,11 +875,6 @@ def cli(
- litecli lite_database
"""
if version:
print("Version:", __version__)
sys.exit(0)
litecli = LiteCli(
prompt=prompt,
logfile=logfile,

View file

@ -21,7 +21,10 @@ from litecli.packages.prompt_utils import confirm_destructive_query
use_expanded_output = False
PAGER_ENABLED = True
tee_file = None
once_file = once_file_args = written_to_once_file = None
once_file = None
written_to_once_file = None
pipe_once_process = None
written_to_pipe_once_process = False
favoritequeries = FavoriteQueries(ConfigObj())
@ -376,9 +379,12 @@ def write_tee(output):
aliases=("\\o", "\\once"),
)
def set_once(arg, **_):
global once_file_args
once_file_args = parseargfile(arg)
global once_file, written_to_once_file
try:
once_file = open(**parseargfile(arg))
except (IOError, OSError) as e:
raise OSError("Cannot write to file '{}': {}".format(e.filename, e.strerror))
written_to_once_file = False
return [(None, None, None, "")]
@ -386,26 +392,66 @@ def set_once(arg, **_):
@export
def write_once(output):
global once_file, written_to_once_file
if output and once_file_args:
if once_file is None:
try:
once_file = open(**once_file_args)
except (IOError, OSError) as e:
once_file = None
raise OSError("Cannot write to file '{}': {}".format(e.filename, e.strerror))
if output and once_file:
click.echo(output, file=once_file, nl=False)
click.echo("\n", file=once_file, nl=False)
once_file.flush()
written_to_once_file = True
@export
def unset_once_if_written():
"""Unset the once file, if it has been written to."""
global once_file, once_file_args, written_to_once_file
global once_file, written_to_once_file
if once_file and written_to_once_file:
once_file.close()
once_file = once_file_args = written_to_once_file = None
once_file = written_to_once_file = None
@special_command("\\pipe_once", "\\| command", "Send next result to a subprocess.", aliases=("\\|",))
def set_pipe_once(arg, **_):
global pipe_once_process, written_to_pipe_once_process
pipe_once_cmd = shlex.split(arg)
if len(pipe_once_cmd) == 0:
raise OSError("pipe_once requires a command")
written_to_pipe_once_process = False
pipe_once_process = subprocess.Popen(
pipe_once_cmd,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
bufsize=1,
encoding="UTF-8",
universal_newlines=True,
)
return [(None, None, None, "")]
@export
def write_pipe_once(output):
global pipe_once_process, written_to_pipe_once_process
if output and pipe_once_process:
try:
click.echo(output, file=pipe_once_process.stdin, nl=False)
click.echo("\n", file=pipe_once_process.stdin, nl=False)
except (IOError, OSError) as e:
pipe_once_process.terminate()
raise OSError("Failed writing to pipe_once subprocess: {}".format(e.strerror))
written_to_pipe_once_process = True
@export
def unset_pipe_once_if_written():
"""Unset the pipe_once cmd, if it has been written to."""
global pipe_once_process, written_to_pipe_once_process
if written_to_pipe_once_process:
(stdout_data, stderr_data) = pipe_once_process.communicate()
if len(stdout_data) > 0:
print(stdout_data.rstrip("\n"))
if len(stderr_data) > 0:
print(stderr_data.rstrip("\n"))
pipe_once_process = None
written_to_pipe_once_process = False
@special_command(

View file

@ -4,10 +4,8 @@ dynamic = ["version"]
description = "CLI for SQLite Databases with auto-completion and syntax highlighting."
readme = "README.md"
requires-python = ">=3.7"
license = {text = "BSD"}
authors = [
{name = "dbcli", email = "litecli-users@googlegroups.com"}
]
license = { text = "BSD" }
authors = [{ name = "dbcli", email = "litecli-users@googlegroups.com" }]
urls = { "homepage" = "https://github.com/dbcli/litecli" }
dependencies = [
"cli-helpers[styles]>=2.2.1",
@ -19,9 +17,15 @@ dependencies = [
]
[build-system]
requires = ["setuptools >= 61.0"]
requires = [
"setuptools>=64.0",
"setuptools-scm>=8;python_version>='3.8'",
"setuptools-scm<8;python_version<'3.8'",
]
build-backend = "setuptools.build_meta"
[tool.setuptools_scm]
[project.scripts]
litecli = "litecli.main:cli"
@ -42,8 +46,5 @@ exclude = ["screenshots", "tests*"]
[tool.setuptools.package-data]
litecli = ["liteclirc", "AUTHORS"]
[tool.setuptools.dynamic]
version = {attr = "litecli.__version__"}
[tool.ruff]
line-length = 140

View file

@ -0,0 +1,59 @@
import os
import tempfile
import pytest
import litecli.packages.special
def test_once_command():
with pytest.raises(TypeError):
litecli.packages.special.execute(None, ".once")
with pytest.raises(OSError):
litecli.packages.special.execute(None, ".once /proc/access-denied")
litecli.packages.special.write_once("hello world") # write without file set
# keep Windows from locking the file with delete=False
with tempfile.NamedTemporaryFile(delete=False) as f:
litecli.packages.special.execute(None, ".once " + f.name)
litecli.packages.special.write_once("hello world")
if os.name == "nt":
assert f.read() == b"hello world\r\n"
else:
assert f.read() == b"hello world\n"
litecli.packages.special.execute(None, ".once -o " + f.name)
litecli.packages.special.write_once("hello world line 1")
litecli.packages.special.write_once("hello world line 2")
f.seek(0)
if os.name == "nt":
assert f.read() == b"hello world line 1\r\nhello world line 2\r\n"
else:
assert f.read() == b"hello world line 1\nhello world line 2\n"
# delete=False means we should try to clean up
try:
if os.path.exists(f.name):
os.remove(f.name)
except Exception as e:
print(f"An error occurred while attempting to delete the file: {e}")
def test_pipe_once_command():
with pytest.raises(IOError):
litecli.packages.special.execute(None, "\\pipe_once")
with pytest.raises(OSError):
litecli.packages.special.execute(None, "\\pipe_once /proc/access-denied")
if os.name == "nt":
litecli.packages.special.execute(None, '\\pipe_once python -c "import sys; print(len(sys.stdin.read().strip()))"')
litecli.packages.special.write_pipe_once("hello world")
litecli.packages.special.unset_pipe_once_if_written()
else:
with tempfile.NamedTemporaryFile() as f:
litecli.packages.special.execute(None, "\\pipe_once tee " + f.name)
litecli.packages.special.write_pipe_once("hello world")
litecli.packages.special.unset_pipe_once_if_written()
f.seek(0)
assert f.read() == b"hello world\n"