Skip to content

Commit

Permalink
Merge pull request #94 from hroncok/i52
Browse files Browse the repository at this point in the history
Fix for issue #52
  • Loading branch information
wolph authored Nov 21, 2018
2 parents db98f18 + 6736fa3 commit cc201a0
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 13 deletions.
24 changes: 24 additions & 0 deletions stl/_speedups.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,18 @@ ELSE:
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

Expand Down Expand Up @@ -89,6 +101,13 @@ def ascii_read(fh, buf):
cdef size_t pos = 0
cdef State state


IF UNAME_SYSNAME == 'Linux':
cdef locale_t new_locale = newlocale(LC_NUMERIC_MASK, 'C',
<locale_t>NULL)
cdef locale_t old_locale = uselocale(new_locale)
freelocale(new_locale)

try:
state.size = len(buf)
memcpy(state.buf, <char*> buf, state.size)
Expand Down Expand Up @@ -147,6 +166,11 @@ def ascii_read(fh, buf):
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 = <Facet*>arr.data
Expand Down
16 changes: 3 additions & 13 deletions stl/stl.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import enum
import numpy
import struct
import logging
import datetime

from . import base
Expand All @@ -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
Expand Down Expand Up @@ -328,15 +324,9 @@ def from_file(cls, filename, calculate_normals=True, fh=None,
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)
Expand Down
18 changes: 18 additions & 0 deletions tests/qt-lc_numeric-reproducer
Original file line number Diff line number Diff line change
@@ -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)
39 changes: 39 additions & 0 deletions tests/test_ascii.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
import os
import pytest
import subprocess
import sys

from stl.utils import b
from stl import mesh

Expand Down Expand Up @@ -50,3 +55,37 @@ def test_scientific_notation(tmpdir, 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')

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)

if 'No module named' in out:
pytest.skip('Optional dependency PyQt5 or PySide2 not installed')

assert 'File too large' not in out
assert 'File too large' not in err
assert p.returncode == 0
6 changes: 6 additions & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,9 @@ changedir=docs
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

0 comments on commit cc201a0

Please sign in to comment.