realthunder / fcad_pcb

FreeCAD scripts for PCB CAD/CAM
MIT License
130 stars 24 forks source link

UnicodeDecodeError on Windows #75

Open aa956 opened 2 months ago

aa956 commented 2 months ago

Opening any PCB containing non-ASCII characters on Windows results in:

>>> from fcad_pcb import kicad
>>> pcb = kicad.KicadFcad('C:/Users/username/projects/pcb/pcb1.kicad_pcb')
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "C:\Users\username\AppData\Roaming\FreeCAD\Macro\fcad_pcb\kicad.py", line 606, in __init__
    self.pcb = KicadPCB.load(self.filename, self.quote_no_parse)
  File "C:\Users\username\AppData\Roaming\FreeCAD\Macro\fcad_pcb\kicad_parser\kicad_pcb.py", line 93, in load
    return KicadPCB(parseSexp(f.read(), quote_no_parse))
  File "C:\Users\username\AppData\Local\Programs\FreeCAD 0.21\bin\lib\encodings\cp1257.py", line 23, in decode
    return codecs.charmap_decode(input,self.errors,decoding_table)[0]
UnicodeDecodeError: 'charmap' codec can't decode byte 0x9c in position 289: character maps to <undefined>
>>> 

Also had a similar problem when kicad_common.json contained working_dir with non-ASCII characters.

Had to make 2 changes to fix. Probably a good idea to review all of the open() calls?

One change in kicad_parser/kicad_pcb.py

diff --git a/kicad_pcb.py b/kicad_pcb.py
index 35f0eb1..fc6880e 100644
--- a/kicad_pcb.py
+++ b/kicad_pcb.py
@@ -89,6 +89,6 @@ class KicadPCB(SexpParser):

     @staticmethod
     def load(filename, quote_no_parse=None):
-        with open(filename,'r') as f:
+        with open(filename,'r', encoding='utf-8') as f:
             return KicadPCB(parseSexp(f.read(), quote_no_parse))

Another in kicad.py

diff --git a/kicad.py b/kicad.py
index 70af34b..8eab7c1 100644
--- a/kicad.py
+++ b/kicad.py
@@ -480,7 +480,7 @@ def getKicadPath(env=''):
                     logger.warning('cannot find kicad_common')
                     return None
             logger.info("Found kicad_common at {}".format(kicad_common))
-    with open(kicad_common,'r') as f:
+    with open(kicad_common,'r',encoding='utf-8') as f:
         content = f.read()
     match = re.search(r'^\s*"*KISYS3DMOD"*\s*[:=]\s*([^\r\n]+)',content,re.MULTILINE)
     if not match:
diff --git a/kicad_parser b/kicad_parser
--- a/kicad_parser
+++ b/kicad_parser
@@ -1 +1 @@
-Subproject commit 75528791a994ad1ba60e5d927b4b9b5587949a83
+Subproject commit 75528791a994ad1ba60e5d927b4b9b5587949a83-dirty

Actually I'm not sure why the Windows system encoding is used at all, FreeCAD python console shows utf-8 is default?

>>> import sys; print(sys.getdefaultencoding())
utf-8
>>> 
aa956 commented 1 month ago

Setting environment variable PYTHONUTF8=1 does not work with FreeCAD.

According to this: https://forum.freecad.org/viewtopic.php?p=451120#p451120

Found working fix that does not require patching fcad_pcb and kicad_parser.

Before importing fcad_pcb:

import _locale
_locale._getdefaultlocale = (lambda *args: ['en_US', 'utf8'])