Merge branch 'pymod' into net-extract

This commit is contained in:
Matthias Koefferlein 2018-09-26 21:40:23 +02:00
commit c75e67268b
21 changed files with 481 additions and 53 deletions

View File

@ -9,9 +9,20 @@ For more details see http://www.klayout.org.
## Building requirements
Building on Linux:
* Qt 4.7 or later (4.6 with some restrictions) or Qt 5
* gcc 4.6 or later or clang 3.8 or later
Building on Windows with MSYS2:
* MSYS2 with gcc, Qt4 or 5, zlib, ruby and python packages installed
Building on Windows with MSVC 2017:
* MSVC 2017
* Build requisites from klayout-kit
For more build instructions see http://www.klayout.de/build.html.
## Build options
@ -25,16 +36,16 @@ For more build instructions see http://www.klayout.de/build.html.
### Plain building for Qt4
./build.sh
./build.sh
### Plain building for Qt5
./build.sh -qt5
./build.sh -qt5
### Building without Qt binding
./build.sh -without-qtbinding
### Debug build
./build.sh -debug
@ -63,8 +74,8 @@ For more build instructions see http://www.klayout.de/build.html.
### Pass make options
./build.sh -j4
./build.sh -j4
(for running 4 jobs in parallel)
### More options
@ -80,9 +91,54 @@ Go to the build directory (i.e. "bin-release") and enter
export TESTTMP=testtmp # path to a directory that will hold temporary data (will be created)
export TESTSRC=.. # path to the source directory
./ut_runner
For more options use
./ut_runner -h
## Build instructions (Windows, MSYS2)
From the MSYS2 MinGW bash (32 bit or 64 bit) use the same commands as for Linux to build the
binaries.
## Build instructions (Windows, MSVC 2017)
The combination supported and tested was Qt 5.11/MSVC 2017 64bit.
It's sufficient to install the build tools from MSVC's community edition.
A build script similar to build.sh is provided for Windows
(build.bat).
For details about this build script use
```
build.bat -h
```
For MSVC builds a number of third party libraries are required:
* Ruby
* Python
* zlib
* expat
* curl
* pthread-win
The "klayout-bits4msvc2017" project (https://github.com/klayoutmatthias/klayout_bits4msvc2017) targets towards providing a binary distribution for this purpose.
See the release notes there for download links. Download the .zip archive from there and unpack it to some folder, e.g. "c:\klayout-bits".
The build script needs the path to this package. "qmake" and (for obtaining the build version) "git" should be in the path. If qmake is not in the path, you can use "build.bat -qmake ..." to specify qmake's path.
Here is an example for the build.bat call:
```
build.bat -bits c:\klayout-bits
```
The 3rd party bits kit can also be used to build the Python
standalone package on setuptools. Specify the full path to the 3rd party package up to the compiler and architecture. On 64bit with the bits package installed in "c:\klayout-bits" the build call is this:
```
set KLAYOUT_BITS=c:\klayout-bits\msvc2017\x64
python setup.py build
```

255
build.bat Normal file
View File

@ -0,0 +1,255 @@
@echo off
setlocal EnableDelayedExpansion
rem ----------------------------------------------------------
rem KLAYOUT build script
rem See build.bat -h for details
rem
rem ----------------------------------------------------------
rem parse command lines
set CONFIG=release
set HAVE_QTBINDINGS=1
set HAVE_QT=1
set HAVE_64BIT_COORD=0
set HAVE_PYTHON=1
set HAVE_RUBY=1
set MAKE_OPT=
set arch=x64
set compiler=msvc2017
set dry_run=0
set option-qmake=qmake
set "option-bits=c:\klayout-bits"
set "option-build=%TEMP%\klayout-build"
set "option-bin=%TEMP%\klayout-bin"
set "option="
for %%a in (%*) do (
if not defined option (
set arg=%%a
if "!arg:~0,1!" equ "-" (
if "!arg!" equ "-h" (
set "option-h=1"
set "option="
) else if "!arg!" equ "--help" (
set "option-h=1"
set "option="
) else if "!arg!" equ "-help" (
set "option-h=1"
set "option="
) else if "!arg!" equ "-bits" (
set "option=!arg!"
) else if "!arg!" equ "-qmake" (
set "option=!arg!"
) else if "!arg!" equ "-build" (
set "option=!arg!"
) else if "!arg!" equ "-bin" (
set "option-bin=%TEMP%\klayout-bin"
set "option=!arg!"
) else if "!arg!" equ "-prefix" (
set "option-bin=%TEMP%\klayout-bin"
set "option=!arg!"
) else if "!arg!" equ "-build" (
set "option=!arg!"
) else if "!arg!" equ "-debug" (
set "CONFIG=debug"
) else if "!arg!" equ "-release" (
set "CONFIG=release"
) else if "!arg!" equ "-with-qtbinding" (
set "HAVE_QTBINDINGS=1"
) else if "!arg!" equ "-without-qtbinding" (
set "HAVE_QTBINDINGS=0"
) else if "!arg!" equ "-without-qt" (
set "HAVE_QT=0"
) else if "!arg!" equ "-with-64bit-coord" (
set "HAVE_64BIT_COORD=1"
) else if "!arg!" equ "-without-64bit-coord" (
set "HAVE_64BIT_COORD=0"
) else if "!arg!" equ "-nopython" (
set "HAVE_PYTHON=0"
) else if "!arg!" equ "-noruby" (
set "HAVE_RUBY=0"
) else if "!arg!" equ "-dry-run" (
set "dry_run=1"
) else if "!arg!" equ "-x64" (
set "arch=x64"
) else if "!arg!" equ "-x86" (
set "arch=x86"
)
) else (
set "MAKE_OPT=!MAKE_OPT! !arg!"
)
) else (
set "option!option!=%%a"
set "option="
)
)
if defined option-h (
echo build.bat - KLayout build script
echo.
echo Mandatory options:
echo -bits [path] Path to the 3rd party binary kit
echo -build [path] Path to the build directory
echo -bin [path] Path to the installation directory
echo -prefix [path] Same as -bin
echo -x86 32 bit build
echo -x64 64 bit build [default]
echo.
echo Other options:
echo -h -help --help Show this help
echo -qmake [path] Path to the qmake binary
echo -debug Perform a debug build
echo -release Perform a release build [the default]
echo -with-qtbinding Enable Qt support for Ruby/Python [the default]
echo -without-qtbinding Disable Qt support for Ruby/Python
echo -without-qt Entirely Qt-free build of a tool subset
echo -with-64bit-coord Enable 64bit coordinate support [experimental]
echo -without-64bit-coord Disable 64bit coordinate support [default]
echo -nopython Dont include Python support
echo -noruby Dont include Ruby support
echo -dry-run Dont actually make
goto :eof
)
echo Analysing installation ...
echo.
rem ----------------------------------------------------------
rem locate MSVC 2017 on the system
set MSVC2017_COMPILER_INST=notfound
rem VS 2017 sets exactly one install as the "main" install, so we may find MSBuild in there.
reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\SxS\VS7" /v 15.0 /reg:32 >nul 2>nul
if NOT ERRORLEVEL 1 (
for /F "tokens=1,2*" %%i in ('reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\SxS\VS7" /v 15.0 /reg:32') DO (
if "%%i"=="15.0" (
if exist "%%k\VC\Auxiliary\Build" (
set "MSVC2017_COMPILER_INST=%%k\VC\Auxiliary\Build"
set "msg=Found MSVC installation at !MSVC2017_COMPILER_INST!"
echo !msg!
)
)
)
)
if "%MSVC2017_COMPILER_INST%" == "notfound" (
echo ERROR: Unable to find MSVC 2017 installation
goto :eof
)
if %arch% equ x64 (
call "%MSVC2017_COMPILER_INST%\vcvars64"
) else (
call "%MSVC2017_COMPILER_INST%\vcvars32"
)
rem ----------------------------------------------------------
rem check the kit
if not exist "%option-bits%"\%compiler%\%arch% (
echo ERROR: no 3rd party binary kit found in %option-bits%\%compiler%\%arch%
goto :eof
)
if not exist "%option-bits%\%compiler%\%arch%\ruby\bin\ruby.exe" (
echo ERROR: %option-bits% not installed properly or
echo path does not point to architecture folder.
echo Use -bits to specfiy the path to the 3rd party binary kit.
goto :eof
)
echo Using bits from %option-bits%\%compiler%\%arch%
rem ----------------------------------------------------------
rem check the qmake binary
"%option-qmake%" -v >nul 2>nul
if ERRORLEVEL 1 (
echo ERROR: Not a valid qmake: %option-qmake%
echo Use -qmake option to specify the path to the qmake binary.
goto :eof
)
echo Using qmake from %option-qmake%
rem ----------------------------------------------------------
rem read klayout Version
for /F "tokens=1" %%i in ('type version.sh') do (
set line=%%i
if "!line:~0,16!" equ "KLAYOUT_VERSION=" (
set "version=!line:~16,100!"
set "KLAYOUT_VERSION=!version:"=!"
)
)
date /t >%TEMP%\klayout-build-tmp.txt
set /P KLAYOUT_VERSION_DATE=<%TEMP%\klayout-build-tmp.txt
del %TEMP%\klayout-build-tmp.txt
rem The short SHA hash of the commit
git rev-parse --short HEAD 2>nul >%TEMP%\klayout-build-tmp.txt
set /P KLAYOUT_VERSION_REV=<%TEMP%\klayout-build-tmp.txt
if ERRORLEVEL 1 (
set "KLAYOUT_VERSION_REV=LatestSourcePackage"
)
del %TEMP%\klayout-build-tmp.txt
rem ----------------------------------------------------------
rem dump settings
echo.
echo Architecture: %arch%
echo Compiler: %compiler%
echo.
echo CONFIG: %CONFIG%
echo KLAYOUT_VERSION: %KLAYOUT_VERSION%
echo KLAYOUT_VERSION_DATE: %KLAYOUT_VERSION_DATE%
echo KLAYOUT_VERSION_REV: %KLAYOUT_VERSION_REV%
echo HAVE_QTBINDINGS: %HAVE_QTBINDINGS%
echo HAVE_QT: %HAVE_QT%
echo HAVE_64BIT_COORD: %HAVE_64BIT_COORD%
echo HAVE_PYTHON: %HAVE_PYTHON%
echo HAVE_RUBY: %HAVE_RUBY%
echo MAKE_OPT: %MAKE_OPT%
echo.
echo qmake binary: %option-qmake%
echo Build directory: %option-build%
echo Installation directory: %option-bin%
if %dry_run% equ 1 (
echo.
echo Dry run ... stopping now.
goto :eof
)
rem ----------------------------------------------------------
rem Run qmake
set "inst_path=%~dp0"
mkdir "%option-build%" 2>nul
cd "%option-build%"
if not exist "%option-build%" (
echo ERROR: build directory does not exists and cannot be created
goto :eof
)
echo on
"%option-qmake%" ^
HAVE_QT5=1 ^
-recursive ^
-spec win32-msvc ^
"CONFIG+=%CONFIG%" ^
"KLAYOUT_VERSION=%KLAYOUT_VERSION%" ^
"KLAYOUT_VERSION_DATE=%KLAYOUT_VERSION_DATE%" ^
"KLAYOUT_VERSION_REV=%KLAYOUT_VERSION_REV%" ^
"HAVE_QTBINDINGS=%HAVE_QTBINDINGS%" ^
"HAVE_QT=%HAVE_QT%" ^
"HAVE_RUBY=%HAVE_RUBY%" ^
"HAVE_PYTHON=%HAVE_PYTHON%" ^
"HAVE_64BIT_COORD=%HAVE_64BIT_COORD%" ^
"PREFIX=%option-bin%" ^
"BITS_PATH=%option-bits%\%compiler%\%arch%" ^
%inst_path%\src\klayout.pro ^
&& nmake %MAKE_OPT% ^
&& nmake install

View File

@ -344,12 +344,11 @@ rdb = Extension(config.root + '.rdb',
# Core setup function
if __name__ == '__main__':
print("Number of cores", N_cores)
setup(name=config.root,
version=config.version(),
description='KLayout standalone Python package',
author='Matthias Koefferlein',
author_email='matthias@klayout.de',
packages=[config.root],
package_dir={config.root: 'src/pymod/distutils_src'},
ext_modules=[_tl, _gsi, _pya, _db, _rdb] + db_plugins + [tl, db, rdb])
setup(name = config.root,
version = config.version(),
description = 'KLayout standalone Python package',
author = 'Matthias Koefferlein',
author_email = 'matthias@klayout.de',
packages = [config.root],
package_dir = {config.root: 'src/pymod/distutils_src'},
ext_modules = [_tl, _gsi, _pya, _db, _rdb] + db_plugins + [tl, db, rdb])

View File

@ -112,7 +112,7 @@ struct cut_polygon_edge
{
typedef typename PointType::coord_type coord_type;
typedef typename db::edge<coord_type> edge_type;
typedef typename db::coord_traits<coord_type>::area_type projection_type;
typedef double projection_type;
cut_polygon_edge ()
: contour (-1), index (0), projected (0), point (), last_point ()
@ -179,7 +179,7 @@ public:
bool operator< (const loose_end_struct<CuttingEdgeType> &other) const
{
if (proj () != other.proj ()) {
if (! db::coord_traits<double>::equal (proj (), other.proj ())) {
return proj () < other.proj ();
} else {
return db::vprod_sign (edge (), other.edge ()) > 0;
@ -196,13 +196,13 @@ static bool _cut_polygon_internal (const PolygonType &input, const Edge &line, C
typedef db::edge<coord_type> edge_type;
typedef cut_polygon_edge<point_type> cut_polygon_edge_type;
typedef cut_polygon_segment<cut_polygon_edge_type> cutting_segment_type;
typedef typename db::coord_traits<coord_type>::area_type projection_type;
bool do_hole_assignment = (input.holes () > 0);
std::vector <PolygonType> hull_polygons;
std::vector <PolygonType> hole_polygons;
std::vector<cutting_segment_type> cutting_segments;
double line_length = line.double_length ();
for (unsigned int nc = 0; nc < input.holes () + 1; ++nc) {
@ -229,7 +229,7 @@ static bool _cut_polygon_internal (const PolygonType &input, const Edge &line, C
int s1 = line.side_of (e.p1 ());
int s2 = line.side_of (e.p2 ());
projection_type p = db::sprod (ip.second - line.p1 (), line.p2 () - line.p1 ());
double p = line_length * double (db::vprod (e.p1 () - line.p1 (), e.d ())) / double (db::vprod (line.d (), e.d ()));
if (s1 < 0 && s2 >= 0) {
// right -> left or on edge

View File

@ -2242,3 +2242,19 @@ TEST(403)
}
}
// issue 166
TEST(404)
{
db::Polygon poly;
std::string s ("(390,0;438,936;176,874;0,832;438,937;541,961;821,102)");
tl::Extractor ex (s.c_str ());
ex.read (poly);
std::vector<db::Polygon> sp;
db::split_polygon (poly, sp);
EXPECT_EQ (sp.size (), size_t (2));
if (sp.size () >= 2) {
EXPECT_EQ (sp[0].to_string (), "(390,0;438,936;390,925;438,937;541,961;821,102)");
EXPECT_EQ (sp[1].to_string (), "(0,832;176,874;390,925)");
}
}

View File

@ -1145,3 +1145,11 @@ TEST(121)
opt.max_vertex_count = 4;
run_test (_this, "t121.oas.gz", "t121_au.gds.gz", true, opt);
}
// Extreme fracturing by max. points
TEST(166)
{
db::GDS2WriterOptions opt;
opt.max_vertex_count = 4;
run_test (_this, "t166.oas.gz", "t166_au.gds.gz", false, opt);
}

View File

@ -70,17 +70,6 @@ DEFImporter::get_orient (bool optional)
}
}
/**
* @brief A structure describing a via
*/
struct ViaDesc
{
ViaDesc () : cell (0) { }
db::Cell *cell;
std::string m1, m2;
};
void
DEFImporter::read_polygon (db::Polygon &poly, double scale)
{
@ -153,7 +142,7 @@ DEFImporter::do_read (db::Layout &layout)
double dbu_mic = 1000.0;
double scale = 1.0 / (dbu_mic * layout.dbu ());
std::map<int, db::Polygon> styles;
std::map<std::string, ViaDesc> via_desc;
std::map<std::string, ViaDesc> via_desc = m_lef_importer.vias ();
std::map<std::string, std::vector<db::Polygon> > regions;
std::list<Group> groups;
std::list<std::pair<std::string, db::CellInstArray> > instances;

View File

@ -533,6 +533,24 @@ private:
const LEFDEFReaderOptions *mp_tech_comp;
};
/**
* @brief A structure describing a via
*/
struct DB_PLUGIN_PUBLIC ViaDesc
{
ViaDesc () : cell (0) { }
/**
* @brief The cell representing the via
*/
db::Cell *cell;
/**
* @brief The names of bottom and top metal respectively
*/
std::string m1, m2;
};
/**
* @brief The LEF importer object
*/

View File

@ -458,6 +458,9 @@ LEFImporter::do_read (db::Layout &layout)
std::string cellname = "VIA_" + n;
db::Cell &cell = layout.cell (layout.add_cell (cellname.c_str ()));
ViaDesc &via_desc = m_vias[n];
via_desc.cell = &cell;
while (test ("DEFAULT") || test ("TOPOFSTACKONLY"))
;
test (";");
@ -543,9 +546,9 @@ LEFImporter::do_read (db::Layout &layout)
} else if (test ("LAYERS")) {
geometry[0].first = get ();
via_desc.m1 = geometry[0].first = get ();
geometry[1].first = get ();
geometry[2].first = get ();
via_desc.m2 = geometry[2].first = get ();
test (";");

View File

@ -86,6 +86,16 @@ public:
*/
double layer_ext (const std::string &layer, double def_ext = 0.0) const;
/**
* @brief Gets a map of the vias defined in this LEF file
*
* The map maps the via name to the via description.
*/
const std::map<std::string, ViaDesc> &vias () const
{
return m_vias;
}
protected:
void do_read (db::Layout &layout);
@ -95,6 +105,7 @@ private:
std::map<std::string, double> m_default_ext;
std::map<std::string, db::Cell *> m_macros_by_name;
std::map<std::string, db::Box> m_macro_bboxes_by_name;
std::map<std::string, ViaDesc> m_vias;
std::vector <db::Trans> get_iteration (db::Layout &layout);
void read_geometries (db::Layout &layout, db::Cell &cell, LayerPurpose purpose, std::map<std::string, db::Box> *collect_bboxes = 0);

View File

@ -30,7 +30,7 @@
#include <cstdlib>
static void run_test (tl::TestBase *_this, const char *lef_dir, const char *filename, const char *au)
static void run_test (tl::TestBase *_this, const char *lef_dir, const char *filename, const char *au, bool priv = true)
{
db::LEFDEFReaderOptions tc;
tc.set_via_geometry_datatype (0);
@ -60,7 +60,7 @@ static void run_test (tl::TestBase *_this, const char *lef_dir, const char *file
if (ex.test ("def:")) {
std::string fn (tl::testsrc_private ());
std::string fn (priv ? tl::testsrc_private () : tl::testsrc ());
fn += "/testdata/lefdef/";
fn += lef_dir;
fn += "/";
@ -73,7 +73,7 @@ static void run_test (tl::TestBase *_this, const char *lef_dir, const char *file
} else if (ex.test ("lef:")) {
std::string fn (tl::testsrc_private ());
std::string fn (priv ? tl::testsrc_private () : tl::testsrc ());
fn += "/testdata/lefdef/";
fn += lef_dir;
fn += "/";
@ -118,7 +118,7 @@ static void run_test (tl::TestBase *_this, const char *lef_dir, const char *file
if (au) {
std::string fn (tl::testsrc_private ());
std::string fn (priv ? tl::testsrc_private () : tl::testsrc ());
fn += "/testdata/lefdef/";
fn += lef_dir;
fn += "/";
@ -233,3 +233,8 @@ TEST(19)
run_test (_this, "def10", "def:in.def", "au.oas.gz");
}
TEST(20)
{
run_test (_this, "issue-172", "lef:in.lef+def:in.def", "au.oas.gz", false);
}

View File

@ -42,6 +42,9 @@ lib_target.path = $$PREFIX/pymod/klayout
# This would be nice:
# lib_target.files += $$DESTDIR_PYMOD/$${TARGET}$${PYTHONEXTSUFFIX}
# but some Qt versions need this explicitly:
lib_target.extra = $(INSTALL_PROGRAM) $$DESTDIR_PYMOD/$${TARGET}$${PYTHONEXTSUFFIX} $(INSTALLROOT)$$PREFIX/pymod/klayout
msvc {
lib_target.extra = $(INSTALL_PROGRAM) $$shell_path($$DESTDIR_PYMOD/$${TARGET}$${PYTHONEXTSUFFIX}) $$shell_path($(INSTALLROOT)$$PREFIX/pymod/klayout)
} else {
lib_target.extra = $(INSTALL_PROGRAM) $$DESTDIR_PYMOD/$${TARGET}$${PYTHONEXTSUFFIX} $(INSTALLROOT)$$PREFIX/pymod/klayout
}
INSTALLS = lib_target

View File

@ -35,5 +35,9 @@ init_target.path = $$PREFIX/pymod/klayout
# This would be nice:
# init_target.files += $$DESTDIR_PYMOD/__init__.py
# but some Qt versions need this explicitly:
init_target.extra = $(INSTALL_PROGRAM) $$DESTDIR_PYMOD/__init__.py $(INSTALLROOT)$$PREFIX/pymod/klayout
msvc {
init_target.extra = $(INSTALL_PROGRAM) $$shell_path($$DESTDIR_PYMOD/__init__.py) $$shell_path($(INSTALLROOT)$$PREFIX/pymod/klayout)
} else {
init_target.extra = $(INSTALL_PROGRAM) $$DESTDIR_PYMOD/__init__.py $(INSTALLROOT)$$PREFIX/pymod/klayout
}
INSTALLS += init_target

BIN
testdata/gds/t166.oas.gz vendored Normal file

Binary file not shown.

BIN
testdata/gds/t166_au.gds.gz vendored Normal file

Binary file not shown.

BIN
testdata/lefdef/issue-172/au.oas.gz vendored Normal file

Binary file not shown.

16
testdata/lefdef/issue-172/in.def vendored Normal file
View File

@ -0,0 +1,16 @@
VERSION 5.6 ;
NAMESCASESENSITIVE ON ;
DIVIDERCHAR "/" ;
BUSBITCHARS "<>" ;
DESIGN SMALL ;
UNITS DISTANCE MICRONS 100 ;
DIEAREA ( -30 -30 ) ( 1030 1030 ) ;
NETS 1 ;
- TOP
+ ROUTED M1 ( 0 0 ) ( 1000 * ) M2_M1
NEW M2 ( 1000 0 ) ( 1000 1000 ) ;
END NETS
END DESIGN

40
testdata/lefdef/issue-172/in.lef vendored Normal file
View File

@ -0,0 +1,40 @@
VERSION 5.7 ;
NAMESCASESENSITIVE ON ;
BUSBITCHARS "[]" ;
DIVIDERCHAR "/" ;
UNITS
DATABASE MICRONS 1000 ;
END UNITS
USEMINSPACING OBS ON ;
USEMINSPACING PIN OFF ;
CLEARANCEMEASURE EUCLIDEAN ;
MANUFACTURINGGRID 0.05 ;
LAYER M1
TYPE ROUTING ;
DIRECTION HORIZONTAL ;
WIDTH 0.2 ;
END M1
LAYER V2
TYPE CUT ;
END V2
LAYER M2
TYPE ROUTING ;
DIRECTION VERTICAL ;
WIDTH 0.2 ;
END M2
VIA M2_M1 DEFAULT
LAYER M1 ;
RECT -0.300 -0.300 0.300 0.300 ;
LAYER V2 ;
RECT -0.200 -0.200 0.200 0.200 ;
LAYER M2 ;
RECT -0.300 -0.300 0.300 0.300 ;
END M2_M1
END LIBRARY

View File

@ -150,7 +150,7 @@ class DBTransTests(unittest.TestCase):
self.assertEqual( c.is_mirror(), True )
self.assertEqual( c.rot(), pya.DCplxTrans.M135.rot() )
self.assertEqual( str(c.s_trans()), "m135 0,0" )
self.assertEqual( c.angle, 270 )
self.assertAlmostEqual( c.angle, 270 )
self.assertEqual( str(c.trans( pya.Edge(0, 1, 2, 3) )), "(-1,0;-3,-2)" )
self.assertEqual( str(( c * pya.Edge(0, 1, 2, 3) )), "(-1,0;-3,-2)" )
@ -174,7 +174,7 @@ class DBTransTests(unittest.TestCase):
self.assertEqual( c.is_mirror(), False )
self.assertEqual( c.rot(), pya.DCplxTrans.R0.rot() )
self.assertEqual( str(c.s_trans()), "r0 0,0" )
self.assertEqual( c.angle, 0 )
self.assertAlmostEqual( c.angle, 0 )
c = pya.DCplxTrans( 0.75, 45, True, 2.5, -12.5 )
self.assertEqual( str(c), "m22.5 *0.75 2.5,-12.5" )
@ -185,7 +185,7 @@ class DBTransTests(unittest.TestCase):
self.assertEqual( c.is_mag(), True )
self.assertEqual( c.rot(), pya.DCplxTrans.M0.rot() )
self.assertEqual( str(c.s_trans()), "m0 2.5,-12.5" )
self.assertEqual( c.angle, 45 )
self.assertAlmostEqual( c.angle, 45 )
self.assertEqual( str(c.ctrans( 5 )), "3.75" )
self.assertEqual( str(c.trans( pya.DPoint( 12, 16 ) )), "17.3492424049,-14.6213203436" )
@ -335,7 +335,7 @@ class DBTransTests(unittest.TestCase):
self.assertEqual( c.is_mirror(), True )
self.assertEqual( c.rot(), pya.CplxTrans.M135.rot() )
self.assertEqual( str(c.s_trans()), "m135 0,0" )
self.assertEqual( c.angle, 270 )
self.assertAlmostEqual( c.angle, 270 )
c = pya.CplxTrans.from_dtrans( pya.DCplxTrans.M135 )
self.assertEqual( str(c), "m135 *1 0,0" )
@ -348,7 +348,7 @@ class DBTransTests(unittest.TestCase):
self.assertEqual( c.is_mirror(), False )
self.assertEqual( c.rot(), pya.CplxTrans.R0.rot() )
self.assertEqual( str(c.s_trans()), "r0 0,0" )
self.assertEqual( c.angle, 0 )
self.assertAlmostEqual( c.angle, 0 )
c = pya.CplxTrans( 0.75, 45, True, 2.5, -12.5 )
self.assertEqual( str(c), "m22.5 *0.75 2.5,-12.5" )
@ -360,7 +360,7 @@ class DBTransTests(unittest.TestCase):
self.assertEqual( c.is_mag(), True )
self.assertEqual( c.rot(), pya.CplxTrans.M0.rot() )
self.assertEqual( str(c.s_trans()), "m0 3,-13" )
self.assertEqual( c.angle, 45 )
self.assertAlmostEqual( c.angle, 45 )
self.assertEqual( str(c.ctrans( 5 )), "3.75" )
self.assertEqual( str(c.trans( pya.Point( 12, 16 ) )), "17.3492424049,-14.6213203436" )
@ -517,7 +517,7 @@ class DBTransTests(unittest.TestCase):
self.assertEqual(t1 < t4, True)
self.assertEqual(t4 < t1, False)
# Hash values
# Hash values
def test_5_Trans_Hash(self):
t1 = pya.DTrans( pya.DTrans.M135, pya.DPoint( 17, 5 ))

View File

@ -471,9 +471,11 @@ class QtBindingTest(unittest.TestCase):
pya.QApplication.processEvents()
s1 = "QKeyEvent: ShortcutOverride (51)\nQKeyEvent: KeyPress (6)\nQKeyEvent: ShortcutOverride (51)\nQKeyEvent: KeyPress (6)\nQKeyEvent: ShortcutOverride (51)\nQKeyEvent: KeyPress (6)"
s2 = "QKeyEvent: KeyPress (6)\nQKeyEvent: KeyPress (6)\nQKeyEvent: KeyPress (6)"
self.assertEqual("\n".join(ef.log()) == s1 or "\n".join(ef.log()) == s2, True)
s1 = "QKeyEvent: ShortcutOverride (51)\nQKeyEvent: KeyPress (6)\nQKeyEvent: ShortcutOverride (51)\nQKeyEvent: KeyPress (6)\nQKeyEvent: ShortcutOverride (51)\nQKeyEvent: KeyPress (6)"
s2 = "QKeyEvent: KeyPress (6)\nQKeyEvent: KeyPress (6)\nQKeyEvent: KeyPress (6)"
s3 = "QKeyEvent_Native: ShortcutOverride (51)\nQKeyEvent: KeyPress (6)\nQKeyEvent_Native: ShortcutOverride (51)\nQKeyEvent: KeyPress (6)\nQKeyEvent_Native: ShortcutOverride (51)\nQKeyEvent: KeyPress (6)"
self.assertIn("\n".join(ef.log()), (s1, s2, s3))
ef = None
self.assertEqual(widget.text, "ABCpO")

View File

@ -534,7 +534,10 @@ class QtBinding_TestClass < TestBase
GC.start
assert_equal(ef.log.select { |s| s !~ /RBA::QKeyEvent: ShortcutOverride/ }.join("\n"), "RBA::QKeyEvent: KeyPress (6)\nRBA::QKeyEvent: KeyPress (6)\nRBA::QKeyEvent: KeyPress (6)")
assert_equal(ef.log.select { |s| s !~ /RBA::QKeyEvent: ShortcutOverride/ }.join("\n"), "RBA::QKeyEvent: KeyPress (6)\nRBA::QKeyEvent: KeyPress (6)\nRBA::QKeyEvent: KeyPress (6)")
# TODO: on macOS 10.13, ef.log yields "RBA::QKeyEvent_Native: ShortcutOverride (51)\nRBA::QKeyEvent: KeyPress (6)\nRBA::QKeyEvent_Native: ShortcutOverride (51)\nRBA::QKeyEvent: KeyPress (6)\nRBA::QKeyEvent_Native: ShortcutOverride (51)\nRBA::QKeyEvent: KeyPress (6)", causing this test to fail.
ef = nil
ef = EventFilter::new
GC.start