diff -Nru numpy-stl-2.3.2/debian/changelog numpy-stl-2.9.0/debian/changelog --- numpy-stl-2.3.2/debian/changelog 2018-11-03 12:07:54.000000000 +0000 +++ numpy-stl-2.9.0/debian/changelog 2019-02-02 16:07:22.000000000 +0000 @@ -1,14 +1,24 @@ -numpy-stl (2.3.2-1build2) disco; urgency=medium +numpy-stl (2.9.0-1) unstable; urgency=medium - * No-change rebuild to build without python3.6 support. + [ Chris Lamb ] + * [54adcc4] Remove trailing whitespaces. - -- Matthias Klose Sat, 03 Nov 2018 12:07:54 +0000 + [ Bernd Zeimetz ] + * [79a2342] Update upstream source from tag 'upstream/2.9.0' + Update to upstream version '2.9.0' + with Debian dir f7694bb5345854a86fe91eca983942ea5fbfc2b4 + * [19c7978] Updating changelog. + * [8178317] Adding debian/.gitlab-ci.yml -numpy-stl (2.3.2-1build1) cosmic; urgency=medium + -- Bernd Zeimetz Sat, 02 Feb 2019 17:07:22 +0100 - * No-change rebuild to build for python3.7. +numpy-stl (2.3.2-2) unstable; urgency=medium - -- Matthias Klose Thu, 28 Jun 2018 12:36:10 +0000 + * d/control: Set Vcs-* to salsa.debian.org + * d/control: Remove ancient X-Python-Version field + * d/control: Remove ancient X-Python3-Version field + + -- Ondřej Nový Tue, 13 Feb 2018 10:13:33 +0100 numpy-stl (2.3.2-1) unstable; urgency=medium diff -Nru numpy-stl-2.3.2/debian/control numpy-stl-2.9.0/debian/control --- numpy-stl-2.3.2/debian/control 2017-10-08 11:34:31.000000000 +0000 +++ numpy-stl-2.9.0/debian/control 2019-02-02 16:07:22.000000000 +0000 @@ -15,11 +15,9 @@ # PyTest python3-pytest, python3-pytest-runner, Standards-Version: 4.1.1.0 -X-Python-Version: >= 2.7 -X-Python3-Version: >= 3.4 Homepage: https://github.com/WoLpH/numpy-stl -Vcs-Git: https://anonscm.debian.org/git/python-modules/packages/numpy-stl.git -Vcs-Browser: https://anonscm.debian.org/cgit/python-modules/packages/numpy-stl.git +Vcs-Git: https://salsa.debian.org/python-team/modules/numpy-stl.git +Vcs-Browser: https://salsa.debian.org/python-team/modules/numpy-stl Package: numpy-stl Architecture: all diff -Nru numpy-stl-2.3.2/debian/copyright numpy-stl-2.9.0/debian/copyright --- numpy-stl-2.3.2/debian/copyright 2017-10-08 11:34:31.000000000 +0000 +++ numpy-stl-2.9.0/debian/copyright 2019-02-02 16:07:22.000000000 +0000 @@ -88,4 +88,3 @@ . On Debian systems, the complete text of the GNU General Public License version 2 can be found in "/usr/share/common-licenses/GPL-2". - diff -Nru numpy-stl-2.3.2/debian/.gitlab-ci.yml numpy-stl-2.9.0/debian/.gitlab-ci.yml --- numpy-stl-2.3.2/debian/.gitlab-ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ numpy-stl-2.9.0/debian/.gitlab-ci.yml 2019-02-02 16:07:22.000000000 +0000 @@ -0,0 +1,11 @@ +image: registry.salsa.debian.org/salsa-ci-team/ci-image-git-buildpackage:latest + +pages: + stage: deploy + artifacts: + paths: + - public + script: + - gitlab-ci-git-buildpackage + - gitlab-ci-lintian + - gitlab-ci-aptly diff -Nru numpy-stl-2.3.2/debian/rules numpy-stl-2.9.0/debian/rules --- numpy-stl-2.3.2/debian/rules 2017-10-08 11:34:31.000000000 +0000 +++ numpy-stl-2.9.0/debian/rules 2019-02-02 16:07:22.000000000 +0000 @@ -22,4 +22,3 @@ --parallel rm -f stl/_speedups.c - diff -Nru numpy-stl-2.3.2/pytest.ini numpy-stl-2.9.0/pytest.ini --- numpy-stl-2.3.2/pytest.ini 2017-07-26 00:05:51.000000000 +0000 +++ numpy-stl-2.9.0/pytest.ini 2018-12-17 01:26:21.000000000 +0000 @@ -1,6 +1,8 @@ [pytest] basetemp = tmp +doctest_optionflags = NORMALIZE_WHITESPACE + python_files = stl/*.py tests/*.py @@ -11,13 +13,14 @@ --cov-report term-missing --cov-report html --no-cov-on-fail - --pep8 - --flakes + --flake8 --ignore=build -pep8ignore = +flake8-ignore = *.py W391 docs/*.py ALL -flakes-ignore = - docs/*.py ALL +looponfailroots = + stl + tests + build diff -Nru numpy-stl-2.3.2/.pyup.yml numpy-stl-2.9.0/.pyup.yml --- numpy-stl-2.3.2/.pyup.yml 1970-01-01 00:00:00.000000000 +0000 +++ numpy-stl-2.9.0/.pyup.yml 2018-12-17 01:26:21.000000000 +0000 @@ -0,0 +1,4 @@ +# autogenerated pyup.io config file +# see https://pyup.io/docs/configuration/ for all available options + +update: insecure diff -Nru numpy-stl-2.3.2/README.rst numpy-stl-2.9.0/README.rst --- numpy-stl-2.3.2/README.rst 2017-07-26 00:05:51.000000000 +0000 +++ numpy-stl-2.9.0/README.rst 2018-12-17 01:26:21.000000000 +0000 @@ -70,6 +70,7 @@ your_mesh.save('new_stl_file.stl') Plotting using `matplotlib`_ is equally easy: +------------------------------------------------------------------------------ .. code-block:: python @@ -341,16 +342,17 @@ def translate(_solid, step, padding, multiplier, axis): - if axis == 'x': - items = [0, 3, 6] - elif axis == 'y': - items = [1, 4, 7] - elif axis == 'z': - items = [2, 5, 8] - for p in _solid.points: - # point items are ((x, y, z), (x, y, z), (x, y, z)) - for i in range(3): - p[items[i]] += (step * multiplier) + (padding * multiplier) + if 'x' == axis: + items = 0, 3, 6 + elif 'y' == axis: + items = 1, 4, 7 + elif 'z' == axis: + items = 2, 5, 8 + else: + raise RuntimeError('Unknown axis %r, expected x, y or z' % axis) + + # _solid.points.shape == [:, ((x, y, z), (x, y, z), (x, y, z))] + _solid.points[:, items] += (step * multiplier) + (padding * multiplier) def copy_obj(obj, dims, num_rows, num_cols, num_layers): diff -Nru numpy-stl-2.3.2/setup.py numpy-stl-2.9.0/setup.py --- numpy-stl-2.3.2/setup.py 2017-07-26 00:05:51.000000000 +0000 +++ numpy-stl-2.9.0/setup.py 2018-12-17 01:26:21.000000000 +0000 @@ -8,39 +8,56 @@ setup_kwargs = {} -try: - import numpy - from Cython import Build - setup_kwargs['ext_modules'] = Build.cythonize([ - extension.Extension( - 'stl._speedups', - ['stl/_speedups.pyx'], - include_dirs=[numpy.get_include()], - ), - ]) +def error(*lines): + for line in lines: + print(line, file=sys.stderr) + + +try: + from stl import stl + if not hasattr(stl, 'BaseStl'): + error('ERROR', + 'You have an incompatible stl package installed' + 'Please run "pip uninstall -y stl" first') + sys.exit(1) except ImportError: - print('WARNING', file=sys.stderr) - print('Cython and Numpy is required for building extension.', - file=sys.stderr) - print('Falling back to pure Python implementation.', file=sys.stderr) + pass + + +if sys.version_info.major == 2 or sys.platform.lower() != 'win32': + try: + import numpy + from Cython import Build + + setup_kwargs['ext_modules'] = Build.cythonize([ + extension.Extension( + 'stl._speedups', + ['stl/_speedups.pyx'], + include_dirs=[numpy.get_include()], + ), + ]) + except ImportError: + error('WARNING', + 'Cython and Numpy is required for building extension.', + 'Falling back to pure Python implementation.') # To prevent importing about and thereby breaking the coverage info we use this # exec hack about = {} -with open('stl/__about__.py') as fp: - exec(fp.read(), about) +with open('stl/__about__.py') as fh: + exec(fh.read(), about) if os.path.isfile('README.rst'): - long_description = open('README.rst').read() + with open('README.rst') as fh: + long_description = fh.read() else: long_description = 'See http://pypi.python.org/pypi/%s/' % ( about['__package_name__']) install_requires = [ 'numpy', - 'nine', 'python-utils>=1.6.2', ] diff -Nru numpy-stl-2.3.2/stl/__about__.py numpy-stl-2.9.0/stl/__about__.py --- numpy-stl-2.3.2/stl/__about__.py 2017-07-26 00:05:51.000000000 +0000 +++ numpy-stl-2.9.0/stl/__about__.py 2018-12-17 01:26:21.000000000 +0000 @@ -1,6 +1,6 @@ __package_name__ = 'numpy-stl' __import_name__ = 'stl' -__version__ = '2.3.2' +__version__ = '2.8.0' __author__ = 'Rick van Hattem' __author_email__ = 'Wolph@Wol.ph' __description__ = ' '.join(''' diff -Nru numpy-stl-2.3.2/stl/base.py numpy-stl-2.9.0/stl/base.py --- numpy-stl-2.3.2/stl/base.py 2017-07-26 00:05:51.000000000 +0000 +++ numpy-stl-2.9.0/stl/base.py 2018-12-17 01:26:21.000000000 +0000 @@ -4,7 +4,10 @@ import math import numpy import logging -import collections +try: # pragma: no cover + from collections import abc +except ImportError: # pragma: no cover + import collections as abc from python_utils import logger @@ -44,10 +47,10 @@ @classmethod def map(cls, value): - if value and value in cls: - pass - elif value: + if value is True: value = cls.SINGLE + elif value and value in cls: + pass else: value = cls.NONE @@ -74,7 +77,7 @@ @logged -class BaseMesh(logger.Logged, collections.Mapping): +class BaseMesh(logger.Logged, abc.Mapping): ''' Mesh object with easy access to the vectors through v0, v1 and v2. The normals, areas, min, max and units are calculated automatically. @@ -105,24 +108,33 @@ >>> mesh.v1[0] += 2 >>> # Check item 0 (contains v0, v1 and v2) - >>> mesh[0] - array([ 1., 1., 1., 2., 2., 2., 0., 0., 0.], dtype=float32) - >>> mesh.vectors[0] # doctest: +NORMALIZE_WHITESPACE - array([[ 1., 1., 1.], - [ 2., 2., 2.], - [ 0., 0., 0.]], dtype=float32) - >>> mesh.v0[0] - array([ 1., 1., 1.], dtype=float32) - >>> mesh.points[0] - array([ 1., 1., 1., 2., 2., 2., 0., 0., 0.], dtype=float32) - >>> mesh.data[0] # doctest: +NORMALIZE_WHITESPACE - ([ 0., 0., 0.], [[ 1., 1., 1.], [ 2., 2., 2.], [ 0., 0., 0.]], [0]) - >>> mesh.x[0] - array([ 1., 2., 0.], dtype=float32) + >>> assert numpy.array_equal( + ... mesh[0], + ... numpy.array([1., 1., 1., 2., 2., 2., 0., 0., 0.])) + >>> assert numpy.array_equal( + ... mesh.vectors[0], + ... numpy.array([[1., 1., 1.], + ... [2., 2., 2.], + ... [0., 0., 0.]])) + >>> assert numpy.array_equal( + ... mesh.v0[0], + ... numpy.array([1., 1., 1.])) + >>> assert numpy.array_equal( + ... mesh.points[0], + ... numpy.array([1., 1., 1., 2., 2., 2., 0., 0., 0.])) + >>> assert numpy.array_equal( + ... mesh.data[0], + ... numpy.array(( + ... [0., 0., 0.], + ... [[1., 1., 1.], [2., 2., 2.], [0., 0., 0.]], + ... [0]), + ... dtype=BaseMesh.dtype)) + >>> assert numpy.array_equal(mesh.x[0], numpy.array([1., 2., 0.])) >>> mesh[0] = 3 - >>> mesh[0] - array([ 3., 3., 3., 3., 3., 3., 3., 3., 3.], dtype=float32) + >>> assert numpy.array_equal( + ... mesh[0], + ... numpy.array([3., 3., 3., 3., 3., 3., 3., 3., 3.])) >>> len(mesh) == len(list(mesh)) True @@ -315,6 +327,22 @@ areas = .5 * numpy.sqrt((self.normals ** 2).sum(axis=1)) self.areas = areas.reshape((areas.size, 1)) + def check(self): + '''Check the mesh is valid or not''' + return self.is_closed() + + def is_closed(self): + """Check the mesh is closed or not""" + if (self.normals.sum(axis=0) >= 1e-4).any(): + self.warning(''' + Your mesh is not closed, the mass methods will not function + correctly on this mesh. For more info: + https://github.com/WoLpH/numpy-stl/issues/69 + '''.strip()) + return False + else: + return True + def get_mass_properties(self): ''' Evaluate and return a tuple with the following elements: @@ -325,6 +353,8 @@ Documentation can be found here: http://www.geometrictools.com/Documentation/PolyhedralMassProperties.pdf ''' + self.check() + def subexpression(x): w0, w1, w2 = x[:, 0], x[:, 1], x[:, 2] temp0 = w0 + w1 @@ -421,7 +451,7 @@ [2 * (bc - ad), aa + cc - bb - dd, 2 * (cd + ab)], [2 * (bd + ac), 2 * (cd - ab), aa + dd - bb - cc]]) - def rotate(self, axis, theta, point=None): + def rotate(self, axis, theta=0, point=None): ''' Rotate the matrix over the given axis by the given theta (angle) @@ -442,6 +472,13 @@ if not theta: return + self.rotate_using_matrix(self.rotation_matrix(axis, theta), point) + + def rotate_using_matrix(self, rotation_matrix, point=None): + # No need to rotate if there is no actual rotation + if not rotation_matrix.any(): + return + if isinstance(point, (numpy.ndarray, list, tuple)) and len(point) == 3: point = numpy.asarray(point) elif point is None: @@ -451,12 +488,6 @@ else: raise TypeError('Incorrect type for point', point) - rotation_matrix = self.rotation_matrix(axis, theta) - - # No need to rotate if there is no actual rotation - if not rotation_matrix.any(): - return - def _rotate(matrix): if point.any(): # Translate while rotating diff -Nru numpy-stl-2.3.2/stl/_speedups.pyx numpy-stl-2.9.0/stl/_speedups.pyx --- numpy-stl-2.3.2/stl/_speedups.pyx 2017-07-26 00:05:51.000000000 +0000 +++ numpy-stl-2.9.0/stl/_speedups.pyx 2018-12-17 01:26:21.000000000 +0000 @@ -1,13 +1,25 @@ from libc.stdio cimport * from libc.string cimport memcpy, strcmp, strstr, strcpy -IF UNAME_SYSNAME == u"Windows": - cdef extern from "io.h": +IF UNAME_SYSNAME == 'Windows': + cdef extern from 'io.h': int dup(int fd) ELSE: - cdef extern from "unistd.h": + cdef extern from 'unistd.h': int dup(int fd) +IF UNAME_SYSNAME == 'Linux': + cdef extern from 'locale.h': + ctypedef struct locale_t: + pass + + locale_t uselocale(locale_t __dataset) + locale_t newlocale(int __category_mask, const char *__locale, + locale_t __base) + void freelocale(locale_t __dataset) + + enum: LC_NUMERIC_MASK + import numpy as np cimport numpy as np @@ -45,18 +57,21 @@ cdef char current; while True: if state.pos == state.size: - if feof(state.fp): if line_pos != 0: state.line[line_pos] = '\0' return state.line - raise RuntimeError(state.recoverable, - "Unexpected EOF") + raise RuntimeError(state.recoverable, 'Unexpected EOF') state.size = fread(state.buf, 1, BUF_SIZE, state.fp) state.pos = 0 state.recoverable = 0 + if line_pos == LINE_SIZE: + raise RuntimeError( + state.recoverable, 'Line longer than %d, probably non-ascii' % + LINE_SIZE) + current = state.buf[state.pos] state.pos += 1 @@ -86,6 +101,13 @@ cdef size_t pos = 0 cdef State state + + IF UNAME_SYSNAME == 'Linux': + cdef locale_t new_locale = newlocale(LC_NUMERIC_MASK, 'C', + NULL) + cdef locale_t old_locale = uselocale(new_locale) + freelocale(new_locale) + try: state.size = len(buf) memcpy(state.buf, buf, state.size) @@ -97,9 +119,9 @@ line = readline(&state) - if strstr(line, "solid") != line: + if strstr(line, 'solid') != line: raise RuntimeError(state.recoverable, - "Solid name not found (%i:%s)" % (state.line_num, line)) + 'Solid name not found (%i:%s)' % (state.line_num, line)) strcpy(name, line+5) @@ -108,26 +130,26 @@ line = readline(&state) line = state.line - if strstr(line, "endsolid") != NULL: + if strstr(line, 'endsolid') != NULL: arr.resize(facet - arr.data, refcheck=False) return (name).strip(), arr - if strcmp(line, "color") == 0: + if strcmp(line, 'color') == 0: readline(&state) continue - elif sscanf(line, "%*s %*s %f %f %f", + elif sscanf(line, '%*s %*s %e %e %e', facet.n, facet.n+1, facet.n+2) != 3: raise RuntimeError(state.recoverable, - "Can't read normals (%i:%s)" % (state.line_num, line)) + 'Cannot read normals (%i:%s)' % (state.line_num, line)) readline(&state) # outer loop for i in range(3): line = readline(&state) - if sscanf(line, "%*s %f %f %f\n", + if sscanf(line, '%*s %e %e %e', facet.v[i], facet.v[i]+1, facet.v[i]+2) != 3: raise RuntimeError(state.recoverable, - "Can't read vertex (%i:%s)" % (state.line_num, line)) + 'Cannot read vertex (%i:%s)' % (state.line_num, line)) readline(&state) # endloop readline(&state) # endfacet @@ -144,6 +166,11 @@ fclose(state.fp) fh.seek(pos, SEEK_SET) + IF UNAME_SYSNAME == 'Linux': + uselocale(old_locale) + freelocale(old_locale) + + def ascii_write(fh, name, np.ndarray[Facet, mode = 'c', cast=True] arr): cdef FILE* fp cdef Facet* facet = arr.data @@ -156,13 +183,13 @@ fprintf(fp, 'solid %s\n', name) while facet != end: fprintf(fp, - "facet normal %f %f %f\n" - " outer loop\n" - " vertex %f %f %f\n" - " vertex %f %f %f\n" - " vertex %f %f %f\n" - " endloop\n" - "endfacet\n", + 'facet normal %f %f %f\n' + ' outer loop\n' + ' vertex %f %f %f\n' + ' vertex %f %f %f\n' + ' vertex %f %f %f\n' + ' endloop\n' + 'endfacet\n', facet.n[0], facet.n[1], facet.n[2], facet.v[0][0], facet.v[0][1], facet.v[0][2], facet.v[1][0], facet.v[1][1], facet.v[1][2], diff -Nru numpy-stl-2.3.2/stl/stl.py numpy-stl-2.9.0/stl/stl.py --- numpy-stl-2.3.2/stl/stl.py 2017-07-26 00:05:51.000000000 +0000 +++ numpy-stl-2.9.0/stl/stl.py 2018-12-17 01:26:21.000000000 +0000 @@ -6,7 +6,6 @@ import enum import numpy import struct -import logging import datetime from . import base @@ -20,9 +19,6 @@ _speedups = None -logger = logging.getLogger(__name__) - - class Mode(enum.IntEnum): #: Automatically detect whether the output is a TTY, if so, write ASCII #: otherwise write BINARY @@ -74,6 +70,10 @@ name, data = cls._load_ascii( fh, header, speedups=speedups) except RuntimeError as exception: + # Disable fallbacks in ASCII mode + if mode is ASCII: + raise + (recoverable, e) = exception.args # If we didn't read beyond the header the stream is still # readable through the binary reader @@ -177,12 +177,6 @@ return b(line) line = get() - if not line.startswith(b('solid ')) and line.startswith(b('solid')): - cls.warning('ASCII STL files should start with solid . ' - 'The application that produced this STL file may be ' - 'faulty, please report this error. The erroneous ' - 'line: %r', line) - if not lines: raise RuntimeError(recoverable[0], 'No lines found, impossible to read') @@ -210,11 +204,13 @@ except AssertionError as e: # pragma: no cover raise RuntimeError(recoverable[0], e) except StopIteration: - raise + return @classmethod def _load_ascii(cls, fh, header, speedups=True): - if _speedups and speedups: + # The speedups module is covered by travis but it can't be tested in + # all environments, this makes coverage checks easier + if _speedups and speedups: # pragma: no cover return _speedups.ascii_read(fh, header) else: iterator = cls._ascii_reader(fh, header) @@ -259,7 +255,7 @@ pass def _write_ascii(self, fh, name): - if _speedups and self.speedups: + if _speedups and self.speedups: # pragma: no cover _speedups.ascii_write(fh, b(name), self.data) else: def p(s, file): @@ -315,22 +311,16 @@ :param str filename: The file to load :param bool calculate_normals: Whether to update the normals :param file fh: The file handle to open - :param dict \**kwargs: The same as for :py:class:`stl.mesh.Mesh` + :param dict kwargs: The same as for :py:class:`stl.mesh.Mesh` ''' if fh: name, data = cls.load( fh, mode=mode, speedups=speedups) else: - try: - with open(filename, 'rb') as fh: - name, data = cls.load( - fh, mode=mode, speedups=speedups) - except AssertionError: # pragma: no cover - logger.warn('Unable to read the file with speedups, retrying') - with open(filename, 'rb') as fh: - name, data = cls.load( - fh, mode=Mode.ASCII, speedups=False) + with open(filename, 'rb') as fh: + name, data = cls.load( + fh, mode=mode, speedups=speedups) return cls(data, calculate_normals, name=name, speedups=speedups, **kwargs) @@ -340,10 +330,13 @@ mode=ASCII, speedups=True, **kwargs): '''Load multiple meshes from a STL file + Note: mode is hardcoded to ascii since binary stl files do not support + the multi format + :param str filename: The file to load :param bool calculate_normals: Whether to update the normals :param file fh: The file handle to open - :param dict \**kwargs: The same as for :py:class:`stl.mesh.Mesh` + :param dict kwargs: The same as for :py:class:`stl.mesh.Mesh` ''' if fh: close = False @@ -357,7 +350,7 @@ name, data = raw_data yield cls(data, calculate_normals, name=name, speedups=speedups, **kwargs) - raw_data = cls.load(fh, mode=mode, + raw_data = cls.load(fh, mode=ASCII, speedups=speedups) finally: diff -Nru numpy-stl-2.3.2/tests/qt-lc_numeric-reproducer numpy-stl-2.9.0/tests/qt-lc_numeric-reproducer --- numpy-stl-2.3.2/tests/qt-lc_numeric-reproducer 1970-01-01 00:00:00.000000000 +0000 +++ numpy-stl-2.9.0/tests/qt-lc_numeric-reproducer 2018-12-17 01:26:21.000000000 +0000 @@ -0,0 +1,18 @@ +from __future__ import print_function + +import os.path +import sys + +from stl import mesh + +try: + from PySide2 import QtWidgets +except ImportError: + from PyQt5 import QtWidgets + +app = QtWidgets.QApplication([]) + +dir_path = os.path.dirname(os.path.realpath(__file__)) +stl_path = os.path.join(dir_path, 'stl_ascii/Star.stl') + +your_mesh = mesh.Mesh.from_file(stl_path, speedups=True) diff -Nru numpy-stl-2.3.2/tests/requirements.txt numpy-stl-2.9.0/tests/requirements.txt --- numpy-stl-2.3.2/tests/requirements.txt 2017-07-26 00:05:51.000000000 +0000 +++ numpy-stl-2.9.0/tests/requirements.txt 2018-12-17 01:26:21.000000000 +0000 @@ -10,8 +10,7 @@ pytest pytest-cache pytest-cov -pytest-flakes -pytest-pep8 +pytest-flake8 python-utils Sphinx flake8 Binary files /tmp/tmptnX2Xp/fzmC0qWXp3/numpy-stl-2.3.2/tests/stl_binary/rear_case.stl and /tmp/tmptnX2Xp/SN_oh2r79w/numpy-stl-2.9.0/tests/stl_binary/rear_case.stl differ diff -Nru numpy-stl-2.3.2/tests/stl_corruption.py numpy-stl-2.9.0/tests/stl_corruption.py --- numpy-stl-2.3.2/tests/stl_corruption.py 2017-07-26 00:05:51.000000000 +0000 +++ numpy-stl-2.9.0/tests/stl_corruption.py 2018-12-17 01:26:21.000000000 +0000 @@ -1,4 +1,5 @@ from __future__ import print_function +import numpy import pytest import struct @@ -127,3 +128,17 @@ fh.seek(0) mesh.Mesh.from_file(str(tmp_file), fh=fh, speedups=speedups) + +def test_duplicate_polygons(): + data = numpy.zeros(3, dtype=mesh.Mesh.dtype) + data['vectors'][0] = numpy.array([[0, 0, 0], + [1, 0, 0], + [0, 1, 1.]]) + data['vectors'][0] = numpy.array([[0, 0, 0], + [2, 0, 0], + [0, 2, 1.]]) + data['vectors'][0] = numpy.array([[0, 0, 0], + [3, 0, 0], + [0, 3, 1.]]) + + assert not mesh.Mesh(data, remove_empty_areas=False).check() diff -Nru numpy-stl-2.3.2/tests/test_ascii.py numpy-stl-2.9.0/tests/test_ascii.py --- numpy-stl-2.3.2/tests/test_ascii.py 2017-07-26 00:05:51.000000000 +0000 +++ numpy-stl-2.9.0/tests/test_ascii.py 2018-12-17 01:26:21.000000000 +0000 @@ -1,3 +1,9 @@ +import os +import sys +import pytest +import warnings +import subprocess + from stl.utils import b from stl import mesh @@ -26,3 +32,71 @@ assert test_mesh.name == b(name) +def test_scientific_notation(tmpdir, speedups): + name = 'just some very long name which will not fit within the standard' + name += name + _stl_file = (''' + solid %s + facet normal 1.014565e-10 7.3223e-5 -10 + outer loop + vertex 0.399344 0.461940 1.044090e-5 + vertex 5.00000e-5 5.00000e-5 1.500000e-3 + vertex 0 2.22045e-15 -10 + endloop + endfacet + endsolid + ''' % name).lstrip() + + tmp_file = tmpdir.join('tmp.stl') + with tmp_file.open('wb+') as fh: + fh.write(b(_stl_file)) + fh.seek(0) + test_mesh = mesh.Mesh.from_file(str(tmp_file), fh=fh, + speedups=speedups) + assert test_mesh.name == b(name) + + +@pytest.mark.skipif(sys.platform.startswith('win'), + reason='Only makes sense on Unix') +def test_use_with_qt_with_custom_locale_decimal_delimeter(speedups): + if not speedups: + pytest.skip('Only makes sense with speedups') + + try: + from PySide2 import QtWidgets + except ImportError: + try: + from PyQt5 import QtWidgets + except ImportError: + warnings.warn( + 'Unable to import PySide2/PyQt5, skipping locale tests', + ImportWarning, + ) + pytest.skip('PySide2/PyQt5 missing') + assert QtWidgets + + dir_path = os.path.dirname(os.path.realpath(__file__)) + script_path = os.path.join(dir_path, 'qt-lc_numeric-reproducer') + + env = os.environ.copy() + env['LC_NUMERIC'] = 'cs_CZ.utf-8' + + prefix = tuple() + if sys.platform.startswith('linux'): + prefix = ('xvfb-run', '-a') + + p = subprocess.Popen(prefix + (sys.executable, script_path), + env=env, + universal_newlines=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + out, err = p.communicate() + + # Unable to read the file with speedups, retrying + # https://github.com/WoLpH/numpy-stl/issues/52 + sys.stdout.write(out) + sys.stderr.write(err) + + assert 'File too large' not in out + assert 'File too large' not in err + assert p.returncode == 0 diff -Nru numpy-stl-2.3.2/tests/test_binary.py numpy-stl-2.9.0/tests/test_binary.py --- numpy-stl-2.3.2/tests/test_binary.py 1970-01-01 00:00:00.000000000 +0000 +++ numpy-stl-2.9.0/tests/test_binary.py 2018-12-17 01:26:21.000000000 +0000 @@ -0,0 +1,26 @@ +import pytest +from stl import mesh, Mode + + +@pytest.mark.parametrize('mode', [Mode.BINARY, Mode.AUTOMATIC]) +def test_ascii_like_binary(tmpdir, speedups, mode): + _test(tmpdir, speedups, mode, False) + _test(tmpdir, speedups, mode, True) + + +def test_binary_in_ascii_mode(tmpdir, speedups): + with pytest.raises(RuntimeError): + _test(tmpdir, speedups, mode=Mode.ASCII, use_filehandle=False) + + with pytest.raises(RuntimeError): + _test(tmpdir, speedups, mode=Mode.ASCII, use_filehandle=True) + + +def _test(tmpdir, speedups, mode, use_filehandle=True): + if use_filehandle: + with open('tests/stl_binary/rear_case.stl', 'rb') as fh: + mesh.Mesh.from_file('rear_case.stl', fh=fh, speedups=speedups, + mode=mode) + else: + mesh.Mesh.from_file('tests/stl_binary/rear_case.stl', + speedups=speedups, mode=mode) diff -Nru numpy-stl-2.3.2/tests/test_mesh.py numpy-stl-2.9.0/tests/test_mesh.py --- numpy-stl-2.3.2/tests/test_mesh.py 2017-07-26 00:05:51.000000000 +0000 +++ numpy-stl-2.9.0/tests/test_mesh.py 2018-12-17 01:26:21.000000000 +0000 @@ -33,12 +33,9 @@ mesh = Mesh(data, remove_empty_areas=False) mesh.update_units() - assert (mesh.areas == [.5, .5]).all() - assert (mesh.normals == [[0, 0, 1.], - [0, 0, -1.]]).all() - - assert (mesh.units == [[0, 0, 1], - [0, 0, -1]]).all() + assert numpy.allclose(mesh.areas, [.5, .5]) + assert numpy.allclose(mesh.normals, [[0, 0, 1.], [0, 0, -1.]]) + assert numpy.allclose(mesh.units, [[0, 0, 1], [0, 0, -1]]) def test_units_3d(): @@ -51,7 +48,7 @@ mesh.update_units() assert (mesh.areas - 2 ** .5) < 0.0001 - assert (mesh.normals == [0, -1, 1]).all() + assert numpy.allclose(mesh.normals, [0, -1, 1]) units = mesh.units[0] assert units[0] == 0 @@ -102,28 +99,28 @@ mesh = Mesh(data, remove_duplicate_polygons=True) assert mesh.data.size == 3 - assert (mesh.vectors[0] == numpy.array([[1, 0, 0], - [0, 0, 0], - [0, 0, 0]])).all() - assert (mesh.vectors[1] == numpy.array([[2, 0, 0], - [0, 0, 0], - [0, 0, 0]])).all() - assert (mesh.vectors[2] == numpy.array([[0, 0, 0], - [0, 0, 0], - [0, 0, 0]])).all() + assert numpy.allclose(mesh.vectors[0], numpy.array([[1, 0, 0], + [0, 0, 0], + [0, 0, 0]])) + assert numpy.allclose(mesh.vectors[1], numpy.array([[2, 0, 0], + [0, 0, 0], + [0, 0, 0]])) + assert numpy.allclose(mesh.vectors[2], numpy.array([[0, 0, 0], + [0, 0, 0], + [0, 0, 0]])) mesh = Mesh(data, remove_duplicate_polygons=RemoveDuplicates.ALL) assert mesh.data.size == 3 - assert (mesh.vectors[0] == numpy.array([[1, 0, 0], - [0, 0, 0], - [0, 0, 0]])).all() - assert (mesh.vectors[1] == numpy.array([[2, 0, 0], - [0, 0, 0], - [0, 0, 0]])).all() - assert (mesh.vectors[2] == numpy.array([[0, 0, 0], - [0, 0, 0], - [0, 0, 0]])).all() + assert numpy.allclose(mesh.vectors[0], numpy.array([[1, 0, 0], + [0, 0, 0], + [0, 0, 0]])) + assert numpy.allclose(mesh.vectors[1], numpy.array([[2, 0, 0], + [0, 0, 0], + [0, 0, 0]])) + assert numpy.allclose(mesh.vectors[2], numpy.array([[0, 0, 0], + [0, 0, 0], + [0, 0, 0]])) def test_remove_all_duplicate_polygons(): diff -Nru numpy-stl-2.3.2/tests/test_rotate.py numpy-stl-2.9.0/tests/test_rotate.py --- numpy-stl-2.3.2/tests/test_rotate.py 2017-07-26 00:05:51.000000000 +0000 +++ numpy-stl-2.9.0/tests/test_rotate.py 2018-12-17 01:26:21.000000000 +0000 @@ -49,14 +49,16 @@ # substracting .5 data['vectors'] += .5 - assert (mesh.vectors == numpy.array([ + # We use a slightly higher absolute tolerance here, for ppc64le + # https://github.com/WoLpH/numpy-stl/issues/78 + assert numpy.allclose(mesh.vectors, numpy.array([ [[1, 0, 0], [0, 1, 0], [0, 0, 0]], [[0, 1, 0], [1, 0, 0], [1, 1, 0]], [[0, 1, 1], [0, 1, 0], [1, 1, 1]], [[1, 1, 0], [0, 1, 0], [1, 1, 1]], [[0, 0, 1], [0, 1, 1], [0, 1, 0]], [[0, 0, 1], [0, 0, 0], [0, 1, 0]], - ])).all() + ]), atol=1e-07) def test_rotation_over_point(): @@ -94,6 +96,27 @@ mesh.rotate([1, 0, 0], math.radians(180), point='x') +def test_double_rotation(): + # Create a single face + data = numpy.zeros(1, dtype=Mesh.dtype) + + data['vectors'][0] = numpy.array([[1, 0, 0], + [0, 1, 0], + [0, 0, 1]]) + + mesh = Mesh(data, remove_empty_areas=False) + + rotation_matrix = mesh.rotation_matrix([1, 0, 0], math.radians(180)) + combined_rotation_matrix = numpy.dot(rotation_matrix, rotation_matrix) + + mesh.rotate_using_matrix(combined_rotation_matrix) + utils.array_equals( + mesh.vectors, + numpy.array([[[1., 0., 0.], + [0., 1., 0.], + [0., 0., 1.]]])) + + def test_no_rotation(): # Create a single face data = numpy.zeros(1, dtype=Mesh.dtype) @@ -106,13 +129,13 @@ # Rotate by 0 degrees mesh.rotate([0.5, 0.0, 0.0], math.radians(0)) - assert (mesh.vectors == numpy.array([ - [[0, 1, 1], [1, 0, 1], [0, 0, 1]]])).all() + assert numpy.allclose(mesh.vectors, numpy.array([ + [[0, 1, 1], [1, 0, 1], [0, 0, 1]]])) # Use a zero rotation matrix mesh.rotate([0.0, 0.0, 0.0], math.radians(90)) - assert (mesh.vectors == numpy.array([ - [[0, 1, 1], [1, 0, 1], [0, 0, 1]]])).all() + assert numpy.allclose(mesh.vectors, numpy.array([ + [[0, 1, 1], [1, 0, 1], [0, 0, 1]]])) def test_no_translation(): @@ -123,13 +146,13 @@ [0, 0, 1]]) mesh = Mesh(data, remove_empty_areas=False) - assert (mesh.vectors == numpy.array([ - [[0, 1, 1], [1, 0, 1], [0, 0, 1]]])).all() + assert numpy.allclose(mesh.vectors, numpy.array([ + [[0, 1, 1], [1, 0, 1], [0, 0, 1]]])) # Translate mesh with a zero vector mesh.translate([0.0, 0.0, 0.0]) - assert (mesh.vectors == numpy.array([ - [[0, 1, 1], [1, 0, 1], [0, 0, 1]]])).all() + assert numpy.allclose(mesh.vectors, numpy.array([ + [[0, 1, 1], [1, 0, 1], [0, 0, 1]]])) def test_translation(): @@ -140,13 +163,13 @@ [0, 0, 1]]) mesh = Mesh(data, remove_empty_areas=False) - assert (mesh.vectors == numpy.array([ - [[0, 1, 1], [1, 0, 1], [0, 0, 1]]])).all() + assert numpy.allclose(mesh.vectors, numpy.array([ + [[0, 1, 1], [1, 0, 1], [0, 0, 1]]])) # Translate mesh with vector [1, 2, 3] mesh.translate([1.0, 2.0, 3.0]) - assert (mesh.vectors == numpy.array([ - [[1, 3, 4], [2, 2, 4], [1, 2, 4]]])).all() + assert numpy.allclose(mesh.vectors, numpy.array([ + [[1, 3, 4], [2, 2, 4], [1, 2, 4]]])) def test_no_transformation(): @@ -157,14 +180,14 @@ [0, 0, 1]]) mesh = Mesh(data, remove_empty_areas=False) - assert (mesh.vectors == numpy.array([ - [[0, 1, 1], [1, 0, 1], [0, 0, 1]]])).all() + assert numpy.allclose(mesh.vectors, numpy.array([ + [[0, 1, 1], [1, 0, 1], [0, 0, 1]]])) # Transform mesh with identity matrix mesh.transform(numpy.eye(4)) - assert (mesh.vectors == numpy.array([ - [[0, 1, 1], [1, 0, 1], [0, 0, 1]]])).all() - assert numpy.all(mesh.areas == 0.5) + assert numpy.allclose(mesh.vectors, numpy.array([ + [[0, 1, 1], [1, 0, 1], [0, 0, 1]]])) + assert numpy.allclose(mesh.areas, 0.5) def test_transformation(): @@ -175,14 +198,14 @@ [0, 0, 1]]) mesh = Mesh(data, remove_empty_areas=False) - assert (mesh.vectors == numpy.array([ - [[0, 1, 1], [1, 0, 1], [0, 0, 1]]])).all() + assert numpy.allclose(mesh.vectors, numpy.array([ + [[0, 1, 1], [1, 0, 1], [0, 0, 1]]])) # Transform mesh with identity matrix tr = numpy.zeros((4, 4)) tr[0:3, 0:3] = Mesh.rotation_matrix([0, 0, 1], 0.5 * numpy.pi) tr[0:3, 3] = [1, 2, 3] mesh.transform(tr) - assert (mesh.vectors == numpy.array([ - [[0, 2, 4], [1, 3, 4], [1, 2, 4]]])).all() - assert numpy.all(mesh.areas == 0.5) + assert numpy.allclose(mesh.vectors, numpy.array([ + [[0, 2, 4], [1, 3, 4], [1, 2, 4]]])) + assert numpy.allclose(mesh.areas, 0.5) diff -Nru numpy-stl-2.3.2/tox.ini numpy-stl-2.9.0/tox.ini --- numpy-stl-2.3.2/tox.ini 2017-07-26 00:05:51.000000000 +0000 +++ numpy-stl-2.9.0/tox.ini 2018-12-17 01:26:21.000000000 +0000 @@ -1,5 +1,5 @@ [tox] -envlist = {py27,py33,py34,py35,py36}-{windows-32,windows-64,nix}, docs, flake8 +envlist = {py27,py33,py34,py35,py36,py37}-{windows-32,windows-64,nix}, docs, flake8 skip_missing_interpreters = True [testenv] @@ -12,6 +12,7 @@ py34-nix: python3.4 py35-nix: python3.5 py36-nix: python3.6 + py37-nix: python3.7 py27-windows-32: C:\\Python27\\python.exe py27-windows-64: C:\\Python27-x64\\python.exe py34-windows-32: C:\\Python34\\python.exe @@ -20,6 +21,8 @@ py35-windows-64: C:\\Python35-x64\\python.exe py36-windows-32: C:\\Python36\\python.exe py36-windows-64: C:\\Python36-x64\\python.exe + py37-windows-32: C:\\Python37\\python.exe + py37-windows-64: C:\\Python37-x64\\python.exe [testenv:flake8] basepython=python @@ -31,3 +34,9 @@ commands= sphinx-build -b html -d {envtmpdir}/doctrees . {envtmpdir}/html # sphinx-build -W -b html -d {envtmpdir}/doctrees . {envtmpdir}/html + +[testenv:py36-nix] +# one optional test has PyQt5 dep, only test that once +deps = + -rtests/requirements.txt + PyQt5 diff -Nru numpy-stl-2.3.2/.travis.yml numpy-stl-2.9.0/.travis.yml --- numpy-stl-2.3.2/.travis.yml 2017-07-26 00:05:51.000000000 +0000 +++ numpy-stl-2.9.0/.travis.yml 2018-12-17 01:26:21.000000000 +0000 @@ -1,6 +1,6 @@ sudo: false language: python -python: 3.5 +python: 3.6 cache: - pip - directory: @@ -13,6 +13,13 @@ - TOX_ENV=py34-nix - TOX_ENV=py35-nix - TOX_ENV=py36-nix +matrix: + include: + - env: TOX_ENV=py37-nix + python: '3.7-dev' + install: pip install coveralls flake8 tox + # be more verbose not to timeout: + script: tox -vv -e $TOX_ENV install: - pip install -r tests/requirements.txt - pip install coveralls flake8 tox @@ -21,6 +28,8 @@ - tox -e $TOX_ENV after_success: - coveralls +- pip install codecov +- codecov before_script: flake8 --ignore=W391 stl tests notifications: email: