1818
1919from decimal import Decimal
2020from fractions import Fraction
21+ from test import support
2122
2223
2324# Module to be tested.
@@ -178,6 +179,23 @@ class _DoNothing:
178179# We prefer this for testing numeric values that may not be exactly equal,
179180# and avoid using TestCase.assertAlmostEqual, because it sucks :-)
180181
182+ py_statistics = support .import_fresh_module ('statistics' , blocked = ['_statistics' ])
183+ c_statistics = support .import_fresh_module ('statistics' , fresh = ['_statistics' ])
184+
185+
186+ class TestModules (unittest .TestCase ):
187+ func_names = ['_normal_dist_inv_cdf' ]
188+
189+ def test_py_functions (self ):
190+ for fname in self .func_names :
191+ self .assertEqual (getattr (py_statistics , fname ).__module__ , 'statistics' )
192+
193+ @unittest .skipUnless (c_statistics , 'requires _statistics' )
194+ def test_c_functions (self ):
195+ for fname in self .func_names :
196+ self .assertEqual (getattr (c_statistics , fname ).__module__ , '_statistics' )
197+
198+
181199class NumericTestCase (unittest .TestCase ):
182200 """Unit test class for numeric work.
183201
@@ -2314,7 +2332,7 @@ def test_error_cases(self):
23142332 quantiles ([10 , None , 30 ], n = 4 ) # data is non-numeric
23152333
23162334
2317- class TestNormalDist ( unittest . TestCase ) :
2335+ class TestNormalDist :
23182336
23192337 # General note on precision: The pdf(), cdf(), and overlap() methods
23202338 # depend on functions in the math libraries that do not make
@@ -2324,35 +2342,35 @@ class TestNormalDist(unittest.TestCase):
23242342 # implementing our own implementations from scratch.
23252343
23262344 def test_slots (self ):
2327- nd = statistics .NormalDist (300 , 23 )
2345+ nd = self . module .NormalDist (300 , 23 )
23282346 with self .assertRaises (TypeError ):
23292347 vars (nd )
23302348 self .assertEqual (tuple (nd .__slots__ ), ('_mu' , '_sigma' ))
23312349
23322350 def test_instantiation_and_attributes (self ):
2333- nd = statistics .NormalDist (500 , 17 )
2351+ nd = self . module .NormalDist (500 , 17 )
23342352 self .assertEqual (nd .mean , 500 )
23352353 self .assertEqual (nd .stdev , 17 )
23362354 self .assertEqual (nd .variance , 17 ** 2 )
23372355
23382356 # default arguments
2339- nd = statistics .NormalDist ()
2357+ nd = self . module .NormalDist ()
23402358 self .assertEqual (nd .mean , 0 )
23412359 self .assertEqual (nd .stdev , 1 )
23422360 self .assertEqual (nd .variance , 1 ** 2 )
23432361
23442362 # error case: negative sigma
2345- with self .assertRaises (statistics .StatisticsError ):
2346- statistics .NormalDist (500 , - 10 )
2363+ with self .assertRaises (self . module .StatisticsError ):
2364+ self . module .NormalDist (500 , - 10 )
23472365
23482366 # verify that subclass type is honored
2349- class NewNormalDist (statistics .NormalDist ):
2367+ class NewNormalDist (self . module .NormalDist ):
23502368 pass
23512369 nnd = NewNormalDist (200 , 5 )
23522370 self .assertEqual (type (nnd ), NewNormalDist )
23532371
23542372 def test_alternative_constructor (self ):
2355- NormalDist = statistics .NormalDist
2373+ NormalDist = self . module .NormalDist
23562374 data = [96 , 107 , 90 , 92 , 110 ]
23572375 # list input
23582376 self .assertEqual (NormalDist .from_samples (data ), NormalDist (99 , 9 ))
@@ -2361,9 +2379,9 @@ def test_alternative_constructor(self):
23612379 # iterator input
23622380 self .assertEqual (NormalDist .from_samples (iter (data )), NormalDist (99 , 9 ))
23632381 # error cases
2364- with self .assertRaises (statistics .StatisticsError ):
2382+ with self .assertRaises (self . module .StatisticsError ):
23652383 NormalDist .from_samples ([]) # empty input
2366- with self .assertRaises (statistics .StatisticsError ):
2384+ with self .assertRaises (self . module .StatisticsError ):
23672385 NormalDist .from_samples ([10 ]) # only one input
23682386
23692387 # verify that subclass type is honored
@@ -2373,15 +2391,15 @@ class NewNormalDist(NormalDist):
23732391 self .assertEqual (type (nnd ), NewNormalDist )
23742392
23752393 def test_sample_generation (self ):
2376- NormalDist = statistics .NormalDist
2394+ NormalDist = self . module .NormalDist
23772395 mu , sigma = 10_000 , 3.0
23782396 X = NormalDist (mu , sigma )
23792397 n = 1_000
23802398 data = X .samples (n )
23812399 self .assertEqual (len (data ), n )
23822400 self .assertEqual (set (map (type , data )), {float })
23832401 # mean(data) expected to fall within 8 standard deviations
2384- xbar = statistics .mean (data )
2402+ xbar = self . module .mean (data )
23852403 self .assertTrue (mu - sigma * 8 <= xbar <= mu + sigma * 8 )
23862404
23872405 # verify that seeding makes reproducible sequences
@@ -2395,7 +2413,7 @@ def test_sample_generation(self):
23952413 self .assertNotEqual (data1 , data2 )
23962414
23972415 def test_pdf (self ):
2398- NormalDist = statistics .NormalDist
2416+ NormalDist = self . module .NormalDist
23992417 X = NormalDist (100 , 15 )
24002418 # Verify peak around center
24012419 self .assertLess (X .pdf (99 ), X .pdf (100 ))
@@ -2426,15 +2444,15 @@ def test_pdf(self):
24262444 self .assertAlmostEqual (Z .pdf (- x / 100.0 ), px , places = 4 )
24272445 # Error case: variance is zero
24282446 Y = NormalDist (100 , 0 )
2429- with self .assertRaises (statistics .StatisticsError ):
2447+ with self .assertRaises (self . module .StatisticsError ):
24302448 Y .pdf (90 )
24312449 # Special values
24322450 self .assertEqual (X .pdf (float ('-Inf' )), 0.0 )
24332451 self .assertEqual (X .pdf (float ('Inf' )), 0.0 )
24342452 self .assertTrue (math .isnan (X .pdf (float ('NaN' ))))
24352453
24362454 def test_cdf (self ):
2437- NormalDist = statistics .NormalDist
2455+ NormalDist = self . module .NormalDist
24382456 X = NormalDist (100 , 15 )
24392457 cdfs = [X .cdf (x ) for x in range (1 , 200 )]
24402458 self .assertEqual (set (map (type , cdfs )), {float })
@@ -2456,7 +2474,7 @@ def test_cdf(self):
24562474 self .assertAlmostEqual (Z .cdf (- z ), 1.0 - cum_prob , places = 5 )
24572475 # Error case: variance is zero
24582476 Y = NormalDist (100 , 0 )
2459- with self .assertRaises (statistics .StatisticsError ):
2477+ with self .assertRaises (self . module .StatisticsError ):
24602478 Y .cdf (90 )
24612479 # Special values
24622480 self .assertEqual (X .cdf (float ('-Inf' )), 0.0 )
@@ -2465,7 +2483,7 @@ def test_cdf(self):
24652483
24662484 @support .skip_if_pgo_task
24672485 def test_inv_cdf (self ):
2468- NormalDist = statistics .NormalDist
2486+ NormalDist = self . module .NormalDist
24692487
24702488 # Center case should be exact.
24712489 iq = NormalDist (100 , 15 )
@@ -2513,23 +2531,23 @@ def test_inv_cdf(self):
25132531 self .assertAlmostEqual (iq .inv_cdf (iq .cdf (x )), x , places = 5 )
25142532
25152533 # Error cases:
2516- with self .assertRaises (statistics .StatisticsError ):
2534+ with self .assertRaises (self . module .StatisticsError ):
25172535 iq .inv_cdf (0.0 ) # p is zero
2518- with self .assertRaises (statistics .StatisticsError ):
2536+ with self .assertRaises (self . module .StatisticsError ):
25192537 iq .inv_cdf (- 0.1 ) # p under zero
2520- with self .assertRaises (statistics .StatisticsError ):
2538+ with self .assertRaises (self . module .StatisticsError ):
25212539 iq .inv_cdf (1.0 ) # p is one
2522- with self .assertRaises (statistics .StatisticsError ):
2540+ with self .assertRaises (self . module .StatisticsError ):
25232541 iq .inv_cdf (1.1 ) # p over one
2524- with self .assertRaises (statistics .StatisticsError ):
2542+ with self .assertRaises (self . module .StatisticsError ):
25252543 iq = NormalDist (100 , 0 ) # sigma is zero
25262544 iq .inv_cdf (0.5 )
25272545
25282546 # Special values
25292547 self .assertTrue (math .isnan (Z .inv_cdf (float ('NaN' ))))
25302548
25312549 def test_overlap (self ):
2532- NormalDist = statistics .NormalDist
2550+ NormalDist = self . module .NormalDist
25332551
25342552 # Match examples from Imman and Bradley
25352553 for X1 , X2 , published_result in [
@@ -2586,26 +2604,26 @@ def overlap_numeric(X, Y, *, steps=8_192, z=5):
25862604 X .overlap (X , X ) # too may arguments
25872605 with self .assertRaises (TypeError ):
25882606 X .overlap (None ) # right operand not a NormalDist
2589- with self .assertRaises (statistics .StatisticsError ):
2607+ with self .assertRaises (self . module .StatisticsError ):
25902608 X .overlap (NormalDist (1 , 0 )) # right operand sigma is zero
2591- with self .assertRaises (statistics .StatisticsError ):
2609+ with self .assertRaises (self . module .StatisticsError ):
25922610 NormalDist (1 , 0 ).overlap (X ) # left operand sigma is zero
25932611
25942612 def test_properties (self ):
2595- X = statistics .NormalDist (100 , 15 )
2613+ X = self . module .NormalDist (100 , 15 )
25962614 self .assertEqual (X .mean , 100 )
25972615 self .assertEqual (X .stdev , 15 )
25982616 self .assertEqual (X .variance , 225 )
25992617
26002618 def test_same_type_addition_and_subtraction (self ):
2601- NormalDist = statistics .NormalDist
2619+ NormalDist = self . module .NormalDist
26022620 X = NormalDist (100 , 12 )
26032621 Y = NormalDist (40 , 5 )
26042622 self .assertEqual (X + Y , NormalDist (140 , 13 )) # __add__
26052623 self .assertEqual (X - Y , NormalDist (60 , 13 )) # __sub__
26062624
26072625 def test_translation_and_scaling (self ):
2608- NormalDist = statistics .NormalDist
2626+ NormalDist = self . module .NormalDist
26092627 X = NormalDist (100 , 15 )
26102628 y = 10
26112629 self .assertEqual (+ X , NormalDist (100 , 15 )) # __pos__
@@ -2621,7 +2639,7 @@ def test_translation_and_scaling(self):
26212639 y / X
26222640
26232641 def test_unary_operations (self ):
2624- NormalDist = statistics .NormalDist
2642+ NormalDist = self . module .NormalDist
26252643 X = NormalDist (100 , 12 )
26262644 Y = + X
26272645 self .assertIsNot (X , Y )
@@ -2633,7 +2651,7 @@ def test_unary_operations(self):
26332651 self .assertEqual (X .stdev , Y .stdev )
26342652
26352653 def test_equality (self ):
2636- NormalDist = statistics .NormalDist
2654+ NormalDist = self . module .NormalDist
26372655 nd1 = NormalDist ()
26382656 nd2 = NormalDist (2 , 4 )
26392657 nd3 = NormalDist ()
@@ -2673,7 +2691,7 @@ def __init__(self, mu, sigma):
26732691 self .assertNotEqual (nd , lnd )
26742692
26752693 def test_pickle_and_copy (self ):
2676- nd = statistics .NormalDist (37.5 , 5.625 )
2694+ nd = self . module .NormalDist (37.5 , 5.625 )
26772695 nd1 = copy .copy (nd )
26782696 self .assertEqual (nd , nd1 )
26792697 nd2 = copy .deepcopy (nd )
@@ -2682,14 +2700,36 @@ def test_pickle_and_copy(self):
26822700 self .assertEqual (nd , nd3 )
26832701
26842702 def test_hashability (self ):
2685- ND = statistics .NormalDist
2703+ ND = self . module .NormalDist
26862704 s = {ND (100 , 15 ), ND (100.0 , 15.0 ), ND (100 , 10 ), ND (95 , 15 ), ND (100 , 15 )}
26872705 self .assertEqual (len (s ), 3 )
26882706
26892707 def test_repr (self ):
2690- nd = statistics .NormalDist (37.5 , 5.625 )
2708+ nd = self . module .NormalDist (37.5 , 5.625 )
26912709 self .assertEqual (repr (nd ), 'NormalDist(mu=37.5, sigma=5.625)' )
26922710
2711+ # Swapping the sys.modules['statistics'] is to solving the
2712+ # _pickle.PicklingError:
2713+ # Can't pickle <class 'statistics.NormalDist'>:
2714+ # it's not the same object as statistics.NormalDist
2715+ class TestNormalDistPython (unittest .TestCase , TestNormalDist ):
2716+ module = py_statistics
2717+ def setUp (self ):
2718+ sys .modules ['statistics' ] = self .module
2719+
2720+ def tearDown (self ):
2721+ sys .modules ['statistics' ] = statistics
2722+
2723+
2724+ @unittest .skipUnless (c_statistics , 'requires _statistics' )
2725+ class TestNormalDistC (unittest .TestCase , TestNormalDist ):
2726+ module = c_statistics
2727+ def setUp (self ):
2728+ sys .modules ['statistics' ] = self .module
2729+
2730+ def tearDown (self ):
2731+ sys .modules ['statistics' ] = statistics
2732+
26932733
26942734# === Run tests ===
26952735
0 commit comments