From 8e1dc0583fe1eabce7f5a9b034eb5354caf3aefe Mon Sep 17 00:00:00 2001 From: alisterburt Date: Tue, 16 Jan 2024 08:56:01 +0000 Subject: [PATCH] move to pyproject.toml based setup (#43) * move to pyproject.toml based setup * fix imports? * fix imports? * Update tests/test_writing.py * add ci * add typing-extensions dep * fix import * remove mac and windows tests * temporarily disable 3.12 tests --- .copier-answers.yml | 11 ++ .github/ISSUE_TEMPLATE.md | 15 ++ .github/TEST_FAIL_TEMPLATE.md | 12 ++ .github/dependabot.yml | 10 ++ .github/workflows/ci.yml | 108 +++++++++++++++ .github/workflows/test_and_deploy.yml | 69 ---------- .pre-commit-config.yaml | 34 +++++ README.md | 175 +++++++++--------------- docs/examples/merging.md | 2 + docs/examples/multi_block.md | 3 +- docs/examples/single_block.md | 2 + docs/index.md | 2 + pyproject.toml | 152 +++++++++++++++++++- requirements.txt | 4 - setup.cfg | 45 ------ {starfile => src/starfile}/__init__.py | 0 {starfile => src/starfile}/__main__.py | 0 {starfile => src/starfile}/functions.py | 0 {starfile => src/starfile}/parser.py | 0 {starfile => src/starfile}/typing.py | 0 {starfile => src/starfile}/utils.py | 0 {starfile => src/starfile}/writer.py | 0 tests/test_parsing.py | 1 - tests/test_writing.py | 1 - 24 files changed, 410 insertions(+), 236 deletions(-) create mode 100644 .copier-answers.yml create mode 100644 .github/ISSUE_TEMPLATE.md create mode 100644 .github/TEST_FAIL_TEMPLATE.md create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/ci.yml delete mode 100644 .github/workflows/test_and_deploy.yml create mode 100644 .pre-commit-config.yaml delete mode 100644 requirements.txt delete mode 100644 setup.cfg rename {starfile => src/starfile}/__init__.py (100%) rename {starfile => src/starfile}/__main__.py (100%) rename {starfile => src/starfile}/functions.py (100%) rename {starfile => src/starfile}/parser.py (100%) rename {starfile => src/starfile}/typing.py (100%) rename {starfile => src/starfile}/utils.py (100%) rename {starfile => src/starfile}/writer.py (100%) diff --git a/.copier-answers.yml b/.copier-answers.yml new file mode 100644 index 0000000..b0205fc --- /dev/null +++ b/.copier-answers.yml @@ -0,0 +1,11 @@ +# Do not edit - changes here will be overwritten by Copier +_commit: v1 +_src_path: gh:pydev-guide/pyrepo-copier +author_email: alisterburt@gmail.com +author_name: Alister Burt +github_username: teamtomo +mode: tooling +module_name: starfile +project_name: starfile +project_short_description: STAR file I/O in Python + diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000..f5b1733 --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,15 @@ +* starfile version: +* Python version: +* Operating System: + +### Description + +Describe what you were trying to get done. +Tell us what happened, what went wrong, and what you expected to happen. + +### What I Did + +``` +Paste the command(s) you ran and the output. +If there was a crash, please include the traceback here. +``` diff --git a/.github/TEST_FAIL_TEMPLATE.md b/.github/TEST_FAIL_TEMPLATE.md new file mode 100644 index 0000000..3512972 --- /dev/null +++ b/.github/TEST_FAIL_TEMPLATE.md @@ -0,0 +1,12 @@ +--- +title: "{{ env.TITLE }}" +labels: [bug] +--- +The {{ workflow }} workflow failed on {{ date | date("YYYY-MM-DD HH:mm") }} UTC + +The most recent failing test was on {{ env.PLATFORM }} py{{ env.PYTHON }} +with commit: {{ sha }} + +Full run: https://github.com/{{ repo }}/actions/runs/{{ env.RUN_ID }} + +(This post will be updated if another test fails, as long as this issue remains open.) diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..96505a9 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,10 @@ +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + commit-message: + prefix: "ci(dependabot):" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..c1d4bc3 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,108 @@ +name: CI + +on: + push: + branches: + - main + tags: + - "v*" + pull_request: + workflow_dispatch: + schedule: + # run every week (for --pre release tests) + - cron: "0 0 * * 0" + +# cancel in-progress runs that use the same workflow and branch +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + check-manifest: + # check-manifest is a tool that checks that all files in version control are + # included in the sdist (unless explicitly excluded) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: pipx run check-manifest + + test: + name: ${{ matrix.platform }} (${{ matrix.python-version }}) + runs-on: ${{ matrix.platform }} + strategy: + fail-fast: false + matrix: + python-version: ["3.9", "3.10", "3.11", ] # "3.12"] + platform: [ubuntu-latest, ] # ...macos-latest, windows-latest] + + steps: + - uses: actions/checkout@v4 + + - name: ๐Ÿ Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + cache-dependency-path: "pyproject.toml" + cache: "pip" + + - name: Install Dependencies + run: | + python -m pip install -U pip + # if running a cron job, we add the --pre flag to test against pre-releases + python -m pip install .[test] ${{ github.event_name == 'schedule' && '--pre' || '' }} + + - name: ๐Ÿงช Run Tests + run: pytest --color=yes --cov --cov-report=xml --cov-report=term-missing + + # If something goes wrong with --pre tests, we can open an issue in the repo + - name: ๐Ÿ“ Report --pre Failures + if: failure() && github.event_name == 'schedule' + uses: JasonEtco/create-an-issue@v2 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PLATFORM: ${{ matrix.platform }} + PYTHON: ${{ matrix.python-version }} + RUN_ID: ${{ github.run_id }} + TITLE: "[test-bot] pip install --pre is failing" + with: + filename: .github/TEST_FAIL_TEMPLATE.md + update_existing: true + + - name: Coverage + uses: codecov/codecov-action@v3 + + deploy: + name: Deploy + needs: test + if: success() && startsWith(github.ref, 'refs/tags/') && github.event_name != 'schedule' + runs-on: ubuntu-latest + + permissions: + # IMPORTANT: this permission is mandatory for trusted publishing on PyPi + # see https://docs.pypi.org/trusted-publishers/ + id-token: write + # This permission allows writing releases + contents: write + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: ๐Ÿ Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.x" + + - name: ๐Ÿ‘ท Build + run: | + python -m pip install build + python -m build + + - name: ๐Ÿšข Publish to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + + - uses: softprops/action-gh-release@v1 + with: + generate_release_notes: true + files: './dist/*' diff --git a/.github/workflows/test_and_deploy.yml b/.github/workflows/test_and_deploy.yml deleted file mode 100644 index 6616f06..0000000 --- a/.github/workflows/test_and_deploy.yml +++ /dev/null @@ -1,69 +0,0 @@ -name: tests - -on: - push: - branches: - - main - tags: - - "v*" # Push events to matching v*, i.e. v1.0, v20.15.10 - pull_request: - branches: - - main - workflow_dispatch: - -jobs: - test: - name: ${{ matrix.platform }} py${{ matrix.python-version }} - runs-on: ${{ matrix.platform }} - strategy: - matrix: - platform: [ ubuntu-latest ] - python-version: ["3.9", "3.10" , "3.11"] - - steps: - - uses: actions/checkout@v2 - - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python-version }} - - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install setuptools pytest - pip install -e . - - - name: Test with pytest - run: pytest - env: - PLATFORM: ${{ matrix.platform }} - - - name: Coverage - uses: codecov/codecov-action@v1 - - deploy: - # this will run when you have tagged a commit, starting with "v*" - # and requires that you have put your twine API key in your - # github secrets (see readme for details) - needs: [ test ] - runs-on: ubuntu-latest - if: contains(github.ref, 'tags') - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v2 - with: - python-version: "3.x" - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install -U setuptools setuptools_scm wheel twine - - name: Build and publish - env: - TWINE_USERNAME: __token__ - TWINE_PASSWORD: ${{ secrets.TWINE_API_KEY }} - run: | - git tag - python setup.py sdist bdist_wheel - twine upload dist/* diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..49e3ffa --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,34 @@ +# enable pre-commit.ci at https://pre-commit.ci/ +# it adds: +# 1. auto fixing pull requests +# 2. auto updating the pre-commit configuration +ci: + autoupdate_schedule: monthly + autofix_commit_msg: "style(pre-commit.ci): auto fixes [...]" + autoupdate_commit_msg: "ci(pre-commit.ci): autoupdate" + +repos: + - repo: https://github.com/abravalheri/validate-pyproject + rev: v0.15 + hooks: + - id: validate-pyproject + + - repo: https://github.com/charliermarsh/ruff-pre-commit + rev: v0.1.3 + hooks: + - id: ruff + args: [--fix] + + - repo: https://github.com/psf/black + rev: 23.10.1 + hooks: + - id: black + + - repo: https://github.com/pre-commit/mirrors-mypy + rev: v1.6.1 + hooks: + - id: mypy + files: "^src/" + # # you have to add the things you want to type check against here + # additional_dependencies: + # - numpy diff --git a/README.md b/README.md index 71f04c3..7330e29 100644 --- a/README.md +++ b/README.md @@ -1,142 +1,93 @@ # starfile -[![Build Status](https://travis-ci.com/alisterburt/starfile.svg?branch=master)](https://travis-ci.com/alisterburt/starfile) -[![PyPI version](https://badge.fury.io/py/starfile.svg)](https://pypi.python.org/pypi/starfile/) -[![PyPI pyversions](https://img.shields.io/pypi/pyversions/starfile.svg)](https://pypi.python.org/pypi/starfile/) -[![DOI](https://zenodo.org/badge/273026988.svg)](https://zenodo.org/badge/latestdoi/273026988) +[![License](https://img.shields.io/pypi/l/starfile.svg?color=green)](https://github.com/teamtomo/starfile/raw/main/LICENSE) +[![PyPI](https://img.shields.io/pypi/v/starfile.svg?color=green)](https://pypi.org/project/starfile) +[![Python Version](https://img.shields.io/pypi/pyversions/starfile.svg?color=green)](https://python.org) +[![CI](https://github.com/teamtomo/starfile/actions/workflows/ci.yml/badge.svg)](https://github.com/teamtomo/starfile/actions/workflows/ci.yml) +[![codecov](https://codecov.io/gh/teamtomo/starfile/branch/main/graph/badge.svg)](https://codecov.io/gh/teamtomo/starfile) -`starfile` is a Python implementation of the [STAR](https://en.wikipedia.org/wiki/Self-defining_Text_Archive_and_Retrieval) -file format designed principally for compatibility with [RELION](https://github.com/3dem/relion) - format STAR files. +*starfile* is a package for reading and writing +[STAR files](https://en.wikipedia.org/wiki/Self-defining_Text_Archive_and_Retrieval) in Python. -It allows STAR files to be created and opened easily using a very simple API, exposing data blocks as [pandas](https://pandas.pydata.org/pandas-docs/stable/getting_started/overview.html) `DataFrame` objects. +

+ +

-This library aims to allow users and developers to read and write STAR files in Python as easily as possible as well as to encourage further analysis of data within the scientific Python ([SciPy](https://www.scipy.org/)) ecosystem. +*starfile* can be used interactively to inspect/explore files or in +scripts and larger software packages to provide basic STAR file I/O functions. +Data is exposed as simple python dictionaries or +[pandas dataframes](https://pandas.pydata.org/docs/user_guide/dsintro.html#dataframe). -You can use it interactively to inspect/explore files or in scripts and larger software packages to provide basic STAR file I/O functions. +This package was designed principally for compatibility with files generated by +[RELION](https://www3.mrc-lmb.cam.ac.uk/relion/index.php/Main_Page). -``` -The STAR file: a new format for electronic dataframes transfer and archiving -J. Chem. Inf. Comput. Sci. 1991, 31, 2, 326โ€“333 -Publication Date: May 1, 1991 -https://doi.org/10.1021/ci00002a020 -``` -## Features -- Easy to install and use -- Simple API for reading of STAR files as pandas `DataFrame` objects -- Simple API for writing of STAR files from pandas `DataFrame` objects +For more information on working with dataframes, please see the +[pandas docs](https://pandas.pydata.org/docs/user_guide/10min.html). +For *starfile* specific documentation, see [teamtomo.org/starfile](https://teamtomo.org/starfile) -## Installation -Installation is available directly from the [Python package index](https://pypi.org/project/starfile/) -```bash -pip install starfile -``` - -Currently `python` >= `3.8` is supported. You can check your `python` version with - -```sh -python -V -``` -We recommend installing into a [virtual environment](https://jni.github.io/using-python-for-science/intro-to-environments.html) for use in your projects. +--- +# Quickstart +For the following file `particles.star` with a single data block -## Usage +```txt +data_particles -### Reading STAR files -To open a STAR file -```python ->>> import starfile ->>> df = starfile.read('tests/dataframes/one_loop.star') ->>> df - rlnCoordinateX rlnCoordinateY ... rlnAngleTilt rlnAnglePsi -0 1572.444 1084.500 ... 0 0 -1 1507.500 1104.357 ... 0 0 -2 1512.432 973.500 ... 0 0 -3 1560.385 1063.500 ... 0 0 -4 1537.500 1060.500 ... 0 0 - ... ... ... ... ... -1360 1078.500 796.500 ... 0 0 -1361 1075.500 784.500 ... 0 0 -1362 1080.531 796.500 ... 0 0 -1363 1045.992 737.411 ... 0 0 -1364 1053.530 745.500 ... 0 0 - -[1365 rows x 12 columns] +loop_ +_rlnCoordinateX #1 +_rlnCoordinateY #2 +_rlnCoordinateZ #3 +_rlnAngleRot #4 +_rlnAngleTilt #5 +_rlnAnglePsi #6 +_rlnMicrographName #7 +91.798700 83.622600 203.341030 -51.740000 173.930000 32.971000 01_10.00Apx.mrc +97.635800 80.437000 203.136160 141.500000 171.760000 -134.680000 01_10.00Apx.mrc +92.415200 88.842700 210.663900 -78.750000 173.930000 87.263200 01_10.00Apx.mrc +94.607830 93.135410 205.425960 -85.215000 167.170000 85.632200 01_10.00Apx.mrc +86.187800 80.125400 204.558750 14.910000 163.260000 -16.030000 01_10.00Apx.mrc +91.824240 76.738300 203.794280 39.740000 168.410000 -57.250000 01_10.00Apx.mrc +98.253300 73.530100 203.856030 73.950000 166.380000 -84.640000 01_10.00Apx.mrc +101.303500 80.290800 194.790400 -178.878000 166.090000 73.181000 01_10.00Apx.mrc ``` -- Each block will return either a DataFrame for a `loop_` block, or a `dict` for a simple block -- A STAR file with a single block simply returns that DataFrame or `dict`, while a STAR file containing multiple blocks will return a `dict` of entries, with keys determined by the `data_*` titles -- If you would like to always return a `dict` of entries even for single-block STAR files, you can use the `always_dict=True` keyword argument - - -### Writing STAR files -DataFrame objects (or dicts or lists of dataframes) can be written to STAR files using `starfile.write` +Read the file ```python ->>> starfile.write(df, 'tests/dataframes/cars.star') -``` - -Produces a STAR file which looks like -```bash -# Created by the starfile python package (version 0.1) on 18/06/2020 13:26:32 -data_cars +import starfile -loop_ -_Brand #1 -_Price #2 -Honda_Civic 22000 -Toyota_Corolla 25000 -Ford_Focus 27000 -Audi_A4 35000 +df = starfile.read('particles.star') ``` +Interact with the data -- floating point format can be specified by the `float_format` keyword argument (default `%.6f`) -- data block headers are of format `data_` where key is the dictionary key if a `dict` is passed, `df.name` if a -`DataFrame` or list of `DataFrame`s is passed - -## Interactive usage -You can also use `starfile` as an interactive command line tool for quick -and dirty data analysis. -This functionality can be installed using pip: - -```shell -pip install starfile[cli] +```python +df['rlnCoordinateX'] += 10 +df.head() ``` - -Note that with certain shells (e.g. `zsh`) you may need to use -`pip install 'starfile[cli]'` to avoid unwanted shell expansion of the -square bracket syntax. - -You can then call `starfile .star` to be dropped into an interactive -Python console with access to your data. - -```sh -starfile tests/data/loop_block.star +```txt + rlnCoordinateX rlnCoordinateY rlnCoordinateZ rlnAngleRot rlnAngleTilt rlnAnglePsi rlnMicrographName +0 101.79870 83.62260 203.34103 -51.740 173.93 32.9710 01_10.00Apx.mrc +1 107.63580 80.43700 203.13616 141.500 171.76 -134.6800 01_10.00Apx.mrc +2 102.41520 88.84270 210.66390 -78.750 173.93 87.2632 01_10.00Apx.mrc +3 104.60783 93.13541 205.42596 -85.215 167.17 85.6322 01_10.00Apx.mrc +4 96.18780 80.12540 204.55875 14.910 163.26 -16.0300 01_10.00Apx.mrc ``` -```python -Python 3.9.6 (default, Aug 18 2021, 12:38:10) -Type 'copyright', 'credits' or 'license' for more information -IPython 7.27.0 -- An enhanced Interactive Python. Type '?' for help. +Save the (modified) data to file -=== Starfile === - - access your data with `star` - - write it out with `write(...)` +```python +starfile.write(df, 'modified_particles.star') ``` -Both matplotlib and seaborn are available for plotting your data in this -interactive shell. +For more advanced usage please check out the examples. -## License -The project is released under the BSD 3-Clause License +--- -## Testing -The project is tested using [pytest](https://docs.pytest.org/en/stable/). -To run tests, simply run `pytest` in the `tests` directory +# Installation -## Known Issues -- Cannot handle more than one loop in a data block as found in mmCIF files, please use -[GEMMI](https://github.com/project-gemmi/gemmi) in these cases +```shell +pip install starfile +``` diff --git a/docs/examples/merging.md b/docs/examples/merging.md index 452680a..8f812fc 100644 --- a/docs/examples/merging.md +++ b/docs/examples/merging.md @@ -59,7 +59,9 @@ In pandas, this is implemented as [`DataFrame.merge()`](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.merge.html). ```python + import starfile + star = starfile.read('particles.star') df = star['particles'].merge(star['optics'], on='rlnOpticsGroup') ``` diff --git a/docs/examples/multi_block.md b/docs/examples/multi_block.md index 0885bd2..61e5f74 100644 --- a/docs/examples/multi_block.md +++ b/docs/examples/multi_block.md @@ -52,6 +52,7 @@ In this case, a dictionary of dataframes or dictionaries is returned. The keys o of data blocks. ```python + import starfile star = starfile.read('particles.star') @@ -71,8 +72,8 @@ particle_df = star['particles'] Writing a file containing multiple data blocks is similar, simply pass a dictionary of entries. ```python -import starfile +import starfile starfile.write( {'optics': optics_df, 'particles': particle_df}, 'new_file.star' diff --git a/docs/examples/single_block.md b/docs/examples/single_block.md index aa23dba..c9e1116 100644 --- a/docs/examples/single_block.md +++ b/docs/examples/single_block.md @@ -26,7 +26,9 @@ _rlnMicrographName #7 Read the file ```python + import starfile + df = starfile.read('particles.star') ``` diff --git a/docs/index.md b/docs/index.md index a9bf24f..b101670 100644 --- a/docs/index.md +++ b/docs/index.md @@ -47,7 +47,9 @@ _rlnMicrographName #7 Read the file ```python + import starfile + df = starfile.read('particles.star') ``` diff --git a/pyproject.toml b/pyproject.toml index 85db30f..d9d9549 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,151 @@ +# https://peps.python.org/pep-0517/ [build-system] -requires = ["setuptools>=45", "wheel", "setuptools_scm>=6.2"] +requires = ["hatchling", "hatch-vcs"] +build-backend = "hatchling.build" -[tool.setuptools_scm] -write_to = "starfile/_version.py" +# https://hatch.pypa.io/latest/config/metadata/ +[tool.hatch.version] +source = "vcs" + +# read more about configuring hatch at: +# https://hatch.pypa.io/latest/config/build/ +[tool.hatch.build.targets.wheel] +only-include = ["src"] +sources = ["src"] + +# https://peps.python.org/pep-0621/ +[project] +name = "starfile" +dynamic = ["version"] +description = "STAR file I/O in Python" +readme = "README.md" +requires-python = ">=3.8" +license = { text = "BSD-3-Clause" } +authors = [{ name = "Alister Burt", email = "alisterburt@gmail.com" }] +# https://pypi.org/classifiers/ +classifiers = [ + "Development Status :: 3 - Alpha", + "License :: OSI Approved :: BSD License", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Typing :: Typed", +] +# add your package dependencies here +dependencies = [ + "numpy", + "pandas>=2.1.1", + "typing-extensions", +] + +# https://peps.python.org/pep-0621/#dependencies-optional-dependencies +# "extras" (e.g. for `pip install .[test]`) +[project.optional-dependencies] +# add dependencies used for testing here +test = ["pytest", "pytest-cov"] +# add anything else you like to have in your dev environment here +dev = [ + "black", + "ipython", + "mypy", + "pdbpp", # https://github.com/pdbpp/pdbpp + "pre-commit", + "rich", # https://github.com/Textualize/rich + "ruff", +] + +[project.urls] +homepage = "https://github.com/teamtomo/starfile" +repository = "https://github.com/teamtomo/starfile" + +# Entry points +# https://peps.python.org/pep-0621/#entry-points +# same as console_scripts entry point +# [project.scripts] +# starfile-cli = "starfile:main_cli" + +# [project.entry-points."some.group"] +# tomatoes = "starfile:main_tomatoes" + +# https://docs.astral.sh/ruff +[tool.ruff] +line-length = 88 +target-version = "py38" +src = ["src"] +# https://docs.astral.sh/ruff/rules +select = [ + "E", # style errors + "W", # style warnings + "F", # flakes + "D", # pydocstyle + "I", # isort + "UP", # pyupgrade + "C4", # flake8-comprehensions + "B", # flake8-bugbear + "A001", # flake8-builtins + "RUF", # ruff-specific rules + "TCH", # flake8-type-checking + "TID", # flake8-tidy-imports +] + +[tool.ruff.lint] +pydocstyle = { convention = "numpy" } +extend-select = [ + "D417", # Missing argument descriptions in Docstrings +] +extend-ignore = [ + "D401", # First line should be in imperative mood (remove to opt in) +] + +[tool.ruff.per-file-ignores] +"tests/*.py" = ["D", "S"] +"setup.py" = ["D"] + +# https://mypy.readthedocs.io/en/stable/config_file.html +[tool.mypy] +files = "src/**/" +strict = true +disallow_any_generics = false +disallow_subclassing_any = false +show_error_codes = true +pretty = true + +# # module specific overrides +# [[tool.mypy.overrides]] +# module = ["numpy.*",] +# ignore_errors = true + +# https://docs.pytest.org/en/6.2.x/customize.html +[tool.pytest.ini_options] +minversion = "6.0" +testpaths = ["tests"] +filterwarnings = ["error"] + +# https://coverage.readthedocs.io/en/6.4/config.html +[tool.coverage.report] +exclude_lines = [ + "pragma: no cover", + "if TYPE_CHECKING:", + "@overload", + "except ImportError", + "\\.\\.\\.", + "raise NotImplementedError()", + "pass", +] +show_missing = true + +[tool.coverage.run] +source = ["starfile"] + +# https://github.com/mgedmin/check-manifest#configuration +# add files that you want check-manifest to explicitly ignore here +# (files that are in the repo but shouldn't go in the package) +[tool.check-manifest] +ignore = [ + ".pre-commit-config.yaml", + ".ruff_cache/**/*", + "tests/**/*", +] diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index f5f127e..0000000 --- a/requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ -# requirements are in setup.cfg -# https://caremad.io/posts/2013/07/setup-vs-requirement/ - --e ".[cli]" \ No newline at end of file diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index a42f87c..0000000 --- a/setup.cfg +++ /dev/null @@ -1,45 +0,0 @@ -[metadata] -name = starfile -version = attr: starfile.__version__ -url = https://github.com/alisterburt/starfile -license = BSD 3-Clause -license_file = LICENSE -description = STAR file reading and writing in python. -long_description = file: README.md -long_description_content_type = text/markdown -author = Alister Burt -author_email = alisterburt@gmail.com -classifiers = - License :: OSI Approved :: BSD License - Natural Language :: English - Operating System :: OS Independent - Programming Language :: Python - Programming Language :: Python :: 3.9 - Programming Language :: Python :: 3.10 - Programming Language :: Python :: 3.11 - - -[options] -zip_safe = False -packages = find: -python_requires = >= 3.9 -include_package_data = True -install_requires = - numpy - pandas>=2.1.1 - typing-extensions - - -[options.extras_require] -cli = - click - IPython - - -[options.entry_points] -console_scripts = - starfile = starfile.__main__:cli - - -[options.package_data] -* = *.txt, *.md diff --git a/starfile/__init__.py b/src/starfile/__init__.py similarity index 100% rename from starfile/__init__.py rename to src/starfile/__init__.py diff --git a/starfile/__main__.py b/src/starfile/__main__.py similarity index 100% rename from starfile/__main__.py rename to src/starfile/__main__.py diff --git a/starfile/functions.py b/src/starfile/functions.py similarity index 100% rename from starfile/functions.py rename to src/starfile/functions.py diff --git a/starfile/parser.py b/src/starfile/parser.py similarity index 100% rename from starfile/parser.py rename to src/starfile/parser.py diff --git a/starfile/typing.py b/src/starfile/typing.py similarity index 100% rename from starfile/typing.py rename to src/starfile/typing.py diff --git a/starfile/utils.py b/src/starfile/utils.py similarity index 100% rename from starfile/utils.py rename to src/starfile/utils.py diff --git a/starfile/writer.py b/src/starfile/writer.py similarity index 100% rename from starfile/writer.py rename to src/starfile/writer.py diff --git a/tests/test_parsing.py b/tests/test_parsing.py index 78f7c96..4df542f 100644 --- a/tests/test_parsing.py +++ b/tests/test_parsing.py @@ -248,7 +248,6 @@ def test_empty_loop_block(): ('"',basic_double_quote), ]) def test_quote_basic(quote_character,filename): - import math parser = StarParser(filename) assert len(parser.data_blocks) == 1 assert parser.data_blocks['']['no_quote_string'] == "noquote" diff --git a/tests/test_writing.py b/tests/test_writing.py index 24ec1a0..1396520 100644 --- a/tests/test_writing.py +++ b/tests/test_writing.py @@ -1,7 +1,6 @@ from os.path import join as join_path from tempfile import TemporaryDirectory import time -import math import pandas as pd import pytest