Skip to content

Commit

Permalink
Merge pull request #1 from pharmaverse/main
Browse files Browse the repository at this point in the history
Synchronize changes until v0.1.0
  • Loading branch information
nanxstats authored Jan 13, 2025
2 parents 9a447ac + ebbeb3c commit b2a6594
Show file tree
Hide file tree
Showing 39 changed files with 1,268 additions and 224 deletions.
56 changes: 56 additions & 0 deletions .github/workflows/ci-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
on:
push:
branches:
- main
pull_request:
branches:
- main

name: CI Tests

jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13"]
fail-fast: false

steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
# we are using the -e flag, so that code cov finds the source.
# this is not ideal, since installing an editable can technically
# differ from a normal install in surprising ways.
pip install -e '.[all]'
- name: Test with pytest
run: |
pip install pytest pytest-cov
pytest --cov=pkglite --cov-report=xml
# - name: Upload coverage reports to Codecov
# uses: codecov/codecov-action@v4
# with:
# name: "py${{ matrix.python-version }}"
# token: ${{ secrets.CODECOV_TOKEN }}

test-windows:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.13"
- name: Install dependencies
run: |
pip install -e '.[all]'
- name: Test with pytest
run: |
pip install pytest pytest-cov
pytest --cov=pkglite --cov-report=xml
34 changes: 34 additions & 0 deletions .github/workflows/mkdocs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: mkdocs

on:
push:
branches:
- main

permissions:
contents: write

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Configure Git Credentials
run: |
git config user.name github-actions[bot]
git config user.email 41898282+github-actions[bot]@users.noreply.github.com
- uses: actions/setup-python@v5
with:
python-version: 3.x
- run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV

- uses: actions/cache@v4
with:
key: mkdocs-material-${{ env.cache_id }}
path: .cache
restore-keys: |
mkdocs-material-
- run: pip install mkdocs-material
- run: pip install mkdocstrings-python
- run: mkdocs gh-deploy --force
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,8 @@ dist/
wheels/
*.egg-info

# pytest
.coverage

# venv
.venv
1 change: 1 addition & 0 deletions .python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.13.1
16 changes: 13 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,17 @@

## py-pkglite 0.1.0

### New features
### Typing

- First version.
- Add `CHANGELOG.md` to record changes.
- Refactor type hints to use built-in generics and base abstract classes
following typing best practices (#11).
- Use PEP 604 style shorthand syntax for union and optional types (#10).

### Bug fixes

- Use pathspec to handle ignore pattern matching. This makes the packing
feature work properly under Windows (#7).

### Improvements

- Read and write text files using UTF-8 encoding on all platforms (#7).
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright (c) 2024 Merck & Co., Inc., Rahway, NJ, USA and its affiliates. All rights reserved.
Copyright (c) 2025 Merck & Co., Inc., Rahway, NJ, USA and its affiliates. All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
Expand Down
4 changes: 3 additions & 1 deletion LICENSES_THIRD_PARTY
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ Third party Python packages listed by license type
--------------------------------------------------

MIT License (https://opensource.org/license/mit)
* gitignore-parser - https://github.com/mherrmann/gitignore_parser/blob/master/LICENSE
* rich - https://github.com/Textualize/rich/blob/master/LICENSE
* typer - https://github.com/fastapi/typer/blob/master/LICENSE

Mozilla Public License 2.0 (https://opensource.org/license/mpl-2-0)
* pathspec - https://github.com/cpburnz/python-pathspec/blob/master/LICENSE
103 changes: 20 additions & 83 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,107 +1,44 @@
# pkglite for Python
# pkglite for Python <img src="docs/assets/logo.png" align="right" width="120" />

pkglite for Python provides a simple framework and command line interface for
packing source packages written in any programming language into a text file
and restoring them into the original directory structure.
[![PyPI version](https://img.shields.io/pypi/v/pkglite)](https://pypi.org/project/pkglite/)
![Python versions](https://img.shields.io/pypi/pyversions/pkglite)
[![CI Tests](https://github.com/pharmaverse/py-pkglite/actions/workflows/ci-tests.yml/badge.svg)](https://github.com/pharmaverse/py-pkglite/actions/workflows/ci-tests.yml)
[![mkdocs](https://github.com/pharmaverse/py-pkglite/actions/workflows/mkdocs.yml/badge.svg)](https://pharmaverse.github.io/py-pkglite/)
[![PyPI Downloads](https://img.shields.io/pypi/dm/pkglite)](https://pypistats.org/packages/pkglite)
![License](https://img.shields.io/pypi/l/pkglite)

A simple framework for packing source packages written in any programming
language into a text file and restoring them into the original directory structure.

Beisdes the Python API, a command line interface is also provided.

## Installation

You can install pkglite for Python from PyPI:

```bash
pip3 install pkglite
pip install pkglite
```

Or install the development version from GitHub:

```bash
git clone https://github.com/<placeholder-github-org>/py-pkglite.git
git clone https://github.com/pharmaverse/py-pkglite.git
cd py-pkglite
python3 -m pip install -e .
```

## Usage

### CLI

Single directory:

```bash
# Create a .pkgliteignore file to exclude files from packing
pkglite use path/to/pkg

# Pack a single directory into a text file
pkglite pack path/to/pkg -o path/to/pkg.txt

# Unpack the text file into a directory
pkglite unpack path/to/pkg.txt -o path/to/output
```

Multiple directories:

```bash
# Create a .pkgliteignore file to exclude files from packing
pkglite use path/to/pkg1 path/to/pkg2

# Pack multiple directories into a text file
pkglite pack path/to/pkg1 path/to/pkg2 -o path/to/pkgs.txt

# Unpack the text file into multiple directories under `output/`
pkglite unpack path/to/pkgs.txt -o path/to/output
```

Run `pkglite --help`, `pkglite use --help`, `pkglite pack --help`,
or `pkglite unpack --help` for more information about the available
subcommands and options.

To install the command line tool globally,
[use pipx](https://packaging.python.org/en/latest/guides/installing-stand-alone-command-line-tools/).

### Python API

Single directory:

```python
from pkglite import use_pkglite, pack, unpack

dirs = ["path/to/pkg"]
txt = "path/to/pkg.txt"
use_pkglite(dirs)
pack(dirs, output_file=txt)
unpack(txt, output_dir="path/to/output")
```

Multiple directories:

```python
from pkglite import use_pkglite, pack, unpack

dirs = ["path/to/pkg1", "path/to/pkg2"]
txt = "path/to/pkgs.txt"
use_pkglite(dirs)
pack(dirs, output_file=txt)
unpack(txt, output_dir="path/to/output")
```

## Why pkglite for Python?

Building on our experience with [r-pkglite](https://cran.r-project.org/package=pkglite),
we identified several limitations and unmet needs:

- **Broader scope**: Extend support for packing and unpacking packages
across any programming language, without R-specific assumptions.
- **Optimized tooling**: Simplify packing logic by classifying files
based on content rather than file extensions.
- **Engineering-friendly interface**: Besides the language-specific API,
provide a command-line interface (CLI) to better integrate with
standard engineering workflows.
## Usage

We made a few key design changes from r-pkglite to implement the above goals:
Check out the [getting
started](https://pharmaverse.github.io/py-pkglite/articles/get-started/)
article for the CLI and Python API usage.

- Introduced a `.pkgliteignore` configuration file to control packing scope,
following the gitignore standard.
- Adopted content-based file type classification for unsupervised file discovery.
- Built in Python for better flexibility and accessibility.
See the [design](https://pharmaverse.github.io/py-pkglite/articles/design/)
article about the rationale for this package.

## License

Expand Down
24 changes: 24 additions & 0 deletions docs/articles/design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Why pkglite for Python?

## Differentiators

Building on our experience developing pkglite for R, we resolved several
longstanding, unmet needs with pkglite for Python:

- **Broader scope**. Extend support for packing and unpacking packages
across **any** programming language, without R-specific assumptions.
- **Optimized tooling**. Simplify packing logic by classifying files
based on content rather than file extensions.
UTF-8 in and UTF-8 out for all text files on all platforms.
- **Engineering-friendly interface**. Besides the language-specific API,
provide a command-line interface (CLI) to better integrate with
standard engineering workflows.

## Design choices

We made a few key design changes from pkglite for R to implement the above goals:

- Introduced a `.pkgliteignore` configuration file to control packing scope,
following the gitignore standard.
- Adopted content-based file type classification for unsupervised file discovery.
- Built with Python for better flexibility and accessibility.
83 changes: 83 additions & 0 deletions docs/articles/get-started.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Get started


<!-- `.md` and `.py` files are generated from the `.qmd` file. Please edit that file. -->

!!! tip

To run the code from this article as a Python script:

```bash
python3 examples/get-started.py
```

## Python API

Import pkglite:

``` python
import pkglite as pkg
```

### Single directory

Pack a single directory into a text file and unpack it:

``` python
dirs = ["path/to/pkg"]
txt = "path/to/pkg.txt"
pkg.use_pkglite(dirs)
pkg.pack(dirs, output_file=txt)
pkg.unpack(txt, output_dir="path/to/output")
```

### Multiple directories

Pack multiple directories into a text file and unpack it:

``` python
dirs = ["path/to/pkg1", "path/to/pkg2"]
txt = "path/to/pkgs.txt"
pkg.use_pkglite(dirs)
pkg.pack(dirs, output_file=txt)
pkg.unpack(txt, output_dir="path/to/output")
```

The `use_pkglite()` function creates a `.pkgliteignore` file to exclude
files from the packing scope.

## Command line interface

### Single directory

Pack a single directory into a text file and unpack it:

``` bash
pkglite use path/to/pkg
pkglite pack path/to/pkg -o path/to/pkg.txt
pkglite unpack path/to/pkg.txt -o path/to/output
```

### Multiple directories

Pack multiple directories into a text file and unpack it:

``` bash
pkglite use path/to/pkg1 path/to/pkg2
pkglite pack path/to/pkg1 path/to/pkg2 -o path/to/pkgs.txt
pkglite unpack path/to/pkgs.txt -o path/to/output
```

The `pkglite use` subcommand creates a `.pkgliteignore` file to exclude
files from the packing scope.

Run

``` bash
pkglite --help
pkglite use --help
pkglite pack --help
pkglite unpack --help
```

for more information about the available subcommands and their options.
Loading

0 comments on commit b2a6594

Please sign in to comment.