Skip to content

Commit ef9870d

Browse files
authored
Merge pull request #32 from ishiland/windows_bugfix
explicitly define path to the nycgeo dll and fix unit tests
2 parents 750e3be + e8f02d0 commit ef9870d

4 files changed

Lines changed: 70 additions & 10 deletions

File tree

geosupport/geosupport.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from .error import GeosupportError
1212
from .function_info import FUNCTIONS, function_help, list_functions, input_help
1313
from .io import format_input, parse_output, set_mode
14+
from .sysutils import build_win_dll_path
1415

1516
GEOLIB = None
1617

@@ -50,10 +51,13 @@ def __init__(self, geosupport_path=None, geosupport_version=None):
5051
kernel32.FreeLibrary.argtypes = [wintypes.HMODULE]
5152
kernel32.FreeLibrary(GEOLIB._handle)
5253

54+
# get the full path to the NYCGEO.dll
55+
nyc_geo_dll_path = build_win_dll_path(geosupport_path)
56+
5357
if self.py_bit == '64':
54-
self.geolib = cdll.LoadLibrary("NYCGEO.dll")
58+
self.geolib = cdll.LoadLibrary(nyc_geo_dll_path)
5559
else:
56-
self.geolib = windll.LoadLibrary("NYCGEO.dll")
60+
self.geolib = windll.LoadLibrary(nyc_geo_dll_path)
5761
elif self.platform.startswith('linux'):
5862
from ctypes import cdll
5963

geosupport/sysutils.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import os
2+
3+
4+
def build_win_dll_path(geosupport_path=None, dll_filename='nycgeo.dll'):
5+
""""
6+
Windows specific function to return full path of the nycgeo.dll
7+
example: 'C:\\Program Files\\Geosupport Desktop Edition\\Bin\\NYCGEO.dll'
8+
"""
9+
# return the provided geosupport path with the proper suffix pointing to the dll
10+
if geosupport_path:
11+
return os.path.join(geosupport_path, 'bin', dll_filename)
12+
# otherwise try to find the nycgeo.dll from system path entries
13+
system_path_entries = os.environ['PATH'].split(';')
14+
# look for directories ending with 'bin' since this is where the nycgeo.dll is stored
15+
bin_directories = [b for b in system_path_entries if b.endswith('bin')]
16+
# scan the bin directories for the nycgeo.dll, returning first occurrence.
17+
for b in bin_directories:
18+
file_names = [fn for fn in os.listdir(b)]
19+
for file in file_names:
20+
if file.lower() == dll_filename.lower():
21+
return os.path.join(b, file)
22+
raise Exception(
23+
"Unable to locate the {0} within your system. Ensure the Geosupport 'bin' directory is in your system path.".format(
24+
dll_filename))

tests/functional/test_call.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ def test_1E(self):
4848

4949
self.assertDictSubsetEqual({
5050
'City Council District': '01',
51-
'State Senatorial District': '26'
51+
'State Senatorial District': '27'
5252
}, result)
5353

5454
self.assertTrue('Physical ID' not in result)
@@ -220,11 +220,11 @@ def test_2W_more_than_2_intersections(self):
220220

221221
self.assertEqual(
222222
str(cm.exception),
223-
'STREETS INTERSECT MORE THAN TWICE - USE NODE AS INPUT '
223+
'PLAZA STREET EAST IS AN INVALID STREET NAME FOR THIS LOCATION '
224224
)
225225

226-
self.assertEqual(len(cm.exception.result['List of Nodes']), 4)
227-
self.assertEqual(len(cm.exception.result['B7SCs For Nodes']), 4)
226+
self.assertEqual(len(cm.exception.result['List of Street Codes']), 2)
227+
self.assertEqual(len(cm.exception.result['List of Street Names']), 2)
228228

229229
self.assertEqual(cm.exception.result['Node Number'], '')
230230

@@ -285,7 +285,7 @@ def test_3_extended(self):
285285
self.assertDictSubsetEqual({
286286
'From Node': '0015487',
287287
'To Node': '0020353',
288-
'Left NTA Name': 'SOHO-TRIBECA-CIVIC CENTER-LITTLE ITALY'
288+
'Left 2020 Community District Tabulation Area (CDTA)': 'MN01'
289289
}, result)
290290

291291
self.assertTrue('Segment IDs' not in result)
@@ -304,7 +304,7 @@ def test_3_extended_auxseg(self):
304304
self.assertDictSubsetEqual({
305305
'From Node': '0015487',
306306
'To Node': '0020353',
307-
'Left NTA Name': 'SOHO-TRIBECA-CIVIC CENTER-LITTLE ITALY'
307+
'Left 2020 Community District Tabulation Area (CDTA)': 'MN01'
308308
}, result)
309309

310310
self.assertEqual(len(result['Segment IDs']), 2)
@@ -367,11 +367,12 @@ def test_3C_extended_auxseg(self):
367367
'To Node': '0020353',
368368
'Side-of-Street Indicator': 'R',
369369
'Blockface ID': '0212262072'
370+
370371
}, result)
371372

372373
self.assertEqual(len(result['Segment IDs']), 2)
373-
self.assertTrue('0023578' in result['Segment IDs'])
374-
self.assertTrue('0032059' in result['Segment IDs'])
374+
self.assertTrue('7800320' in result['Segment IDs'])
375+
self.assertTrue('59' in result['Segment IDs'])
375376

376377
def test_3S(self):
377378
result = self.geosupport.call({

tests/unit/test_sysutils.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import os
2+
import sys
3+
from unittest import TestCase, mock, skipUnless
4+
from geosupport.sysutils import build_win_dll_path
5+
6+
7+
class TestSysUtils(TestCase):
8+
9+
@skipUnless(sys.platform.startswith("win"), "requires Windows")
10+
def test_build_dll_path_with_geosupport_path(self):
11+
""" test that the dll path is created from the provided geosupport path"""
12+
dll_path = build_win_dll_path(geosupport_path=r'C:\somewhere\on\my\pc')
13+
self.assertEqual(dll_path.lower(), r'c:\somewhere\on\my\pc\bin\nycgeo.dll')
14+
15+
@skipUnless(sys.platform.startswith("win"), "requires Windows")
16+
@mock.patch.dict(os.environ, {
17+
"PATH": r"C:\Program Files\Python311\Scripts\;C:\Program Files\Python311\;c:\another\place\on\my\pc\bin"})
18+
def test_build_dll_path_with_geosupport_path_none(self):
19+
""" test that the dll path is created when geosupport path is not provided"""
20+
with mock.patch('os.listdir') as mocked_listdir:
21+
mocked_listdir.return_value = ['geo.dll', 'docs', 'nycgeo.exe', 'nycgeo.dll']
22+
dll_path = build_win_dll_path(geosupport_path=None)
23+
self.assertEqual(dll_path.lower(), r'c:\another\place\on\my\pc\bin\nycgeo.dll')
24+
25+
@skipUnless(sys.platform.startswith("win"), "requires Windows")
26+
@mock.patch.dict(os.environ, {"PATH": "just a bunch of nonsense"})
27+
def test_build_dll_path_raise_exception(self):
28+
""" test that an exception is raised when the nycgeo.dll is not found"""
29+
with self.assertRaises(Exception) as context:
30+
build_win_dll_path(geosupport_path=None)
31+
self.assertTrue('Unable to locate the nycgeo.dll' in context.exception)

0 commit comments

Comments
 (0)