Skip to content

Commit

Permalink
Python: Use black, flake8, isort
Browse files Browse the repository at this point in the history
  • Loading branch information
dbaston committed Dec 18, 2023
1 parent c51455d commit 1ce4c39
Show file tree
Hide file tree
Showing 18 changed files with 267 additions and 182 deletions.
21 changes: 21 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[flake8]
max_line_length = 88
ignore =
C408 # Unnecessary dict/list/tuple call - rewrite as a literal
E203 # whitespace before ':' - doesn't work well with black
E225 # missing whitespace around operator - let black worry about that
E262 # inline comment should start with '# '
E265 # block comment should start with '# '
E266 # too many leading '#' for block comment
E302 # expected 2 blank lines, found 1
E402 # module level import not at top of file
E501 # line too long - let black handle that
E711 # comparison to None should be
E712 # comparison to False/True should be
E741 # ambiguous variable name
F405 # may be undefined, or defined from star imports
W291 # trailing
W503 # line break occurred before a binary operator - let black worry about that
W504 # line break occurred after a binary operator - let black worry about that
per-file-ignores =
__init__.py:F401
3 changes: 3 additions & 0 deletions .isort.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[settings]
known_first_party=exactextract
profile=black
12 changes: 12 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
repos:
- repo: https://github.com/psf/black
rev: 22.3.0
hooks:
- id: black
- repo: https://github.com/timothycrosley/isort
rev: 5.12.0
hooks:
- id: isort
- repo: https://github.com/pycqa/flake8
rev: 3.9.2
hooks:
- id: flake8
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: 'v15.0.7'
hooks:
Expand Down
101 changes: 54 additions & 47 deletions python/setup.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@

# -*- coding: utf-8 -*-
import configparser
import os
import sys
import subprocess
import configparser
import sys
from pathlib import Path

from setuptools import setup, Extension
from setuptools import Extension, setup
from setuptools.command.build_ext import build_ext


Expand All @@ -18,53 +17,55 @@ def __init__(self, name):
class CMakeBuild(build_ext):
def run(self):
try:
subprocess.check_output(['cmake', '--version'])
subprocess.check_output(["cmake", "--version"])
except OSError:
raise RuntimeError(
"CMake must be installed to build the following extensions: " +
", ".join(e.name for e in self.extensions))
"CMake must be installed to build the following extensions: "
+ ", ".join(e.name for e in self.extensions)
)

build_directory = os.path.abspath(self.build_temp)

cmake_args = [
'-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=' + build_directory,
'-DPYTHON_EXECUTABLE=' + sys.executable,
'-DBUILD_CLI=OFF',
'-DBUILD_TEST=OFF',
'-DBUILD_DOC=OFF'
"-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=" + build_directory,
"-DPYTHON_EXECUTABLE=" + sys.executable,
"-DBUILD_CLI=OFF",
"-DBUILD_TEST=OFF",
"-DBUILD_DOC=OFF",
]

cfg = 'Debug' if self.debug else 'Release'
build_args = ['--config', cfg]
cfg = "Debug" if self.debug else "Release"
build_args = ["--config", cfg]

cmake_args += ['-DCMAKE_BUILD_TYPE=' + cfg]
cmake_args += ["-DCMAKE_BUILD_TYPE=" + cfg]

# Assuming Makefiles
build_args += ['--', '-j2']
build_args += ["--", "-j2"]

self.build_args = build_args

env = os.environ.copy()
env['CXXFLAGS'] = '{} -DVERSION_INFO=\\"{}\\"'.format(
env.get('CXXFLAGS', ''),
self.distribution.get_version()) # type: ignore
env["CXXFLAGS"] = '{} -DVERSION_INFO=\\"{}\\"'.format(
env.get("CXXFLAGS", ""), self.distribution.get_version()
) # type: ignore
if not os.path.exists(self.build_temp):
os.makedirs(self.build_temp)

# CMakeLists.txt is in the parent directory of this setup.py file
cmake_list_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir))
print('-' * 10, 'Running CMake prepare', '-' * 40)
subprocess.check_call(['cmake', cmake_list_dir] + cmake_args,
cwd=self.build_temp, env=env)
cmake_list_dir = os.path.abspath(
os.path.join(os.path.dirname(__file__), os.pardir)
)
print("-" * 10, "Running CMake prepare", "-" * 40)
subprocess.check_call(
["cmake", cmake_list_dir] + cmake_args, cwd=self.build_temp, env=env
)

print('-' * 10, 'Building extensions', '-' * 40)
cmake_cmd = ['cmake', '--build', '.'] + self.build_args
subprocess.check_call(cmake_cmd,
cwd=self.build_temp)
print("-" * 10, "Building extensions", "-" * 40)
cmake_cmd = ["cmake", "--build", "."] + self.build_args
subprocess.check_call(cmake_cmd, cwd=self.build_temp)

make_cmd = ['make']
subprocess.check_call(make_cmd,
cwd=self.build_temp)
make_cmd = ["make"]
subprocess.check_call(make_cmd, cwd=self.build_temp)

# Move from build temp to final position
for ext in self.extensions:
Expand All @@ -81,42 +82,48 @@ def move_output(self, ext):

def find_version():
version_script = os.path.abspath(
os.path.join(os.path.dirname(__file__), os.pardir, 'cmake', 'VersionSource.cmake'))
version = subprocess.run(['cmake', '-P', version_script],
capture_output=True,
text=True).stderr.split(':')[1].strip()
os.path.join(
os.path.dirname(__file__), os.pardir, "cmake", "VersionSource.cmake"
)
)
version = (
subprocess.run(["cmake", "-P", version_script], capture_output=True, text=True)
.stderr.split(":")[1]
.strip()
)
print(f"Version: {version}")
return version


# The information here can also be placed in setup.cfg - better separation of
# logic and declaration, and simpler if you include description/version in a file.

# For now, just parse from config file
config = configparser.ConfigParser()
config.read('project.ini')

project = config['base']['project']
copyright = config['base']['copyright']
author = config['base']['author']
url = config['base']['url']
title = config['base']['title']
description = config['base']['description']
tag = config['base']['tag']
config.read("project.ini")

project = config["base"]["project"]
copyright = config["base"]["copyright"]
author = config["base"]["author"]
url = config["base"]["url"]
title = config["base"]["title"]
description = config["base"]["description"]
tag = config["base"]["tag"]
version = find_version()

setup(
name=project,
version=version,
author=author,
url=url,
author_email='',
author_email="",
description=description,
packages=['exactextract'],
package_dir={'exactextract': 'src/exactextract'},
packages=["exactextract"],
package_dir={"exactextract": "src/exactextract"},
ext_modules=[CMakeExtension("_exactextract")],
cmdclass={"build_ext": CMakeBuild},
zip_safe=False,
extras_require={"test": ["pytest>=6.0"]},
python_requires=">=3.7",
install_requires=["pybind11>=2.2"]
install_requires=["pybind11>=2.2"],
)
6 changes: 3 additions & 3 deletions python/src/exactextract/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@
from .feature_source import (
FeatureSource,
GDALFeatureSource,
JSONFeatureSource,
GeoPandasFeatureSource,
JSONFeatureSource,
)
from .operation import Operation
from .processor import FeatureSequentialProcessor, RasterSequentialProcessor
from .raster_source import (
RasterSource,
GDALRasterSource,
NumPyRasterSource,
RasterioRasterSource,
RasterSource,
XArrayRasterSource,
)
from .writer import Writer, JSONWriter, GDALWriter
from .writer import GDALWriter, JSONWriter, Writer
17 changes: 11 additions & 6 deletions python/src/exactextract/exact_extract.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,17 @@
from .feature_source import (
FeatureSource,
GDALFeatureSource,
JSONFeatureSource,
GeoPandasFeatureSource,
JSONFeatureSource,
)
from .raster_source import RasterSource, GDALRasterSource, RasterioRasterSource, XArrayRasterSource
from .operation import Operation
from .processor import FeatureSequentialProcessor, RasterSequentialProcessor
from .raster_source import (
GDALRasterSource,
RasterioRasterSource,
RasterSource,
XArrayRasterSource,
)
from .writer import JSONWriter


Expand Down Expand Up @@ -63,7 +68,7 @@ def prep_raster(rast, band=None, name_root=None, names=None):
pass

try:
import rioxarray
import rioxarray # noqa: F401
import xarray

if isinstance(rast, xarray.core.dataarray.DataArray):
Expand All @@ -73,9 +78,9 @@ def prep_raster(rast, band=None, name_root=None, names=None):
if not names:
names = [f"{name_root}_{i+1}" for i in range(rast.rio.count)]
return [
XArrayRasterSource(rast, i+1, name=names[i])
for i in range(rast.rio.count)
]
XArrayRasterSource(rast, i + 1, name=names[i])
for i in range(rast.rio.count)
]

except ImportError:
pass
Expand Down
2 changes: 1 addition & 1 deletion python/src/exactextract/feature.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def __init__(self, f=None):
Feature.__init__(self)
if f is None:
self.feature = {}
elif hasattr(f, '__geo_interface__'):
elif hasattr(f, "__geo_interface__"):
self.feature = f.__geo_interface__
else:
self.feature = f
Expand Down
4 changes: 2 additions & 2 deletions python/src/exactextract/feature_source.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from _exactextract import FeatureSource

import os

from _exactextract import FeatureSource

from .feature import GDALFeature, JSONFeature


Expand Down
8 changes: 3 additions & 5 deletions python/src/exactextract/processor.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from typing import List, Union
from typing import List

from _exactextract import (
FeatureSequentialProcessor as _FeatureSequentialProcessor,
RasterSequentialProcessor as _RasterSequentialProcessor,
)
from _exactextract import FeatureSequentialProcessor as _FeatureSequentialProcessor
from _exactextract import RasterSequentialProcessor as _RasterSequentialProcessor

from .feature_source import FeatureSource
from .operation import Operation
Expand Down
18 changes: 6 additions & 12 deletions python/src/exactextract/raster_source.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import numpy as np
import os
import pathlib

import numpy as np
from _exactextract import RasterSource


Expand Down Expand Up @@ -134,7 +133,7 @@ def __init__(self, ds, band_idx=1, *, name=None):
super().__init__()

if isinstance(ds, (str, os.PathLike)):
import rioxarray
import rioxarray # noqa: F401
import xarray

ds = xarray.open_dataarray(ds)
Expand All @@ -143,15 +142,14 @@ def __init__(self, ds, band_idx=1, *, name=None):
if self.ds.rio.crs is None:
# Set a default CRS to prevent clip_box from
# complaining that we don't have one
self.ds.rio.set_crs('EPSG:4326', inplace=True)
self.ds.rio.set_crs("EPSG:4326", inplace=True)
self.band_idx = band_idx
self.band_dim = self._band_dim(self.ds)
self.bounds = self.ds.rio.bounds()

if name:
self.set_name(name)


@staticmethod
def _band_dim(ds):
dims = list(ds.dims)
Expand All @@ -165,19 +163,15 @@ def _band_dim(ds):
else:
raise Exception("Cannot handle >1 non-spatial dimension")


def res(self):
return tuple(abs(x) for x in self.ds.rio.resolution())


def extent(self):
return self.bounds


def nodata_value(self):
return self.ds.rio.nodata


def read_window(self, x0, y0, nx, ny):
lats = self.ds[self.ds.rio.y_dim]
flipped = bool(len(lats) > 1 and lats[1] > lats[0])
Expand All @@ -188,8 +182,8 @@ def read_window(self, x0, y0, nx, ny):
selection = {}
if self.band_dim is not None:
selection[self.band_dim] = self.ds[self.band_dim][self.band_idx - 1]
selection[self.ds.rio.x_dim] = self.ds[self.ds.rio.x_dim][x0 : x0+nx]
selection[self.ds.rio.y_dim] = self.ds[self.ds.rio.y_dim][y0 : y0+ny]
selection[self.ds.rio.x_dim] = self.ds[self.ds.rio.x_dim][x0 : x0 + nx]
selection[self.ds.rio.y_dim] = self.ds[self.ds.rio.y_dim][y0 : y0 + ny]

ret = self.ds.sel(**selection).to_numpy()

Expand Down
6 changes: 2 additions & 4 deletions python/src/exactextract/writer.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import pathlib
from typing import Union, Dict, List

from _exactextract import Writer
from .feature import JSONFeature, GDALFeature

from .feature import GDALFeature, JSONFeature


class JSONWriter(Writer):
Expand Down
2 changes: 1 addition & 1 deletion python/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest

from exactextract import NumPyRasterSource, JSONFeature
from exactextract import NumPyRasterSource


@pytest.fixture()
Expand Down
Loading

0 comments on commit 1ce4c39

Please sign in to comment.