mirror of https://github.com/KLayout/klayout.git
Fixed #75 (Python PCell issue when parameters are called 'layer')
This commit - Ignores exceptions when checking for PCells that accept shapes. Hence a single rogue one does not break the feature. - Prevents errors when parameters named "layer" are present by making the implementation safe against this case. - In addition, guiding shape parameters of type "Path", "Box" etc. (i.e. integer types) are supported too although they are not recommended for portability.
This commit is contained in:
parent
6a762db29b
commit
6d0fe85425
|
|
@ -226,16 +226,27 @@ class _PCellDeclarationHelperLayerDescriptor(object):
|
|||
class _PCellDeclarationHelperParameterDescriptor(object):
|
||||
"""
|
||||
A descriptor object which translates the PCell parameters into class attributes
|
||||
|
||||
In some cases (i.e. can_convert_from_shape), these placeholders are not
|
||||
connected to real parameters (obj._param_values is None). In this case,
|
||||
the descriptor acts as a value holder (self.value)
|
||||
"""
|
||||
|
||||
def __init__(self, param_index):
|
||||
self.param_index = param_index
|
||||
self.value = None
|
||||
|
||||
def __get__(self, obj, type = None):
|
||||
return obj._param_values[self.param_index]
|
||||
if obj._param_values:
|
||||
return obj._param_values[self.param_index]
|
||||
else:
|
||||
return self.value
|
||||
|
||||
def __set__(self, obj, value):
|
||||
obj._param_values[self.param_index] = value
|
||||
if obj._param_values:
|
||||
obj._param_values[self.param_index] = value
|
||||
else:
|
||||
self.value = value
|
||||
|
||||
class _PCellDeclarationHelper(pya.PCellDeclaration):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -186,15 +186,28 @@ PCellVariant::update (ImportLayerMapping *layer_mapping)
|
|||
|
||||
shapes (layout ()->guiding_shape_layer ()).insert (db::BoxWithProperties(db::Box (m_parameters[i].to_user<db::DBox> () * (1.0 / layout ()->dbu ())), layout ()->properties_repository ().properties_id (props)));
|
||||
|
||||
} else if (m_parameters[i].is_user<db::Box> ()) {
|
||||
|
||||
shapes (layout ()->guiding_shape_layer ()).insert (db::BoxWithProperties(m_parameters[i].to_user<db::Box> (), layout ()->properties_repository ().properties_id (props)));
|
||||
|
||||
} else if (m_parameters[i].is_user<db::DEdge> ()) {
|
||||
|
||||
shapes (layout ()->guiding_shape_layer ()).insert (db::EdgeWithProperties(db::Edge (m_parameters[i].to_user<db::DEdge> () * (1.0 / layout ()->dbu ())), layout ()->properties_repository ().properties_id (props)));
|
||||
|
||||
} else if (m_parameters[i].is_user<db::Edge> ()) {
|
||||
|
||||
shapes (layout ()->guiding_shape_layer ()).insert (db::EdgeWithProperties(m_parameters[i].to_user<db::Edge> (), layout ()->properties_repository ().properties_id (props)));
|
||||
|
||||
} else if (m_parameters[i].is_user<db::DPoint> ()) {
|
||||
|
||||
db::DPoint p = m_parameters[i].to_user<db::DPoint> ();
|
||||
shapes (layout ()->guiding_shape_layer ()).insert (db::BoxWithProperties(db::Box (db::DBox (p, p) * (1.0 / layout ()->dbu ())), layout ()->properties_repository ().properties_id (props)));
|
||||
|
||||
} else if (m_parameters[i].is_user<db::Point> ()) {
|
||||
|
||||
db::Point p = m_parameters[i].to_user<db::Point> ();
|
||||
shapes (layout ()->guiding_shape_layer ()).insert (db::BoxWithProperties(db::Box (p, p), layout ()->properties_repository ().properties_id (props)));
|
||||
|
||||
} else if (m_parameters[i].is_user<db::DPolygon> ()) {
|
||||
|
||||
db::complex_trans<db::DCoord, db::Coord> dbu_trans (1.0 / layout ()->dbu ());
|
||||
|
|
@ -202,11 +215,21 @@ PCellVariant::update (ImportLayerMapping *layer_mapping)
|
|||
// Hint: we don't compress the polygon since we don't want to loose information
|
||||
shapes (layout ()->guiding_shape_layer ()).insert (db::PolygonWithProperties(poly, layout ()->properties_repository ().properties_id (props)));
|
||||
|
||||
} else if (m_parameters[i].is_user<db::Polygon> ()) {
|
||||
|
||||
db::Polygon poly = m_parameters[i].to_user<db::Polygon> ();
|
||||
// Hint: we don't compress the polygon since we don't want to loose information
|
||||
shapes (layout ()->guiding_shape_layer ()).insert (db::PolygonWithProperties(poly, layout ()->properties_repository ().properties_id (props)));
|
||||
|
||||
} else if (m_parameters[i].is_user<db::DPath> ()) {
|
||||
|
||||
db::complex_trans<db::DCoord, db::Coord> dbu_trans (1.0 / layout ()->dbu ());
|
||||
shapes (layout ()->guiding_shape_layer ()).insert (db::PathWithProperties(dbu_trans * m_parameters[i].to_user<db::DPath> (), layout ()->properties_repository ().properties_id (props)));
|
||||
|
||||
} else if (m_parameters[i].is_user<db::Path> ()) {
|
||||
|
||||
shapes (layout ()->guiding_shape_layer ()).insert (db::PathWithProperties(m_parameters[i].to_user<db::Path> (), layout ()->properties_repository ().properties_id (props)));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1084,23 +1084,29 @@ MainService::cm_convert_to_pcell ()
|
|||
db::Library *lib = db::LibraryManager::instance ().lib (l->second);
|
||||
for (db::Layout::pcell_iterator pc = lib->layout ().begin_pcells (); pc != lib->layout ().end_pcells (); ++pc) {
|
||||
|
||||
const db::PCellDeclaration *pc_decl = lib->layout ().pcell_declaration (pc->second);
|
||||
size_t n = 1000; // 1000 tries max.
|
||||
for (std::vector<edt::Service *>::const_iterator es = edt_services.begin (); n > 0 && pc_decl && es != edt_services.end (); ++es) {
|
||||
for (edt::Service::obj_iterator s = (*es)->selection ().begin (); n > 0 && pc_decl && s != (*es)->selection ().end (); ++s) {
|
||||
const lay::CellView &cv = view ()->cellview (s->cv_index ());
|
||||
if (pc_decl->can_create_from_shape (cv->layout (), s->shape (), s->layer ())) {
|
||||
--n;
|
||||
} else {
|
||||
pc_decl = 0; // stop
|
||||
try {
|
||||
|
||||
const db::PCellDeclaration *pc_decl = lib->layout ().pcell_declaration (pc->second);
|
||||
size_t n = 1000; // 1000 tries max.
|
||||
for (std::vector<edt::Service *>::const_iterator es = edt_services.begin (); n > 0 && pc_decl && es != edt_services.end (); ++es) {
|
||||
for (edt::Service::obj_iterator s = (*es)->selection ().begin (); n > 0 && pc_decl && s != (*es)->selection ().end (); ++s) {
|
||||
const lay::CellView &cv = view ()->cellview (s->cv_index ());
|
||||
if (pc_decl->can_create_from_shape (cv->layout (), s->shape (), s->layer ())) {
|
||||
--n;
|
||||
} else {
|
||||
pc_decl = 0; // stop
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We have positive hit
|
||||
if (pc_decl) {
|
||||
pcells.push_back (std::make_pair (lib, pc->second));
|
||||
items.push_back (tl::to_qstring (lib->get_name () + "." + pc_decl->name ()));
|
||||
// We have positive hit
|
||||
if (pc_decl) {
|
||||
pcells.push_back (std::make_pair (lib, pc->second));
|
||||
items.push_back (tl::to_qstring (lib->get_name () + "." + pc_decl->name ()));
|
||||
}
|
||||
|
||||
} catch (...) {
|
||||
// ignore errors in can_create_from_shape
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue