pystata-x 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pystata_x-0.1.0/.coverage +0 -0
- pystata_x-0.1.0/.github/workflows/build-test.yml +89 -0
- pystata_x-0.1.0/.github/workflows/publish.yml +40 -0
- pystata_x-0.1.0/.github/workflows/release.yml +72 -0
- pystata_x-0.1.0/.gitignore +20 -0
- pystata_x-0.1.0/.python-version +1 -0
- pystata_x-0.1.0/CHANGELOG.md +17 -0
- pystata_x-0.1.0/CONTRIBUTING.md +148 -0
- pystata_x-0.1.0/LICENSE +762 -0
- pystata_x-0.1.0/PKG-INFO +168 -0
- pystata_x-0.1.0/README.md +130 -0
- pystata_x-0.1.0/benchmark_cold_init.py +91 -0
- pystata_x-0.1.0/benchmarks/__init__.py +3 -0
- pystata_x-0.1.0/benchmarks/conftest.py +136 -0
- pystata_x-0.1.0/benchmarks/history/benchmark_20260514_091824.json +5 -0
- pystata_x-0.1.0/benchmarks/history/benchmark_20260514_092231.json +69 -0
- pystata_x-0.1.0/benchmarks/history/benchmark_20260514_092529.json +87 -0
- pystata_x-0.1.0/benchmarks/history/benchmark_20260514_092921.json +87 -0
- pystata_x-0.1.0/benchmarks/history/benchmark_20260514_094156.json +87 -0
- pystata_x-0.1.0/benchmarks/run_benchmarks.py +442 -0
- pystata_x-0.1.0/benchmarks/test_benchmark_pystata.py +193 -0
- pystata_x-0.1.0/main.py +12 -0
- pystata_x-0.1.0/pyproject.toml +100 -0
- pystata_x-0.1.0/scripts/maintenance/sync_version.py +65 -0
- pystata_x-0.1.0/src/pystata_x/__init__.py +22 -0
- pystata_x-0.1.0/src/pystata_x/_config.py +292 -0
- pystata_x-0.1.0/src/pystata_x/_core.py +363 -0
- pystata_x-0.1.0/src/pystata_x/stata_setup.py +52 -0
|
Binary file
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
name: Build & Test
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- '*'
|
|
7
|
+
- '**'
|
|
8
|
+
pull_request:
|
|
9
|
+
branches:
|
|
10
|
+
- main
|
|
11
|
+
workflow_dispatch:
|
|
12
|
+
|
|
13
|
+
concurrency:
|
|
14
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
15
|
+
cancel-in-progress: true
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
test:
|
|
19
|
+
name: Test (py${{ matrix.python-version }}, ${{ matrix.os }})
|
|
20
|
+
runs-on: ${{ matrix.os }}
|
|
21
|
+
strategy:
|
|
22
|
+
matrix:
|
|
23
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
24
|
+
python-version: ["3.11", "3.12", "3.13", "3.14"]
|
|
25
|
+
fail-fast: false
|
|
26
|
+
|
|
27
|
+
steps:
|
|
28
|
+
- name: Checkout code
|
|
29
|
+
uses: actions/checkout@v4
|
|
30
|
+
with:
|
|
31
|
+
fetch-depth: 0
|
|
32
|
+
|
|
33
|
+
- name: Setup uv
|
|
34
|
+
uses: astral-sh/setup-uv@v5
|
|
35
|
+
with:
|
|
36
|
+
enable-cache: true
|
|
37
|
+
cache-dependency-glob: "**/uv.lock"
|
|
38
|
+
|
|
39
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
40
|
+
run: uv python install ${{ matrix.python-version }}
|
|
41
|
+
|
|
42
|
+
- name: Install dependencies
|
|
43
|
+
run: |
|
|
44
|
+
uv sync --python ${{ matrix.python-version }} --all-extras --dev
|
|
45
|
+
timeout-minutes: 10
|
|
46
|
+
|
|
47
|
+
- name: Run tests that don't require Stata
|
|
48
|
+
run: |
|
|
49
|
+
uv run pytest -v -m "not requires_stata"
|
|
50
|
+
timeout-minutes: 15
|
|
51
|
+
|
|
52
|
+
- name: Build package
|
|
53
|
+
run: |
|
|
54
|
+
uv build
|
|
55
|
+
timeout-minutes: 5
|
|
56
|
+
|
|
57
|
+
- name: Test installation in clean environment
|
|
58
|
+
shell: bash
|
|
59
|
+
run: |
|
|
60
|
+
# Create fresh venv using the uv-managed Python
|
|
61
|
+
uv run python -m venv test_venv
|
|
62
|
+
|
|
63
|
+
# Activate and install
|
|
64
|
+
if [[ "$RUNNER_OS" == "Windows" ]]; then
|
|
65
|
+
source test_venv/Scripts/activate
|
|
66
|
+
else
|
|
67
|
+
source test_venv/bin/activate
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
# Install built wheel
|
|
71
|
+
pip install dist/*.whl
|
|
72
|
+
|
|
73
|
+
# Test critical imports and version
|
|
74
|
+
python -c "
|
|
75
|
+
import pystata_x
|
|
76
|
+
print(f'[OK] Import successful (v{pystata_x.__version__})')
|
|
77
|
+
assert pystata_x.__version__ == '0.1.0', f'Version mismatch: {pystata_x.__version__}'
|
|
78
|
+
"
|
|
79
|
+
timeout-minutes: 10
|
|
80
|
+
|
|
81
|
+
- name: Upload build artifacts
|
|
82
|
+
if: failure()
|
|
83
|
+
uses: actions/upload-artifact@v4
|
|
84
|
+
with:
|
|
85
|
+
name: build-artifacts-${{ matrix.os }}-py${{ matrix.python-version }}
|
|
86
|
+
path: |
|
|
87
|
+
dist/
|
|
88
|
+
*.log
|
|
89
|
+
retention-days: 7
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
inputs:
|
|
8
|
+
ref:
|
|
9
|
+
description: "Tag or branch to publish"
|
|
10
|
+
required: true
|
|
11
|
+
default: "main"
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
build-and-publish:
|
|
15
|
+
name: Build and publish to PyPI
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
environment:
|
|
18
|
+
name: pypi
|
|
19
|
+
url: https://pypi.org/p/pystata-x
|
|
20
|
+
permissions:
|
|
21
|
+
id-token: write # required for OIDC trusted publishing
|
|
22
|
+
contents: read
|
|
23
|
+
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@v4
|
|
26
|
+
|
|
27
|
+
- name: Setup uv
|
|
28
|
+
uses: astral-sh/setup-uv@v5
|
|
29
|
+
with:
|
|
30
|
+
enable-cache: true
|
|
31
|
+
cache-dependency-glob: "**/uv.lock"
|
|
32
|
+
|
|
33
|
+
- name: Set up Python
|
|
34
|
+
run: uv python install 3.14
|
|
35
|
+
|
|
36
|
+
- name: Build distributions
|
|
37
|
+
run: uv build
|
|
38
|
+
|
|
39
|
+
- name: Publish package distributions to PyPI
|
|
40
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
paths:
|
|
8
|
+
- 'src/**'
|
|
9
|
+
workflow_dispatch:
|
|
10
|
+
|
|
11
|
+
permissions:
|
|
12
|
+
actions: write
|
|
13
|
+
contents: write
|
|
14
|
+
issues: write
|
|
15
|
+
pull-requests: write
|
|
16
|
+
|
|
17
|
+
concurrency:
|
|
18
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
19
|
+
cancel-in-progress: true
|
|
20
|
+
|
|
21
|
+
jobs:
|
|
22
|
+
release:
|
|
23
|
+
name: Release
|
|
24
|
+
runs-on: ubuntu-latest
|
|
25
|
+
steps:
|
|
26
|
+
- name: Checkout
|
|
27
|
+
uses: actions/checkout@v4
|
|
28
|
+
with:
|
|
29
|
+
fetch-depth: 0
|
|
30
|
+
|
|
31
|
+
- name: Setup uv
|
|
32
|
+
uses: astral-sh/setup-uv@v5
|
|
33
|
+
with:
|
|
34
|
+
enable-cache: true
|
|
35
|
+
cache-dependency-glob: "**/uv.lock"
|
|
36
|
+
|
|
37
|
+
- name: Set up Python
|
|
38
|
+
run: uv python install 3.14
|
|
39
|
+
|
|
40
|
+
- name: Install Hatch (version tooling)
|
|
41
|
+
run: uv tool install hatch
|
|
42
|
+
|
|
43
|
+
- name: Install release dependencies
|
|
44
|
+
run: |
|
|
45
|
+
uv sync --python 3.14 --all-extras --dev
|
|
46
|
+
|
|
47
|
+
- name: Sync versions across repo
|
|
48
|
+
run: |
|
|
49
|
+
uv run python scripts/maintenance/sync_version.py
|
|
50
|
+
timeout-minutes: 2
|
|
51
|
+
|
|
52
|
+
- name: Run tests that don't require Stata
|
|
53
|
+
run: uv run pytest -v -m "not requires_stata"
|
|
54
|
+
|
|
55
|
+
- name: Build package
|
|
56
|
+
run: uv build
|
|
57
|
+
|
|
58
|
+
- name: Release
|
|
59
|
+
env:
|
|
60
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
61
|
+
run: uv run semantic-release version
|
|
62
|
+
|
|
63
|
+
- name: Trigger PyPI publish
|
|
64
|
+
uses: actions/github-script@v7
|
|
65
|
+
with:
|
|
66
|
+
script: |
|
|
67
|
+
await github.rest.actions.createWorkflowDispatch({
|
|
68
|
+
owner: context.repo.owner,
|
|
69
|
+
repo: context.repo.repo,
|
|
70
|
+
workflow_id: "publish.yml",
|
|
71
|
+
ref: context.ref
|
|
72
|
+
})
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Python-generated files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[oc]
|
|
4
|
+
build/
|
|
5
|
+
dist/
|
|
6
|
+
wheels/
|
|
7
|
+
*.egg-info
|
|
8
|
+
|
|
9
|
+
# Virtual environments
|
|
10
|
+
.venv
|
|
11
|
+
|
|
12
|
+
# Proprietary StataCorp pystata reference — not for redistribution
|
|
13
|
+
vendor/
|
|
14
|
+
|
|
15
|
+
# Workspace files
|
|
16
|
+
*.log
|
|
17
|
+
.DS_Store
|
|
18
|
+
|
|
19
|
+
# Pi agent state
|
|
20
|
+
.pi/
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.14
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# CHANGELOG
|
|
2
|
+
|
|
3
|
+
<!-- version list -->
|
|
4
|
+
|
|
5
|
+
## v0.1.0 (beta)
|
|
6
|
+
|
|
7
|
+
Initial release of pystata-x — a fast, independent drop-in replacement for StataCorp's pystata.
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
- **Fast command execution**: Direct `StataSO_Execute()` calls bypass the polling-thread bottleneck, delivering ~10,000–20,000× speedup on short commands.
|
|
12
|
+
- **Optimised cold initialisation**: Skips IPython probe, preference-file I/O, Python 2 compat setup, and extraneous wrapper overhead — ~11× faster than the original `stata_setup`.
|
|
13
|
+
- **Vendor-compatible `run()`**: Drop-in for `pystata.run()` with identical signature and behaviour.
|
|
14
|
+
- **`execute()` (fast path)**: Returns `(output, rc)` tuple — not in the vendor API.
|
|
15
|
+
- **`config` module**: Init, status, and settings — mirrors the vendor's `pystata.config`.
|
|
16
|
+
- **Cross-platform**: Shared-library discovery for macOS, Linux, and Windows.
|
|
17
|
+
- **`track_graphs` support**: Bundled graph queries for Stata graphs.
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# Contributing to pystata-x
|
|
2
|
+
|
|
3
|
+
Thank you for your interest in contributing to pystata-x! This guide will help you set up your development environment, run tests, and understand the project structure.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Development Setup](#development-setup)
|
|
8
|
+
- [Building the Project](#building-the-project)
|
|
9
|
+
- [Testing](#testing)
|
|
10
|
+
- [Submitting Changes](#submitting-changes)
|
|
11
|
+
|
|
12
|
+
## Development Setup
|
|
13
|
+
|
|
14
|
+
### Prerequisites
|
|
15
|
+
|
|
16
|
+
- **Stata 17+** (Required for integration tests)
|
|
17
|
+
- **Python 3.11+**
|
|
18
|
+
- **uv** (Recommended) or pip
|
|
19
|
+
|
|
20
|
+
### Installation
|
|
21
|
+
|
|
22
|
+
1. Clone the repository:
|
|
23
|
+
```bash
|
|
24
|
+
git clone https://github.com/tmonk/pystata-x.git
|
|
25
|
+
cd pystata-x
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
2. Install dependencies with uv:
|
|
29
|
+
```bash
|
|
30
|
+
uv sync --dev
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Or with pip:
|
|
34
|
+
```bash
|
|
35
|
+
pip install -e .[dev]
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Building the Project
|
|
39
|
+
|
|
40
|
+
The project uses **hatchling** as the Python build backend. To build wheels:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
uv build
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Or using the build module directly:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
python -m build
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Testing
|
|
53
|
+
|
|
54
|
+
The test suite is organised with pytest markers.
|
|
55
|
+
|
|
56
|
+
### All Tests (Requires Stata)
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
uv run pytest
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Tests Without Stata (Fast/CI)
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
uv run pytest -v -m "not requires_stata"
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Test Coverage
|
|
69
|
+
|
|
70
|
+
Generate a coverage report:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
uv run pytest --cov=pystata_x --cov-report=term-missing
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Or generate an HTML report:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
uv run pytest --cov=pystata_x --cov-report=html
|
|
80
|
+
open htmlcov/index.html # View the report
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Writing Tests
|
|
84
|
+
|
|
85
|
+
When adding new tests:
|
|
86
|
+
|
|
87
|
+
1. **Mark Stata-dependent tests**:
|
|
88
|
+
```python
|
|
89
|
+
import pytest
|
|
90
|
+
|
|
91
|
+
# At module level for all tests
|
|
92
|
+
pytestmark = pytest.mark.requires_stata
|
|
93
|
+
|
|
94
|
+
# Or for individual tests
|
|
95
|
+
@pytest.mark.requires_stata
|
|
96
|
+
def test_my_stata_feature():
|
|
97
|
+
pass
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
2. **Mark slow tests**:
|
|
101
|
+
```python
|
|
102
|
+
@pytest.mark.slow
|
|
103
|
+
def test_expensive_operation():
|
|
104
|
+
pass
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Submitting Changes
|
|
108
|
+
|
|
109
|
+
### Pull Request Process
|
|
110
|
+
|
|
111
|
+
1. **Create a feature branch**:
|
|
112
|
+
```bash
|
|
113
|
+
git checkout -b feature/my-feature
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
2. **Develop and Test**:
|
|
117
|
+
- Add tests in `tests/`.
|
|
118
|
+
- Ensure `pytest -v -m "not requires_stata"` passes.
|
|
119
|
+
|
|
120
|
+
3. **Commit with clear messages**:
|
|
121
|
+
Follow conventional commits (`feat:`, `fix:`, `docs:`, `chore:`, `refactor:`, `perf:`, `test:`).
|
|
122
|
+
|
|
123
|
+
4. **Push and create a pull request**:
|
|
124
|
+
```bash
|
|
125
|
+
git push origin feature/my-feature
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### CI/CD
|
|
129
|
+
|
|
130
|
+
GitHub Actions automatically runs on all PRs:
|
|
131
|
+
- Runs all non-Stata tests (`pytest -v -m "not requires_stata"`)
|
|
132
|
+
- Tests on Ubuntu with Python 3.11–3.14
|
|
133
|
+
- Builds the package and tests entry points
|
|
134
|
+
|
|
135
|
+
## Project Structure
|
|
136
|
+
|
|
137
|
+
- `src/pystata_x/`: Python source code.
|
|
138
|
+
- `tests/`: Test suite.
|
|
139
|
+
- `scripts/`: Utilities for benchmarks and version syncing.
|
|
140
|
+
|
|
141
|
+
## Getting Help
|
|
142
|
+
|
|
143
|
+
- **Issues**: [GitHub Issues](https://github.com/tmonk/pystata-x/issues)
|
|
144
|
+
- **Author**: [Thomas Monk](https://tdmonk.com)
|
|
145
|
+
|
|
146
|
+
## License
|
|
147
|
+
|
|
148
|
+
By contributing to pystata-x, you agree that your contributions will be licensed under the GNU Affero General Public License v3.0.
|