more diagnostics #5
Workflow file for this run
This file contains hidden or 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
| name: CI Tests | |
| on: [push, pull_request] | |
| jobs: | |
| test: | |
| name: Test ${{ matrix.os }} | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest, ubuntu-22.04, macos-latest, windows-2022] | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.13" | |
| - name: Install Linux dependencies | |
| if: runner.os == 'Linux' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y zlib1g-dev | |
| - name: Build Windows Libraries | |
| if: runner.os == 'Windows' | |
| uses: ./.github/actions/windows_actions | |
| - name: Install Python dependencies | |
| run: | | |
| pip install cython setuptools numpy narwhals | |
| pip install pandas polars | |
| pip install pytest mypy pytest-mypy-plugins pandas-stubs | |
| - name: Install package | |
| run: pip install . | |
| - name: Diagnose value labels | |
| if: runner.os == 'Linux' | |
| working-directory: /tmp | |
| run: | | |
| python -c " | |
| import pyreadstat, pandas as pd, tempfile, os, subprocess, struct, ctypes, ctypes.util | |
| print('=== Environment ===') | |
| print('pyreadstat location:', pyreadstat.__file__) | |
| import sysconfig; print('CC:', sysconfig.get_config_var('CC')) | |
| import platform; print('glibc:', platform.libc_ver()) | |
| # Check linked libraries of the .so | |
| so_dir = os.path.dirname(pyreadstat.__file__) | |
| for f in os.listdir(so_dir): | |
| if '_readstat_parser' in f and f.endswith('.so'): | |
| so_path = os.path.join(so_dir, f) | |
| print(f'\n=== ldd {f} ===') | |
| subprocess.run(['ldd', so_path]) | |
| break | |
| # Check iconv availability | |
| print('\n=== iconv check ===') | |
| libc = ctypes.CDLL(ctypes.util.find_library('c')) | |
| try: | |
| conv = libc.iconv_open(b'UTF-8', b'UTF-8') | |
| print(f'iconv_open(UTF-8, UTF-8) = {conv} (should be != -1)') | |
| if conv != -1: | |
| libc.iconv_close(conv) | |
| except Exception as e: | |
| print(f'iconv_open failed: {e}') | |
| # Test write + read value labels | |
| df = pd.DataFrame({'x': [1.0, 2.0], 'y': ['a', 'b']}) | |
| path = os.path.join(tempfile.gettempdir(), 'diag_labels.sav') | |
| vvl = {'x': {1.0: 'Male', 2.0: 'Female'}} | |
| pyreadstat.write_sav(df, path, variable_value_labels=vvl) | |
| df2, meta = pyreadstat.read_sav(path) | |
| print('\n=== Read-back results ===') | |
| print('variable_value_labels:', meta.variable_value_labels) | |
| print('value_labels (raw):', meta.value_labels) | |
| print('variable_to_label:', meta.variable_to_label) | |
| # Existing file test | |
| checkout = os.environ.get('GITHUB_WORKSPACE', '') | |
| test_sav = os.path.join(checkout, 'test_data', 'basic', 'sample.sav') | |
| if os.path.exists(test_sav): | |
| _, meta2 = pyreadstat.read_sav(test_sav) | |
| print(f'\n=== Existing file ===') | |
| print('variable_value_labels:', meta2.variable_value_labels) | |
| # Dump file structure (record types) | |
| with open(path, 'rb') as f: | |
| data = f.read() | |
| print(f'\n=== Written file: {len(data)} bytes ===') | |
| print('First 64 bytes hex:', data[:64].hex()) | |
| print('Bytes 176-260 hex:', data[176:260].hex()) | |
| # Parse SAV record types sequentially | |
| pos = 176 # after header | |
| for i in range(10): | |
| if pos + 4 > len(data): break | |
| rt = struct.unpack('<I', data[pos:pos+4])[0] | |
| print(f' offset {pos}: record_type={rt}, next 16 bytes: {data[pos:pos+16].hex()}') | |
| if rt == 999: break | |
| pos += 4 | |
| # skip based on record type | |
| if rt == 2: # variable record | |
| pos += 28 # rest of fixed part | |
| elif rt == 3: # value label | |
| lc = struct.unpack('<I', data[pos:pos+4])[0] | |
| print(f' label_count={lc}') | |
| break | |
| elif rt == 7: # extension | |
| pos += 8 # subtype + size + count header | |
| else: | |
| break | |
| " | |
| - name: Run basic tests | |
| run: python tests/test_basic.py | |
| - name: Run narwhals pandas tests | |
| run: python tests/test_narwhalified.py --backend=pandas | |
| - name: Run narwhals polars tests | |
| run: python tests/test_narwhalified.py --backend=polars | |
| - name: Run HTTP integration tests | |
| run: python tests/test_http_integration.py | |
| - name: Run runtime type tests | |
| run: python tests/test_runtime_types.py | |
| - name: Run typing tests | |
| run: pytest tests/test_typing.yml --mypy-ini-file=tests/test_mypy_setup.ini |