Repository: python-babel/babel (python)

Issue:
Using __file__ in a PyInstaller environment is not possible
Babel is not working in my projects which are processed with PyInstaller.
The reason for this: the direct access to "`__file__`".

Pull request:
Introduce PyInstaller support. Fixes #500
Using a new module pi_support.py seems necessary, because there is no
possibility to use core.py or util.py.
These files are used inside setup.py at a time pytz is not yet installed.
This is a follow up to #504

Patch:
diff --git a/babel/core.py b/babel/core.py
index 5140f49..df03b24 100644
--- a/babel/core.py
+++ b/babel/core.py
@@ -68,7 +68,7 @@ def get_global(key):
     """
     global _global_data
     if _global_data is None:
-        dirname = os.path.join(os.path.dirname(__file__))
+        dirname = localedata.get_base_dir()
         filename = os.path.join(dirname, 'global.dat')
         if not os.path.isfile(filename):
             _raise_no_data_error()
diff --git a/babel/localedata.py b/babel/localedata.py
index 9e272a2..4658221 100644
--- a/babel/localedata.py
+++ b/babel/localedata.py
@@ -16,13 +16,23 @@ import os
 import threading
 from collections import MutableMapping
 from itertools import chain
+import sys
 
 from babel._compat import pickle
 
 
+def get_base_dir():
+    if getattr(sys, 'frozen', False):
+        # we are running in a |PyInstaller| bundle
+        basedir = sys._MEIPASS
+    else:
+        # we are running in a normal Python environment
+        basedir = os.path.dirname(__file__)
+    return basedir
+
 _cache = {}
 _cache_lock = threading.RLock()
-_dirname = os.path.join(os.path.dirname(__file__), 'locale-data')
+_dirname = os.path.join(get_base_dir(), 'locale-data')
 
 
 def normalize_locale(name):


Test patch:
diff --git a/tests/test_localedata.py b/tests/test_localedata.py
index 6a41ac2..62ad93c 100644
--- a/tests/test_localedata.py
+++ b/tests/test_localedata.py
@@ -14,6 +14,7 @@
 import unittest
 import random
 from operator import methodcaller
+import sys
 
 from babel import localedata
 
@@ -94,3 +95,14 @@ def test_mixedcased_locale():
         locale_id = ''.join([
             methodcaller(random.choice(['lower', 'upper']))(c) for c in l])
         assert localedata.exists(locale_id)
+
+
+def test_pi_support_frozen(monkeypatch):
+    monkeypatch.setattr(sys, '_MEIPASS', 'testdir', raising=False)
+    monkeypatch.setattr(sys, 'frozen', True, raising=False)
+    assert localedata.get_base_dir() == 'testdir'
+
+
+def test_pi_support_not_frozen():
+    assert not getattr(sys, 'frozen', False)
+    assert localedata.get_base_dir().endswith('babel')