* add github workflow for building wheels

* rename cython module for more consistency
* restructure python code
* proper python module setup
* bump major version 2.0.0
This commit is contained in:
Mario Fink 2021-09-21 12:55:19 +02:00
parent 75e792b86c
commit e6315ee186
14 changed files with 227 additions and 10 deletions

34
.github/workflows/wheels.yml vendored Normal file
View File

@ -0,0 +1,34 @@
name: Build Python Wheels
on:
schedule:
push:
branches:
- master
jobs:
build_wheels:
name: Build wheels on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-20.04, windows-2019, macOS-10.15]
arch: [auto32, auto64, aarch64, ppc64le, s390x]
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
- name: Install cibuildwheel
run: python -m pip install cibuildwheel==2.1.2
- name: Build wheels
run: python -m cibuildwheel --output-dir wheelhouse
upload_wheels:
name: Upload binary wheels to PyPI
needs: [build_wheels]
steps:
uses: pypa/gh-action-pypi-publish@release/v1
with:
user: __token__
password: ${{ secrets.IMCTERMITE_GITHUB_WORKFLOW_PYPI_API_TOKEN }}

10
.gitignore vendored
View File

@ -31,3 +31,13 @@ pip/LICENSE
pip/*egg-info pip/*egg-info
pip/dist/ pip/dist/
pip/build/ pip/build/
python/README.md
python/LICENSE
python/VERSION
python/build
python/*.egg-info
python/dist
python/*.soc
python/lib/
python/*.cpp

View File

@ -211,9 +211,9 @@ channels = imcraw.get_channels(False)
print(channels) print(channels)
``` ```
A more complete [example](python/usage.py), including the methods for obtaining the A more complete [example](python/examples/usage.py), including the methods for
channels, i.a. their data and/or directly printing them to files, can be found obtaining the channels, i.a. their data and/or directly printing them to files,
in the Python folder. can be found in the `python/examples` folder.
## References ## References

24
python/IMCtermite.pxd Normal file
View File

@ -0,0 +1,24 @@
# use some C++ STL libraries
from libcpp.string cimport string
from libcpp.vector cimport vector
from libcpp cimport bool
cdef extern from "lib/imc_raw.hpp" namespace "imc":
cdef cppclass cppimctermite "imc::raw":
# constructor(s)
cppimctermite() except +
cppimctermite(string rawfile) except +
# provide raw file
void set_file(string rawfile) except +
# get JSON list of channels
vector[string] get_channels(bool json, bool data) except +
# print single channel/all channels
void print_channel(string channeluuid, string outputdir, char delimiter) except +
void print_channels(string outputdir, char delimiter) except +
void print_table(string outputfile) except +

44
python/IMCtermite.pyx Normal file
View File

@ -0,0 +1,44 @@
# distutils: language = c++
# cython: language_level = 3
from IMCtermite cimport cppimctermite
import json as jn
import decimal
cdef class imctermite:
# C++ instance of class => stack allocated (requires nullary constructor!)
cdef cppimctermite cppimc
# constructor
def __cinit__(self, string rawfile):
self.cppimc = cppimctermite(rawfile)
# provide raw file
def submit_file(self,string rawfile):
self.cppimc.set_file(rawfile)
# get JSON list of channels
def get_channels(self, bool data):
chnlst = self.cppimc.get_channels(True,data)
chnlstjn = [jn.loads(chn.decode(errors="ignore")) for chn in chnlst]
return chnlstjn
# print single channel/all channels
def print_channel(self, string channeluuid, string outputfile, char delimiter):
self.cppimc.print_channel(channeluuid,outputfile,delimiter)
def print_channels(self, string outputdir, char delimiter):
self.cppimc.print_channels(outputdir,delimiter)
# print table including channels
def print_table(self, string outputfile):
chnlst = self.cppimc.get_channels(True,True)
chnlstjn = [jn.loads(chn.decode(errors="ignore")) for chn in chnlst]
with open(outputfile.decode(),'w') as fout:
for chn in chnlstjn:
fout.write('#' +str(chn['xname']).rjust(19)+str(chn['yname']).rjust(20)+'\n')
fout.write('#'+str(chn['xunit']).rjust(19)+str(chn['yunit']).rjust(20)+'\n')
for n in range(0,len(chn['ydata'])):
fout.write(str(chn['xdata'][n]).rjust(20)+
str(chn['ydata'][n]).rjust(20)+'\n')

0
python/MANIFEST.in Normal file
View File

View File

@ -1,11 +1,11 @@
import imc_termite import IMCtermite
import json import json
import os import os
# declare and initialize instance of "imctermite" by passing a raw-file # declare and initialize instance of "imctermite" by passing a raw-file
try : try :
imcraw = imc_termite.imctermite(b"samples/exampleB.raw") imcraw = IMCtermite.imctermite(b"samples/exampleB.raw")
except RuntimeError as e : except RuntimeError as e :
raise Exception("failed to load/parse raw-file: " + str(e)) raise Exception("failed to load/parse raw-file: " + str(e))

View File

@ -1,5 +1,5 @@
import imc_termite import IMCtermite
import json import json
import os import os
@ -15,7 +15,7 @@ for fl in rawlist1:
# declare and initialize instance of "imctermite" by passing a raw-file # declare and initialize instance of "imctermite" by passing a raw-file
try : try :
imcraw = imc_termite.imctermite(fl.encode()) imcraw = IMCtermite.imctermite(fl.encode())
except RuntimeError as e : except RuntimeError as e :
raise Exception("failed to load/parse raw-file: " + str(e)) raise Exception("failed to load/parse raw-file: " + str(e))
@ -24,7 +24,7 @@ for fl in rawlist1:
print(json.dumps(channels,indent=4, sort_keys=False)) print(json.dumps(channels,indent=4, sort_keys=False))
# print the channels into a specific directory # print the channels into a specific directory
imcraw.print_channels(b"./") imcraw.print_channels(b"./",ord(','))
# print all channels in single file # print all channels in single file
imcraw.print_table(("./"+str(os.path.basename(fl).split('.')[0])+"_allchannels.csv").encode()) imcraw.print_table(("./"+str(os.path.basename(fl).split('.')[0])+"_allchannels.csv").encode())

View File

@ -1,12 +1,12 @@
import imc_termite import IMCtermite
import json import json
import os import os
import datetime import datetime
# declare and initialize instance of "imctermite" by passing a raw-file # declare and initialize instance of "imctermite" by passing a raw-file
try : try :
imcraw = imc_termite.imctermite(b"samples/sampleB.raw") imcraw = IMCtermite.imctermite(b"samples/sampleB.raw")
except RuntimeError as e : except RuntimeError as e :
raise Exception("failed to load/parse raw-file: " + str(e)) raise Exception("failed to load/parse raw-file: " + str(e))

View File

@ -0,0 +1,29 @@
from IMCtermite import imctermite
def show_results(imcraw) :
channels = imcraw.get_channels(False)
print(channels)
channelsData = imcraw.get_channels(True)
print("number of channels: " + str(len(channelsData)))
for (i,chn) in enumerate(channelsData) :
print(str(i) + " | " + chn['name'])
print(chn['xname'] + " | " + chn['xunit'])
print(chn['xdata'][:10])
print(chn['yname'] + " | " + chn['yunit'])
print(chn['ydata'][:10])
print("")
# create instance of 'imctermite'
imcraw = imctermite(b'samples/sampleA.raw')
show_results(imcraw)
# use previous instance of 'imctermite' to provide new file
imcraw.submit_file(b'samples/sampleB.raw')
show_results(imcraw)

44
python/makefile Normal file
View File

@ -0,0 +1,44 @@
GITAG := $(shell git tag -l --sort=version:refname | tail -n1 | sed 's/^v//g')
setup:
echo $(GITAG) > VERSION
cat ../README.md | grep '^# IMCtermite' -A 50000 > ./README.md
cp -r ../lib ./
cp -v ../LICENSE ./
setup-clean:
rm -vf README.md VERSION LICENSE
rm -rf lib/
build: setup
python setup.py build
build-inplace: setup
python setup.py build_ext --inplace
build-sdist: setup
python setup.py sdist
build-bdist: setup
python setup.py bdist
build-clean:
python setup.py clean --all
rm -vf imctermite*.so imctermite*.cpp
rm -vf IMCtermite*.so IMCtermite*.cpp
rm -rvf dist/ IMCtermite.egg-info/
cibuildwheel-build: setup
cibuildwheel --platform linux
cibuildwheel-clean:
rm -rvf wheelhouse/
pypi-upload:
python -m twine upload dist/$(shell ls -t dist/ | head -n1)
clean: setup build-clean cibuildwheel-clean setup-clean
run-example:
PYTHONPATH=$(pwd) python examples/usage_files.py

7
python/pyproject.toml Normal file
View File

@ -0,0 +1,7 @@
[build-system]
requires = ["setuptools", "wheel","Cython"]
build-backend = "setuptools.build_meta"
[tool.cibuildwheel]
before-all = ""

19
python/setup.cfg Normal file
View File

@ -0,0 +1,19 @@
[metadata]
name = IMCtermite
description = Enables extraction of measurement data from binary files with extension 'raw' used by proprietary software imcFAMOS/imcSTUDIO and facilitates its storage in open source file formats
long_description = file: README.md
version = file: VERSION
author = Record Evolution GmbH
author_email = mario.fink@record-evolution.de
maintainer = Record Evolution GmbH
url= 'https://github.com/RecordEvolution/IMCtermite.git'
license = MIT License
license_files = LICENSE
keywords = IMC, raw, imcFAMOS, imcSTUDIO, imcCRONOS
classifiers =
Programming Language :: Python :: 3,
License :: OSI Approved :: MIT License,
Operating System :: OS Independent
[options]

6
python/setup.py Normal file
View File

@ -0,0 +1,6 @@
from setuptools import setup
from Cython.Build import cythonize
setup(
ext_modules=cythonize(["IMCtermite.pyx"],language_level=3)
)