Skip to content

Commit

Permalink
Merge branch 'release/3.0.1'
Browse files Browse the repository at this point in the history
  • Loading branch information
wolph committed Mar 13, 2023
2 parents 30c7818 + 91c167b commit bdaa099
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 75 deletions.
14 changes: 10 additions & 4 deletions README.rst
@@ -1,15 +1,14 @@
numpy-stl
==============================================================================

.. image:: https://github.com/WoLpH/numpy-stl/actions/workflows/main.yml/badge.svg?branch=master
:alt: numpy-stl test status
:target: https://github.com/WoLpH/numpy-stl/actions/workflows/main.yml

.. image:: https://ci.appveyor.com/api/projects/status/cbv7ak2i59wf3lpj?svg=true
:alt: numpy-stl test status
:target: https://ci.appveyor.com/project/WoLpH/numpy-stl

.. image:: https://github.com/WoLpH/numpy-stl/actions/workflows/main.yml/badge.svg
:alt: numpy-stl test status
:target: https://github.com/WoLpH/numpy-stl/actions

.. image:: https://badge.fury.io/py/numpy-stl.svg
:alt: numpy-stl Pypi version
:target: https://pypi.python.org/pypi/numpy-stl
Expand All @@ -26,6 +25,13 @@ and easy.
Due to all operations heavily relying on `numpy` this is one of the fastest
STL editing libraries for Python available.

Security contact information
------------------------------------------------------------------------------

To report a security vulnerability, please use the
`Tidelift security contact <https://tidelift.com/security>`_.
Tidelift will coordinate the fix and disclosure.

Issues
------

Expand Down
7 changes: 2 additions & 5 deletions appveyor.yml
Expand Up @@ -3,12 +3,9 @@ image:

environment:
matrix:
- TOXENV: py36
- TOXENV: py37
- TOXENV: py38
# Does not work because of str of py.path
# - TOXENV: py39
# - TOXENV: py310
- TOXENV: py39
- TOXENV: py310

install:
# Download setup scripts and unzip
Expand Down
2 changes: 1 addition & 1 deletion stl/__about__.py
@@ -1,6 +1,6 @@
__package_name__ = 'numpy-stl'
__import_name__ = 'stl'
__version__ = '3.0.0'
__version__ = '3.0.1'
__author__ = 'Rick van Hattem'
__author_email__ = 'Wolph@Wol.ph'
__description__ = ' '.join('''
Expand Down
100 changes: 65 additions & 35 deletions stl/main.py
@@ -1,26 +1,34 @@
import sys
import random
import argparse
import random
import sys

from . import stl


def _get_parser(description):
parser = argparse.ArgumentParser(description=description)
parser.add_argument('infile', nargs='?', type=argparse.FileType('rb'),
default=sys.stdin, help='STL file to read')
parser.add_argument('outfile', nargs='?', type=argparse.FileType('wb'),
default=sys.stdout, help='STL file to write')
parser.add_argument(
'infile', nargs='?', type=argparse.FileType('rb'),
default=sys.stdin, help='STL file to read'
)
parser.add_argument(
'outfile', nargs='?', type=argparse.FileType('wb'),
default=sys.stdout, help='STL file to write'
)
parser.add_argument('--name', nargs='?', help='Name of the mesh')
parser.add_argument(
'-n', '--use-file-normals', action='store_true',
help='Read the normals from the file instead of recalculating them')
help='Read the normals from the file instead of recalculating them'
)
parser.add_argument(
'-r', '--remove-empty-areas', action='store_true',
help='Remove areas with 0 surface areas to prevent errors during '
'normal calculation')
parser.add_argument('-s', '--disable-speedups', action='store_true',
help='Disable Cython speedups')
'normal calculation'
)
parser.add_argument(
'-s', '--disable-speedups', action='store_true',
help='Disable Cython speedups'
)
return parser


Expand All @@ -33,24 +41,37 @@ def _get_name(args):
]

for name in names: # pragma: no branch
if name and isinstance(name, str) and not name.startswith('<'):
if not isinstance(name, str):
continue
elif name.startswith('<'): # pragma: no cover
continue
elif r'\AppData\Local\Temp' in name: # pragma: no cover
# Windows temp file
continue
else:
return name


def main():
parser = _get_parser('Convert STL files from ascii to binary and back')
parser.add_argument('-a', '--ascii', action='store_true',
help='Write ASCII file (default is binary)')
parser.add_argument('-b', '--binary', action='store_true',
help='Force binary file (for TTYs)')
parser.add_argument(
'-a', '--ascii', action='store_true',
help='Write ASCII file (default is binary)'
)
parser.add_argument(
'-b', '--binary', action='store_true',
help='Force binary file (for TTYs)'
)

args = parser.parse_args()
name = _get_name(args)
stl_file = stl.StlMesh(filename=name,
fh=args.infile,
calculate_normals=False,
remove_empty_areas=args.remove_empty_areas,
speedups=not args.disable_speedups)
stl_file = stl.StlMesh(
filename=name,
fh=args.infile,
calculate_normals=False,
remove_empty_areas=args.remove_empty_areas,
speedups=not args.disable_speedups
)

if args.binary:
mode = stl.BINARY
Expand All @@ -59,30 +80,39 @@ def main():
else:
mode = stl.AUTOMATIC

stl_file.save(name, args.outfile, mode=mode,
update_normals=not args.use_file_normals)
stl_file.save(
name, args.outfile, mode=mode,
update_normals=not args.use_file_normals
)


def to_ascii():
parser = _get_parser('Convert STL files to ASCII (text) format')
args = parser.parse_args()
name = _get_name(args)
stl_file = stl.StlMesh(filename=name, fh=args.infile,
calculate_normals=False,
remove_empty_areas=args.remove_empty_areas,
speedups=not args.disable_speedups)
stl_file.save(name, args.outfile, mode=stl.ASCII,
update_normals=not args.use_file_normals)
stl_file = stl.StlMesh(
filename=name, fh=args.infile,
calculate_normals=False,
remove_empty_areas=args.remove_empty_areas,
speedups=not args.disable_speedups
)
stl_file.save(
name, args.outfile, mode=stl.ASCII,
update_normals=not args.use_file_normals
)


def to_binary():
parser = _get_parser('Convert STL files to binary format')
args = parser.parse_args()
name = _get_name(args)
stl_file = stl.StlMesh(filename=name, fh=args.infile,
calculate_normals=False,
remove_empty_areas=args.remove_empty_areas,
speedups=not args.disable_speedups)
stl_file.save(name, args.outfile, mode=stl.BINARY,
update_normals=not args.use_file_normals)

stl_file = stl.StlMesh(
filename=name, fh=args.infile,
calculate_normals=False,
remove_empty_areas=args.remove_empty_areas,
speedups=not args.disable_speedups
)
stl_file.save(
name, args.outfile, mode=stl.BINARY,
update_normals=not args.use_file_normals
)
29 changes: 15 additions & 14 deletions tests/conftest.py
@@ -1,4 +1,5 @@
import py
import pathlib

import pytest


Expand All @@ -9,35 +10,35 @@ def pytest_generate_tests(metafunc):


@pytest.fixture(scope='session')
def cwd():
return py.path.local(__file__).dirpath()
def cwd() -> pathlib.Path:
return pathlib.Path(__file__).parent


@pytest.fixture(scope='session')
def ascii_path(cwd):
return cwd.join('stl_ascii')
def ascii_path(cwd) -> pathlib.Path:
return cwd / 'stl_ascii'


@pytest.fixture(scope='session')
def binary_path(cwd):
return cwd.join('stl_binary')
def binary_path(cwd) -> pathlib.Path:
return cwd / 'stl_binary'


@pytest.fixture(scope='session')
def three_mf_path(cwd):
return cwd.join('3mf')
def three_mf_path(cwd) -> pathlib.Path:
return cwd / '3mf'


@pytest.fixture(scope='session', params=['ascii', 'binary'])
def binary_ascii_path(request, ascii_path, binary_path):
def binary_ascii_path(request, ascii_path, binary_path) -> pathlib.Path:
return ascii_path if request.param == 'ascii' else binary_path


@pytest.fixture(scope='session')
def ascii_file(ascii_path):
return str(ascii_path.join('HalfDonut.stl'))
def ascii_file(ascii_path) -> str:
return str(ascii_path / 'HalfDonut.stl')


@pytest.fixture(scope='session')
def binary_file(binary_path):
return str(binary_path.join('HalfDonut.stl'))
def binary_file(binary_path) -> str:
return str(binary_path / 'HalfDonut.stl')
5 changes: 4 additions & 1 deletion tests/test_convert.py
@@ -1,11 +1,14 @@
# import os
import py.path
import pytest
import tempfile

from stl import stl


def _test_conversion(from_, to, mode, speedups):
# For some reason the test fails when using pathlib instead of py.path
from_ = py.path.local(from_)
to = py.path.local(to)

for name in from_.listdir():
source_file = from_.join(name)
Expand Down
8 changes: 4 additions & 4 deletions tests/test_meshProperties.py
Expand Up @@ -18,7 +18,7 @@ def test_mass_properties_for_half_donut(binary_ascii_path, speedups):
One checks the results obtained with stl
with the ones obtained with meshlab
'''
filename = binary_ascii_path.join('HalfDonut.stl')
filename = binary_ascii_path/'HalfDonut.stl'
mesh = stl.StlMesh(str(filename), speedups=speedups)
volume, cog, inertia = mesh.get_mass_properties()
assert close([volume], [2.343149])
Expand All @@ -35,7 +35,7 @@ def test_mass_properties_for_moon(binary_ascii_path, speedups):
One checks the results obtained with stl
with the ones obtained with meshlab
'''
filename = binary_ascii_path.join('Moon.stl')
filename = binary_ascii_path/'Moon.stl'
mesh = stl.StlMesh(str(filename), speedups=speedups)
volume, cog, inertia = mesh.get_mass_properties()
assert close([volume], [0.888723])
Expand All @@ -54,7 +54,7 @@ def test_mass_properties_for_star(binary_ascii_path, filename, speedups):
One checks the results obtained with stl
with the ones obtained with meshlab
'''
filename = binary_ascii_path.join(filename)
filename = binary_ascii_path/filename
if not filename.exists():
pytest.skip('STL file does not exist')
mesh = stl.StlMesh(str(filename), speedups=speedups)
Expand All @@ -74,7 +74,7 @@ def test_mass_properties_for_half_donut_with_density(
One checks the results obtained with stl
with the ones obtained with meshlab
'''
filename = binary_ascii_path.join('HalfDonut.stl')
filename = binary_ascii_path/'HalfDonut.stl'
mesh = stl.StlMesh(str(filename), speedups=speedups)
volume, mass, cog, inertia = mesh.get_mass_properties_with_density(1.23)

Expand Down
19 changes: 8 additions & 11 deletions tests/test_multiple.py
Expand Up @@ -3,9 +3,8 @@
import pytest

from stl import mesh
from stl.utils import b

_STL_FILE = '''
_STL_FILE = b'''
solid test.stl
facet normal -0.014565 0.073223 -0.002897
outer loop
Expand All @@ -16,12 +15,10 @@
endfacet
endsolid test.stl
'''
# This is split because the pycharm autoformatter breaks the tests otherwise
_STL_FILE = b(_STL_FILE.lstrip())


def test_single_stl(tmpdir, speedups):
tmp_file = tmpdir.join('tmp.stl')
tmp_file = tmpdir / 'tmp.stl'
with tmp_file.open('wb+') as fh:
fh.write(_STL_FILE)
fh.seek(0)
Expand All @@ -32,7 +29,7 @@ def test_single_stl(tmpdir, speedups):


def test_multiple_stl(tmpdir, speedups):
tmp_file = tmpdir.join('tmp.stl')
tmp_file = tmpdir / 'tmp.stl'
with tmp_file.open('wb+') as fh:
for _ in range(10):
fh.write(_STL_FILE)
Expand All @@ -48,7 +45,7 @@ def test_multiple_stl(tmpdir, speedups):


def test_single_stl_file(tmpdir, speedups):
tmp_file = tmpdir.join('tmp.stl')
tmp_file = tmpdir / 'tmp.stl'
with tmp_file.open('wb+') as fh:
fh.write(_STL_FILE)
fh.seek(0)
Expand All @@ -59,7 +56,7 @@ def test_single_stl_file(tmpdir, speedups):


def test_multiple_stl_file(tmpdir, speedups):
tmp_file = tmpdir.join('tmp.stl')
tmp_file = tmpdir / 'tmp.stl'
with tmp_file.open('wb+') as fh:
for _ in range(10):
fh.write(_STL_FILE)
Expand All @@ -76,7 +73,7 @@ def test_multiple_stl_file(tmpdir, speedups):


def test_multiple_stl_files(tmpdir, speedups):
tmp_file = tmpdir.join('tmp.stl')
tmp_file = tmpdir / 'tmp.stl'
with tmp_file.open('wb+') as fh:
fh.write(_STL_FILE)
fh.seek(0)
Expand All @@ -88,13 +85,13 @@ def test_multiple_stl_files(tmpdir, speedups):


def test_3mf_file(three_mf_path):
for m in mesh.Mesh.from_3mf_file(three_mf_path.join('Moon.3mf')):
for m in mesh.Mesh.from_3mf_file(three_mf_path / 'Moon.3mf'):
print(m)


def test_3mf_missing_file(three_mf_path):
with pytest.raises(FileNotFoundError):
for m in mesh.Mesh.from_3mf_file(three_mf_path.join('some_file.3mf')):
for m in mesh.Mesh.from_3mf_file(three_mf_path / 'some_file.3mf'):
print(m)


Expand Down

0 comments on commit bdaa099

Please sign in to comment.