Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Python 3.6+ #13

Merged
merged 27 commits into from
May 16, 2024
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
5413053
Add minimal setup.py
janbridley May 10, 2024
dd31f29
Switch dataclass to namedtuple
janbridley May 10, 2024
c256e69
Fix typing for python < 3.7
janbridley May 10, 2024
5384645
Split tests into two blocks
janbridley May 10, 2024
258103a
Add required workflow steps
janbridley May 10, 2024
cc4cb60
pip install -r
janbridley May 10, 2024
05393d8
Add pytest to reqs
janbridley May 10, 2024
32984ad
Rename CI features
janbridley May 10, 2024
0646b07
Properly implement workflow_call procedure
janbridley May 10, 2024
f4c5a6d
Remove incorrect runs_on key
janbridley May 10, 2024
805c151
Rename action
janbridley May 10, 2024
dccbd6d
Fix syntax in CI
janbridley May 10, 2024
1321804
Set legacy tests to run after modern versions pass
janbridley May 10, 2024
9275e93
Clean up CI script
janbridley May 10, 2024
157286c
Clean up action names
janbridley May 10, 2024
3e346fa
Parameterize runs-on
janbridley May 11, 2024
c24fc58
Add runs-on input to workflow callable
janbridley May 11, 2024
0b99c43
Move python 3.6 tests to ubuntu 20.04
janbridley May 11, 2024
4306088
Test python 3.5
janbridley May 11, 2024
266d574
Remove broken python 3.5
janbridley May 11, 2024
f939f64
Update install files
janbridley May 11, 2024
d4f3fdd
Merge branch 'main' into feature/#10-support-python-3.6
janbridley May 13, 2024
adabd29
Swapped requirements.txt with requirements.in
janbridley May 16, 2024
6ba81a6
Swapped tests requirements.txt with requirements.in
janbridley May 16, 2024
20b4554
Added legacy test requirements file
janbridley May 16, 2024
a81bb51
Fixed pin and reran pip-compile on python 3.6
janbridley May 16, 2024
9dcd291
Set default value for requirements-file
janbridley May 16, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 21 additions & 31 deletions .github/workflows/CI.yaml
Original file line number Diff line number Diff line change
@@ -1,45 +1,35 @@
name: Run Tests

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

on:
# trigger on pull requests
pull_request:

# trigger on all commits to master
push:
branches:
- "main"
- "breaking"

# trigger on request
workflow_dispatch:


jobs:
run_tests:
name: Run tests on ubuntu-latest with Python ${{ matrix.python-version }}
runs-on: ubuntu-latest
run-tests-modern-python:
strategy:
fail-fast: true
matrix:
python-version: ["3.9", "3.10", "3.11", "3.12"]
runs-on: ["ubuntu-latest"]
# Pull in the test script from run_tests and distribute python from matrix versions
uses: ./.github/workflows/run_tests.yaml
with:
python-version: ${{ matrix.python-version }}
runs-on: ${{ matrix.runs-on }}

run-tests-legacy-python:
needs: run-tests-modern-python # Wait until tests pass on python 3.9+
strategy:
fail-fast: true
matrix:
python-version: ["3.9","3.10","3.11","3.12"]
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: |
python -m pip install requirements.txt
python -m pip install tests/requirements.txt
- name: Install package
run: |
python --version
python -c "import numpy; print('numpy', numpy.__version__)"
python -m pip install . -v --progress-bar off
- name: Test with pytest
run: |
python -m pytest -v
python-version: ["3.6", "3.7", "3.8"]
runs-on: ["ubuntu-20.04"]
uses: ./.github/workflows/run_tests.yaml
with:
python-version: ${{ matrix.python-version }}
runs-on: ${{ matrix.runs-on }}
34 changes: 34 additions & 0 deletions .github/workflows/run_tests.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: Run tests

on:
workflow_call:
inputs:
python-version:
required: true
type: string
runs-on:
required: true
type: string

jobs:
run_test:
runs-on: ${{ inputs.runs-on }}
steps:
# Steps common to both groups
- uses: actions/checkout@v4
- name: Set up Python ${{ inputs.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ inputs.python-version }}
- name: Install dependencies
run: |
python -m pip install -r requirements.txt
python -m pip install -r tests/requirements.txt
- name: Install package
run: |
python --version
python -m pip install . -v --progress-bar off
python -c "import parsnip; print('parsnip', parsnip.__version__)"
- name: Test with pytest
run: |
python -m pytest -v
11 changes: 5 additions & 6 deletions parsnip/parse.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
"""CIF parsing tools."""

import warnings

import numpy as np
Expand All @@ -15,9 +14,9 @@ def _remove_comments_from_line(line):
def read_table(
filename: str,
keys: str,
filter_line: tuple[tuple[str, str]] = ((r",\s+", ",")),
filter_line: tuple = ((r",\s+", ",")),
keep_original_key_order=False,
) -> np.ndarray[str]:
) -> np.ndarray:
r"""Extract data from a CIF file loop_ table.

CIF files store tabular data as whitespace-delimited blocks that start with `loop_`.
Expand Down Expand Up @@ -61,7 +60,7 @@ def read_table(
Args:
filename (str): The name of the .cif file to be parsed.
keys (tuple[str]): The names of the keys to be parsed.
filter_line (tuple[tuple[str]], optional):
filter_line (tuple[tuple[str,str]], optional):
A tuple of strings that are compiled to a regex filter and applied to each
data line. (Default value: ((r",\s+",",")) )
keep_original_key_order (bool, optional):
Expand Down Expand Up @@ -146,13 +145,13 @@ def read_table(

def read_fractional_positions(
filename: str,
filter_line: tuple[tuple[str, str]] = ((r",\s+", ",")),
filter_line: tuple = ((r",\s+", ",")),
):
r"""Extract the fractional X,Y,Z coordinates from a CIF file.

Args:
filename (str): The name of the .cif file to be parsed.
filter_line (tuple[tuple[str]], optional):
filter_line (tuple[tuple[str,str]], optional):
A tuple of strings that are compiled to a regex filter and applied to each
data line. (Default value: ((r",\s+",",")) )

Expand Down
6 changes: 3 additions & 3 deletions parsnip/patterns.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
_comma_prune_spaces = re.compile(r",\s+")


def compile_pattern_from_strings(filter_patterns: tuple[str]):
def compile_pattern_from_strings(filter_patterns: tuple):
"""Return a regex pattern that matches any of the characters in the filter.

Args:
filter_patterns (list[str]): Description
filter_patterns (tuple[str]): Description

Returns:
re.Pattern: Pattern matching any of the input characters.
Expand Down Expand Up @@ -46,7 +46,7 @@ class LineCleaner:
what that pattern will be replaced with.
"""

def __init__(self, patterns: tuple[tuple[str, str]]):
def __init__(self, patterns: tuple):
self.patterns, self.replacements = [], []

# If we only have a single tuple
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "parsnip"
version = "0.0.2"
requires-python = ">=3.9"
requires-python = ">=3.6"
description = "Minimal library for parsing CIF/mmCIF files in Python."
readme = "README.md"
license = { file = "LICENSE" }
Expand Down
4 changes: 4 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# ruff: noqa: D100
from setuptools import setup

setup(name="parsnip")
10 changes: 2 additions & 8 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
import dataclasses
import os
from collections import namedtuple

import pytest

# ruff: noqa: N816. Allow mixed-case global variables


@dataclasses.dataclass
class CifData:
"""Class to hold the filename and stored keys for a CIF file."""

filename: str
symop_keys: tuple[str]
atom_site_keys: tuple[str]
CifData = namedtuple("CifData", ["filename", "symop_keys", "atom_site_keys"])


box_keys = (
Expand Down
1 change: 1 addition & 0 deletions tests/requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
gemmi
pytest
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To make CI tests more reproducible, you should pin specific versions of packages in requirements.in, then use pip-compile to generate requirements.txt that pins all transitive dependencies. That way, an update to a transitive dependency is less likely to cause CI failures from one build to the next with no changes to parsnip. Readthedocs has a nice write up: https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html#pin-your-transitive-dependencies

Dependabot knows how to update requirements.in and rerun pip-compile. Add pip to the dependabot config and you will get PRs that test the updated pins: https://github.com/glotzerlab/gsd/blob/trunk-patch/.github/dependabot.yml