kicad-developers team mailing list archive
-
kicad-developers team
-
Mailing list archive
-
Message #19816
Re: [PATCH] Fix handle ZoneConnection enum in python scripting agains BZR6098
In response to a message written on 18.08.2015, 16:23, from jp charras:
Le 18/08/2015 08:38, LordBlick a écrit :
Attached, tested(on PLD Linux) patch implements the following changes:
- not finished python scripting issue - brings pad.GetZoneConnection()
and in
example pad.SetZoneConnection(pcbnew.PAD_ZONE_CONN_FULL) to full workable.
- cleanup namespace pretty artistic disorder in enum ZoneConnection in
pcbnew/zones.h to self-explained names unification:
PAD_ZONE_CONN_INHERITED = -1
PAD_ZONE_CONN_NONE
PAD_ZONE_CONN_THERMAL
PAD_ZONE_CONN_FULL
PAD_ZONE_CONN_THT_THERMAL
There is no influence for instability after applying.
Committed. Thanks.
Be careful with this kind of changes: it can break existing Python
scripts like wizards.
I understand it. Eventually it might be changed after next stable release, where
all stable users can use old namespace, then on production namespace can be cleaned.
All scripts included in repository of course will be updated, because changes
are generated by search & replace script, not manually. Example diff generator
in attachment
(This is not the case for this change)
Of course not, because that functionality there was not working in Python before… ;)
Thanks for commit.
--
Best Regards,
LordBlick
#!/usr/bin/env python2
# -*- encoding: utf-8 -*-
# -*- coding: utf-8 -*-
debug_level = 1
dbg_files = 'zones.h', 'class_zone.cpp'
import re
from os import path as ph, readlink as rlnk, rename as mv, makedirs
from shutil import copy2 as cp
'''
rename_rex_list = (
(r'\b(PAD_)((CIRCLE)|(OVAL)|(TRAPEZOID)|(RECT))\b', '\\g<1>SHAPE_\\g<2>'),
(r'\b(PAD_)((STANDARD)|(SMD)|(CONN))\b', '\\g<1>TYPE_\\g<2>'),
(r'\b(PAD_)HOLE_NOT_PLATED\b', '\\g<1>TYPE_NPTH'),
)
'''
rename_rex_list = (
(r'\bUNDEFINED_CONNECTION\b', 'PAD_ZONE_CONN_INHERITED'),
(r'\bPAD_NOT_IN_ZONE\b', 'PAD_ZONE_CONN_NONE'),
(r'\bTHERMAL_PAD\b', 'PAD_ZONE_CONN_THERMAL'),
(r'\bPAD_IN_ZONE\b', 'PAD_ZONE_CONN_FULL'),
(r'\bTHT_THERMAL\b', 'PAD_ZONE_CONN_THT_THERMAL'),
)
'\b(UNDEFINED_CONNECTION)|(PAD_NOT_IN_ZONE)|(THERMAL_PAD)|(PAD_IN_ZONE)|(THT_THERMAL)\b'
strict_rex_list = (
('pcbnew.i', '^(.*include\s*\<)(class_zone\.h)(\>.*)$', '\\g<1>\\g<2>\\g<3>\n\\g<1>zones.h\\g<3>'),
)
H = ph.expanduser('~') # Home dir
hh = lambda s: s.replace(H, '~')
from sys import stdout as sto
_p = lambda _str: sto.write(hh(str(_str)))
_err = lambda _str: sto.write(_str)
def _dbg(s, level=1):
if debug_level>=level:
_p(s)
unp_dir = "%s/rpm/BUILD/" % H
diff_root_dn = ''
output_fn = unp_dir+'pyZoneConnection'
#ls_fn = []
class Patcher:
def __init__(it):
it.search_and_prepare()
#it.diff()
def search_and_prepare(it):
#Search for newest build tree
from glob import glob as ls
bld = ('main', 'stable')[0]
rexBldDirBzrRev = re.compile("kicad-sources-BZR\.(?P<BzrRev>\d+)-"+bld, re.U)
lsBldDirs = []
for dirName in ls(unp_dir+'*'):#+'kicad-sources-BZR.*-'+bld
mBldDirBzrRev = rexBldDirBzrRev.search(dirName)
if not(mBldDirBzrRev) or(not(ph.isdir(dirName))):
continue
bzrRev = int(mBldDirBzrRev.group('BzrRev'))
lsBldDirs.append( (bzrRev, dirName) )
if not(lsBldDirs):
_p("No usable build tree in %sr…\n" % hh(unp_dir))
return
global diff_root_dn, output_fn #, ls_fn
revno, diff_root_dn = tuple(reversed(sorted(lsBldDirs)))[0]
output_fn += "-BZR%d.path" % revno
diff_tree = diff_root_dn+'/'
_p("Freshest usable build tree: '%s'\n" % hh(diff_root_dn))
#Search for files to patch
def S_R(data, search, replace):
if not search:
_err("There is no find expresion...\n")
return None
if not replace:
_err("There is no replace expresion...\n")
return None
try:
rexFindIt = re.compile(search, re.U|re.M)
except:
_err("This is not regular expresion:'%s'\n" % search)
return None
matchIt = rexFindIt.search(data)
if not(matchIt):
_dbg("This file:'%s' does not contain expresion: %s\n" % (
fn.replace(diff_tree, ''), repr(search)), dbg_lvl)
return None
return re.sub(rexFindIt, replace, data)
strict_fns = map(lambda n: n[0], strict_rex_list)
match_fn = re.compile(
'''^(
(.+\.(((c|h)((p{2})|(x{2}))?)|(i)|(py)))
|(.*cmake.*)
)$''', re.I|re.X|re.U)
from os import walk
from difflib import unified_diff as udiff
from time import ctime, localtime, strftime
ud_data = ''
if debug_level: ls_all_fn = []
for findRoot, fDir, findFiles in walk(diff_root_dn):
if not findFiles:
continue
for base_fn in findFiles:
fn = '/'.join((findRoot, base_fn))
if debug_level: ls_all_fn.append(fn)
if not(match_fn.match(base_fn)):
continue
while ph.islink(fn):
link_target = ph.realpath(ph.expanduser(rlnk(fn)))
fn = link_target
if not(ph.isfile(fn)):
_err("This file does not exist:'%s'\n" % fn)
return
diffNew, diffOld = fn, fn+'.old'
diffOldInTree, diffNewInTree = diffOld.replace(diff_tree, ''), diffNew.replace(diff_tree, '')
if ph.isfile(diffOld):
_err("Seems to diff generation already was performed…\nOld file found:'%s'\n" % diffOld)
#ls_fn = None
return
dbg_lvl = (2, 1)[base_fn in dbg_files]
hFile = open(fn, 'r')
if not(hFile):
_p("Can not open this file:'%s'\n" % fn)
return
data = dataCp = hFile.read()
hFile.close()
_dbg("Readed file:'%s'\n" % fn, dbg_lvl)
if base_fn in strict_fns:
idx = strict_fns.index(base_fn)
search, replace = strict_rex_list[idx][1:]
new_data = S_R(data, search, replace)
if new_data:
data = new_data
_dbg("Strict file:'%s'\n" % fn, 1)
for search, replace in rename_rex_list:
new_data = S_R(data, search, replace)
if not(new_data):
continue
data = new_data
if data != dataCp:
ud_data += '\n'.join(udiff(dataCp.splitlines(), data.splitlines(),
fromfile=diffOldInTree, tofile=diffNewInTree,
fromfiledate=strftime("%Y-%m-%d %H:%M:%S.%s", localtime(ph.getmtime(fn))),
tofiledate=strftime("%Y-%m-%d %H:%M:%S.%s"), n=3, lineterm=''))+'\n'
'''
cp(diffNew, diffOld)
ls_fn.append((diffOldInTree, diffNewInTree))
hFile = open(fn, 'w')
if not(hFile):
_err("Can't write to file:'%s'\n" % fn)
return
hFile.write(data)
hFile.close()
'''
_p("Modified file:'%s'\n" % fn)
else:
_dbg("File not touched:'%s'\n" % fn, dbg_lvl)
if ud_data:
to_fn =
hFile = open(output_fn, 'w')
#hFile = open(unp_dir+'alternative.patch', 'w')
hFile.write(ud_data)
hFile.close()
if debug_level:
hFile = open(unp_dir+'diff_search_test.txt', 'w')
hFile.write(("Found %d files:\n" % len(ls_all_fn))+'\n'.join(ls_all_fn)+'\n')
hFile.close()
'''
def call(it, cmd, echo=True):
from subprocess import Popen, PIPE, STDOUT
from shlex import split as shs
if echo:
print("> %s" % cmd)
proc = Popen(
shs(cmd),
stdout=PIPE,
stderr=PIPE)
result, stderr = proc.communicate()
return proc.returncode, result, stderr
def diff(it):
from os import getcwd as pwd, chdir as cd
if not(diff_root_dn):
_err("Empty diff_root_dn…\n")
return
if not(output_fn):
_err("Empty output_fn…\n")
return
if not(ls_fn):
_err("Empty ls_fn…\n")
return
diff_NoDiff = 0
diff_Found = 1
diff_Error = 2
diff_data_out = ''
_pwd = pwd()
cd(diff_root_dn)
for diffOld, diffNew in ls_fn:
retcode, diffData, err = it.call("diff -u %s %s" % (diffOld, diffNew))
_dbg("retCode: %i" % retcode, 1)
_dbg(", diff data:\n%s" % diffData, 2)
_dbg("\n", 1)
if retcode==diff_Found:
diff_data_out += diffData
cd(_pwd)
if diff_data_out:
output_dn = ph.dirname(output_fn)
if not(ph.isdir(output_dn)):
makedirs(output_dn)
hFile = open(output_fn, 'w')
if not(hFile):
_err("Can't write to File:'%s'\n" % output_fn)
return
hFile.write(diff_data_out)
hFile.close()
_p("Writen File:'%s'\n" % output_fn)
'''
if __name__=='__main__':
x = Patcher()
References