Skip to content

Commit

Permalink
Merge pull request planetarypy#23 from michaelaye/main
Browse files Browse the repository at this point in the history
implement GH workflow for running tests
  • Loading branch information
michaelaye authored Nov 27, 2024
2 parents fbe3be7 + 8805b49 commit 081441c
Show file tree
Hide file tree
Showing 16 changed files with 442 additions and 455 deletions.
19 changes: 0 additions & 19 deletions .github/workflows/run_makefile.yml

This file was deleted.

66 changes: 66 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# FILE: .github/workflows/test.yaml
name: Run software tests

on:
push:
pull_request:
branches:
- main

jobs:
test:
name: Run tests
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Setup Conda
uses: conda-incubator/setup-miniconda@v3
with:
miniforge-variant: Miniforge3
miniforge-version: latest
activate-environment: test_env
use-mamba: true
python-version: "3.9"
channels: conda-forge
channel-priority: strict
auto-activate-base: false
conda-remove-defaults: true

- name: Cache conda env
uses: actions/cache@v3
with:
path: |
~/.conda/pkgs
~/.conda/envs
key: conda-${{ runner.os }}-py${{ matrix.python-version }}-${{ github.sha }}
restore-keys: |
conda-${{ runner.os }}-py${{ matrix.python-version }}-
conda-${{ runner.os }}-
- name: Install dependencies
shell: bash -l {0}
run: |
# Install tomlkit and sh first to run the installation script
mamba install -y -c conda-forge tomlkit sh
# Run the installation script
python install_dev_deps.py
- name: Install package
shell: bash -l {0}
run: |
pip install -e .
- name: Run tests
shell: bash -l {0}
run: |
pytest --cov=src/planetarypy --cov-report=xml --cov-report=term
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./coverage.xml
fail_ci_if_error: true
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,8 @@ dmypy.json

# Pyre type checker
.pyre/

# pixi environments
.pixi
*.egg-info
*.code-workspace
1 change: 0 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ lintblack: ## check style with black
black --check src/planetarypy tests

test: ## run tests quickly with the default Python
jupyter nbconvert --to python tests/test_*.ipynb
pytest --cov

test-all: ## run tests on every Python version with tox
Expand Down
2 changes: 2 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ planetarypy
:target: https://planetarypy.readthedocs.io/en/latest/?badge=latest
:alt: Documentation Status

.. image:: https://codecov.io/gh/planetarypy/planetarypy/branch/main/graph/badge.svg
:target: https://codecov.io/gh/planetarypy/planetarypy
Core package for planetary science tools.

Warning
Expand Down
53 changes: 53 additions & 0 deletions install_dev_deps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#!/usr/bin/env python
from pathlib import Path
import tomlkit
import sh
import sys

# Define packages that should be installed via pip instead of conda
PIP_PACKAGES = {'build', 'pip-tools'}

def install_deps():
# Read pyproject.toml
pyproject_path = Path("pyproject.toml")
with open(pyproject_path) as f:
pyproject = tomlkit.load(f)

# Get both main and dev dependencies
main_deps = pyproject["project"]["dependencies"]
dev_deps = pyproject["project"]["optional-dependencies"]["dev"]
all_deps = main_deps + dev_deps

# Split dependencies into conda and pip packages
conda_deps = [dep for dep in all_deps if dep not in PIP_PACKAGES]
pip_deps = [dep for dep in all_deps if dep in PIP_PACKAGES]

# Install conda packages
if conda_deps:
try:
print("Installing with mamba:", ' '.join(conda_deps))
sh.mamba("install", "-y", "-c", "conda-forge", *conda_deps,
_err=sys.stderr, _out=sys.stdout)
print("Conda installation completed successfully!")
except sh.ErrorReturnCode as e:
print("Error installing conda packages!")
print("Exit code:", e.exit_code)
print("Stdout:", e.stdout.decode() if e.stdout else 'No stdout')
print("Stderr:", e.stderr.decode() if e.stderr else 'No stderr')
sys.exit(1)

# Install pip packages
if pip_deps:
try:
print("\nInstalling with pip:", ' '.join(pip_deps))
sh.pip("install", *pip_deps, _err=sys.stderr, _out=sys.stdout)
print("Pip installation completed successfully!")
except sh.ErrorReturnCode as e:
print("Error installing pip packages!")
print("Exit code:", e.exit_code)
print("Stdout:", e.stdout.decode() if e.stdout else 'No stdout')
print("Stderr:", e.stderr.decode() if e.stderr else 'No stderr')
sys.exit(1)

if __name__ == "__main__":
install_deps()
11 changes: 11 additions & 0 deletions planetarypy.code-workspace
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"folders": [
{
"path": "."
},
{
"path": "../0_nbplanetary"
}
],
"settings": {}
}
53 changes: 53 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "planetarypy"
version = "0.2.0"
description = "Core package for planetary data tools."
readme = "README.rst"
requires-python = ">= 3.9, <4"
license = {text = "BSD license"}
license-file = "LICENSE"
authors = [
{name = "Planetarypy Developers", email = "[email protected]"}
]
keywords = ["planetarypy", "planetary", "space", "science"]
classifiers = [
"Development Status :: 2 - Pre-Alpha",
"Intended Audience :: Developers",
"License :: OSI Approved :: BSD License",
"Natural Language :: English",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
]
dependencies = [
"tomlkit",
"requests",
"tqdm",
"pandas",
"astropy",
"spiceypy",
"yarl",
"matplotlib",
]
repository = "https://github.com/planetarypy/planetarypy"

[project.optional-dependencies]
dev = [
"pytest",
"pytest-cov",
"build",
"twine",
"pip-tools",
"make"
]

[project.scripts]
planetarypy = "planetarypy.cli:main"

[tool.hatch.build.targets.wheel]
packages = ["src/planetarypy"]
10 changes: 5 additions & 5 deletions src/planetarypy/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from pathlib import Path
from typing import Union

import toml
import tomlkit


def reset_non_urls(
Expand Down Expand Up @@ -57,7 +57,7 @@ def _read_config(self):
`storage_root` will be stored as attribute.
"""
self.tomldoc = toml.loads(self.path.read_text())
self.tomldoc = tomlkit.loads(self.path.read_text())
if not self.tomldoc["storage_root"]:
path = Path.home() / "planetarypy_data"
path.mkdir(exist_ok=True)
Expand All @@ -78,7 +78,7 @@ def __getitem__(self, key: str):
key = "missions." + key
try:
return reduce(lambda c, k: c[k], key.split("."), self.d)
except toml.exceptions.NonExistentKey:
except KeyError:
return ""

def get_value(
Expand All @@ -90,7 +90,7 @@ def get_value(
key = "missions." + key
try:
return reduce(lambda c, k: c[k], key.split("."), self.d)
except toml.exceptions.NonExistentKey:
except KeyError:
return ""

def set_value(
Expand Down Expand Up @@ -119,7 +119,7 @@ def __setitem__(self, nested_key: str, value: Union[float, str]):

def save(self):
"""Write the TOML doc to file."""
self.path.write_text(toml.dumps(self.tomldoc))
self.path.write_text(tomlkit.dumps(self.tomldoc))

@property
def missions(self):
Expand Down
17 changes: 5 additions & 12 deletions src/planetarypy/spice/kernels.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@
import requests
import spiceypy as spice
from astropy.time import Time
from dask.distributed import Client
from tqdm.auto import tqdm
from tqdm.contrib.concurrent import process_map
from yarl import URL
Expand Down Expand Up @@ -237,17 +236,11 @@ def get_local_path(self, url) -> Path:
return basepath / u.parent.name / u.name

def _non_blocking_download(self, overwrite: bool = False):
"Use dask for a parallel download."
with Client() as client:
futures = []
for url in tqdm(self.kernel_urls, desc="Kernels downloaded"):
local_path = self.get_local_path(url)
if local_path.exists() and not overwrite:
print(local_path.parent.name, local_path.name, "locally available.")
continue
local_path.parent.mkdir(exist_ok=True, parents=True)
futures.append(client.submit(url_retrieve, url, local_path))
return [f.result() for f in futures]
"Use multiprocessing for parallel download."
paths = [self.get_local_path(url) for url in self.kernel_urls]
args = zip(self.kernel_urls, paths, repeat(overwrite))
_ = process_map(download_one_url, args, max_workers=cpu_count() - 2,
desc="Kernels downloaded")

def _concurrent_download(self, overwrite: bool = False):
paths = [self.get_local_path(url) for url in self.kernel_urls]
Expand Down
12 changes: 11 additions & 1 deletion src/planetarypy/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,19 @@ def file_variations(filename: Union[str, Path], extensions: list) -> list:
Parameters
----------
filename : str
filename : str or Path
The original filename to use as a base.
extensions : list
List of extensions to use for variations.
Raises
------
TypeError
If extensions is not a list
ValueError
If any extension doesn't start with a dot
"""
if not isinstance(extensions, list):
raise TypeError("extensions must be a list")

return [Path(filename).with_suffix(extension) for extension in extensions]
Loading

0 comments on commit 081441c

Please sign in to comment.