This repository has been archived by the owner on Jul 31, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: initial commit for qsv-duct, v0.0.1
- Loading branch information
0 parents
commit 8e6b113
Showing
14 changed files
with
34,678 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
name: Publish qsv-duct distribution to PyPI | ||
|
||
on: | ||
release: | ||
types: [created] | ||
|
||
jobs: | ||
build: | ||
name: Build distribution | ||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- uses: actions/checkout@v4 | ||
- name: Set up Python | ||
uses: actions/setup-python@v5 | ||
with: | ||
python-version: "3.x" | ||
- name: Install pypa/build | ||
run: >- | ||
python3 -m | ||
pip install | ||
build | ||
--user | ||
- name: Build a binary wheel and a source tarball | ||
run: python3 -m build | ||
- name: Store the distribution packages | ||
uses: actions/upload-artifact@v3 | ||
with: | ||
name: python-package-distributions | ||
path: dist/ | ||
|
||
publish-to-pypi: | ||
name: Publish qsv-duct distribution to PyPI | ||
needs: | ||
- build | ||
runs-on: ubuntu-latest | ||
environment: | ||
name: pypi | ||
url: https://pypi.org/p/qsv-duct # Replace <package-name> with your PyPI project name | ||
permissions: | ||
id-token: write # IMPORTANT: mandatory for trusted publishing | ||
|
||
steps: | ||
- name: Download all the dists | ||
uses: actions/download-artifact@v3 | ||
with: | ||
name: python-package-distributions | ||
path: dist/ | ||
- name: Publish qsv-duct distribution to PyPI | ||
uses: pypa/gh-action-pypi-publish@release/v1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
__pycache__ | ||
.pytest_cache | ||
.venv | ||
dist |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
# qsv-duct | ||
|
||
Python wrapper you may use to call [qsv](https://github.com/jqnatividad/qsv) commands using [duct.py](https://github.com/oconnor663/duct.py) for composability. | ||
|
||
This library is compatible with qsv v0.128.0. Not all commands are available. | ||
|
||
**Make sure you have qsv installed on your system first and can access it anywhere as a `PATH` command.** | ||
|
||
To install this library run: | ||
|
||
```bash | ||
pip install qsv-duct | ||
``` | ||
|
||
## Basic example | ||
|
||
We have a file `fruits.csv` with the following contents: | ||
|
||
```csv | ||
fruit,price | ||
apple,2.50 | ||
banana,3.00 | ||
carrot,1.50 | ||
``` | ||
|
||
Let's count the total number of non-header rows in `fruits.csv` using `qsv.count`: | ||
|
||
```python | ||
import qsv | ||
|
||
qsv.count("fruits.csv", run=True) | ||
``` | ||
|
||
The following output gets printed to stdout: | ||
|
||
```console | ||
3 | ||
``` | ||
|
||
## Reading output to a variable | ||
|
||
You may want to save the output value to a variable and use it in your code. Use the `read` parameter instead of `run`. For example: | ||
|
||
```python | ||
non_header_row_count = qsv.count("fruits.csv", read=True) | ||
print(non_header_row_count) | ||
``` | ||
|
||
## Piping commands | ||
|
||
Since this library uses duct.py, you may access the command as an `Expression` type by not passing `read` and `run`. | ||
|
||
For example, let's say we want to get the first two rows of `fruits.csv` with `qsv.slice`. Normally we would use `run` to run the command: | ||
|
||
```python | ||
qsv.slice("fruits.csv", length=2, run=True) | ||
``` | ||
|
||
```console | ||
fruit,price | ||
apple,2.50 | ||
banana,3.00 | ||
``` | ||
|
||
If we want to display this output in a pretty format, we can pipe `qsv.slice` into `qsv.table`: | ||
|
||
```python | ||
qsv.slice("fruits.csv", length=2).pipe(qsv.table()).run() | ||
``` | ||
|
||
```console | ||
fruit price | ||
apple 2.50 | ||
banana 3.00 | ||
``` | ||
|
||
If you use the `duct.py` library you can also pipe qsv commands with other bash-related commands using the `duct` library's `cmd` function. For example: | ||
|
||
```bash | ||
import qsv | ||
from duct import cmd | ||
|
||
cmd("cat", "fruits.csv").pipe(qsv.table()).run() | ||
``` | ||
|
||
```console | ||
fruit price | ||
apple 2.50 | ||
banana 3.00 | ||
carrot 1.50 | ||
``` | ||
|
||
## Testing | ||
|
||
You can run the tests with the pytest package: | ||
|
||
```bash | ||
pytest | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
[build-system] | ||
requires = ["flit_core >=3.2,<4"] | ||
build-backend = "flit_core.buildapi" | ||
|
||
[project] | ||
name = "qsv-duct" | ||
authors = [{name = "Mueez Khan"}] | ||
readme = "README.md" | ||
dynamic = ["version", "description"] | ||
keywords = ["qsv", "csv"] | ||
dependencies = ["duct"] | ||
|
||
[tool.flit.module] | ||
name = "qsv" | ||
|
||
[project.urls] | ||
Home = "https://github.com/rzmk/qsv-duct" | ||
|
||
[project.optional-dependencies] | ||
test = [ | ||
"pytest" | ||
] | ||
|
||
[tool.flit.sdist] | ||
exclude = ["**/__pycache__", ".venv"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
duct |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
"""Python wrapper based on the qsv CLI tool""" | ||
|
||
__version__ = "0.0.1" | ||
|
||
from .count import count, CountBuilder | ||
from .sample import sample | ||
from .slice import slice | ||
from .table import table |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
from duct import cmd, Expression | ||
|
||
|
||
def count( | ||
file_path: str = "-", | ||
run: bool = False, | ||
read: bool = False, | ||
include_header_row: bool = False, | ||
human_readable: bool = False, | ||
width: bool = False, | ||
): | ||
""" | ||
# qsv count | ||
Returns a count of the number of records in the CSV data. | ||
Note that the count will not include the header row | ||
unless the `include_header_row` parameter/method is used. | ||
## Examples | ||
Assume we have a file `fruits.csv` with the following content: | ||
```csv | ||
fruit,price | ||
apple,2.50 | ||
banana,3.00 | ||
carrot,1.50 | ||
``` | ||
### Get non-header row count and print to stdout | ||
```python | ||
qsv.count("fruits.csv").run() | ||
# or | ||
qsv.count("fruits.csv", run=True) | ||
``` | ||
Output: | ||
```console | ||
3 | ||
``` | ||
### Get non-header row count and read to variable | ||
```python | ||
row_count = qsv.count("fruits.csv").read() | ||
# or | ||
row_count = qsv.count("fruits.csv", read=True) | ||
``` | ||
### Get row count including header row and print to stdout | ||
```python | ||
qsv.count("fruits.csv").include_header_row().run() | ||
# or | ||
qsv.count("fruits.csv", include_header_row=True, run=True) | ||
``` | ||
Output: | ||
```console | ||
4 | ||
``` | ||
Args: | ||
file_path (str): The file to run `qsv count` on. | ||
run (bool, optional): Execute the command without returning its output. Defaults to False. | ||
read (bool, optional): Execute the command and return its output. Defaults to False. | ||
include_header_row (bool, optional): Include the header row (first row) in the row count. Defaults to False. | ||
human_readable (bool, optional): Comma separate row count. Defaults to False. | ||
width (bool, optional): Also return the estimated length of the longest record. Defaults to False. | ||
""" | ||
|
||
args = [] | ||
if include_header_row: | ||
args.append("-n") | ||
if human_readable: | ||
args.append("-H") | ||
if width: | ||
args.append("--width") | ||
|
||
count_cmd = cmd("qsv", "count", file_path, *args) | ||
|
||
if run: | ||
return count_cmd.run() | ||
if read: | ||
return count_cmd.read() | ||
return count_cmd | ||
|
||
|
||
class CountBuilder(Expression): | ||
def __init__(self): | ||
self.file_path: str | None = None | ||
self.args = [] | ||
|
||
def file(self, file_path: str): | ||
""" | ||
The file to run `qsv count` on. | ||
""" | ||
self.file_path = file_path | ||
return self | ||
|
||
def include_header_row(self): | ||
""" | ||
Include the header row (first row) in the row count. | ||
""" | ||
self.args.append("-n") | ||
return self | ||
|
||
def human_readable(self): | ||
""" | ||
Comma separate row count. | ||
""" | ||
self.args.append("-H") | ||
return self | ||
|
||
def width(self): | ||
""" | ||
Also return the estimated length of the longest record. | ||
""" | ||
self.args.append("--width") | ||
return self | ||
|
||
def run(self): | ||
""" | ||
Execute the command without returning its output. | ||
""" | ||
if not self.file_path: | ||
return None | ||
return cmd("qsv", "count", self.file_path, *self.args).run() | ||
|
||
def read(self): | ||
""" | ||
Execute the command and return its output. | ||
""" | ||
return cmd("qsv", "count", self.file_path, *self.args).read() |
Oops, something went wrong.