diff --git a/Doc/conf.py b/Doc/conf.py --- a/Doc/conf.py +++ b/Doc/conf.py @@ -8,6 +8,7 @@ import sys, os, time sys.path.append(os.path.abspath('tools/extensions')) +sys.path.append(os.path.abspath('includes')) # General configuration # --------------------- @@ -198,3 +199,31 @@ # Relative filename of the reference count data file. refcount_file = 'data/refcounts.dat' + +# When we execute the doctests under Sphinx, the __main__ module is +# the sphinx-build script, that is why we can not use the __main__ +# module as we do in the REPL. For instance, this example does not work: +# +# >>> b = 33 +# >>> import __main__ +# >>> __main__.b +# 33 +# +# To solve the problem, we can set `doctest_global_setup` in the following way. +doctest_global_setup = """ +import sys +import __main__ + +# keep a reference to __main__ +__main = __main__ + +class ProxyModule(object): + def __init__(self): + self.__dict__ = globals() + +sys.modules['__main__'] = ProxyModule() +""" + +doctest_global_cleanup = """ +sys.modules['__main__'] = __main +""" diff --git a/Doc/faq/programming.rst b/Doc/faq/programming.rst --- a/Doc/faq/programming.rst +++ b/Doc/faq/programming.rst @@ -203,7 +203,7 @@ ---------------------------------------------------------------------------------- Assume you use a for loop to define a few different lambdas (or even plain -functions), e.g.:: +functions), e.g.: >>> squares = [] >>> for x in range(5): @@ -212,7 +212,7 @@ This gives you a list that contains 5 lambdas that calculate ``x**2``. You might expect that, when called, they would return, respectively, ``0``, ``1``, ``4``, ``9``, and ``16``. However, when you actually try you will see that -they all return ``16``:: +they all return ``16``: >>> squares[2]() 16 @@ -223,14 +223,14 @@ the outer scope, and it is accessed when the lambda is called --- not when it is defined. At the end of the loop, the value of ``x`` is ``4``, so all the functions now return ``4**2``, i.e. ``16``. You can also verify this by -changing the value of ``x`` and see how the results of the lambdas change:: +changing the value of ``x`` and see how the results of the lambdas change: >>> x = 8 >>> squares[2]() 64 In order to avoid this, you need to save the values in variables local to the -lambdas, so that they don't rely on the value of the global ``x``:: +lambdas, so that they don't rely on the value of the global ``x``: >>> squares = [] >>> for x in range(5): @@ -240,7 +240,7 @@ when the lambda is defined so that it has the same value that ``x`` had at that point in the loop. This means that the value of ``n`` will be ``0`` in the first lambda, ``1`` in the second, ``2`` in the third, and so on. -Therefore each lambda will now return the correct result:: +Therefore each lambda will now return the correct result: >>> squares[2]() 4 @@ -428,7 +428,7 @@ Why did changing list 'y' also change list 'x'? ------------------------------------------------ -If you wrote code like:: +If you wrote code like: >>> x = [] >>> y = x @@ -452,7 +452,7 @@ changed from ``[]`` to ``[10]``. Since both the variables refer to the same object, using either name accesses the modified value ``[10]``. -If we instead assign an immutable object to ``x``:: +If we instead assign an immutable object to ``x``: >>> x = 5 # ints are immutable >>> y = x @@ -653,7 +653,7 @@ Generally speaking, it can't, because objects don't really have names. Essentially, assignment always binds a name to a value; The same is true of ``def`` and ``class`` statements, but in that case the value is a -callable. Consider the following code:: +callable. Consider the following code: >>> class A: ... pass @@ -662,9 +662,9 @@ >>> a = B() >>> b = a >>> print(b) - <__main__.A object at 0x16D07CC> + >>> print(a) - <__main__.A object at 0x16D07CC> + Arguably the class has a name: even though it is bound to two names and invoked through the name B the created instance is still reported as an instance of @@ -691,7 +691,7 @@ What's up with the comma operator's precedence? ----------------------------------------------- -Comma is not an operator in Python. Consider this session:: +Comma is not an operator in Python. Consider this session: >>> "a" in "b", "a" (False, 'a') @@ -770,7 +770,7 @@ To specify an octal digit, precede the octal value with a zero, and then a lower or uppercase "o". For example, to set the variable "a" to the octal value "10" -(8 in decimal), type:: +(8 in decimal), type: >>> a = 0o10 >>> a @@ -778,7 +778,7 @@ Hexadecimal is just as easy. Simply precede the hexadecimal number with a zero, and then a lower or uppercase "x". Hexadecimal digits can be specified in lower -or uppercase. For example, in the Python interpreter:: +or uppercase. For example, in the Python interpreter: >>> a = 0xa5 >>> a @@ -850,7 +850,7 @@ simply construct a new string from the various parts you want to assemble it from. However, if you need an object with the ability to modify in-place unicode data, try using an :class:`io.StringIO` object or the :mod:`array` -module:: +module: >>> import io >>> s = "Hello, world" @@ -940,7 +940,7 @@ terminator from the end of the string ``S`` without removing other trailing whitespace. If the string ``S`` represents more than one line, with several empty lines at the end, the line terminators for all the blank lines will -be removed:: +be removed: >>> lines = ("line 1 \r\n" ... "\r\n" @@ -1168,28 +1168,26 @@ How do I create a multidimensional list? ---------------------------------------- -You probably tried to make a multidimensional array like this:: +You probably tried to make a multidimensional array like this: + +.. testsetup:: multidimensional-list + + A = [[None] * 2] * 3 + +.. doctest:: multidimensional-list >>> A = [[None] * 2] * 3 This looks correct if you print it: -.. testsetup:: - - A = [[None] * 2] * 3 - -.. doctest:: +.. doctest:: multidimensional-list >>> A [[None, None], [None, None], [None, None]] But when you assign a value, it shows up in multiple places: -.. testsetup:: - - A = [[None] * 2] * 3 - -.. doctest:: +.. doctest:: multidimensional-list >>> A[0][0] = 5 >>> A @@ -1201,14 +1199,18 @@ show in all rows, which is almost certainly not what you want. The suggested approach is to create a list of the desired length first and then -fill in each element with a newly created list:: +fill in each element with a newly created list: + +.. doctest:: A = [None] * 3 for i in range(3): A[i] = [None] * 2 This generates a list containing 3 different lists of length two. You can also -use a list comprehension:: +use a list comprehension: + +.. doctest:: w, h = 2, 3 A = [[None] * w for i in range(h)] @@ -1237,7 +1239,7 @@ applied to elements of a tuple that point to mutable objects, but we'll use a ``list`` and ``+=`` as our exemplar. -If you wrote:: +If you wrote: >>> a_tuple = (1, 2) >>> a_tuple[0] += 1 @@ -1252,7 +1254,7 @@ a tuple points to. Under the covers, what this augmented assignment statement is doing is -approximately this:: +approximately this: >>> result = a_tuple[0] + 1 >>> a_tuple[0] = result @@ -1263,7 +1265,7 @@ It is the assignment part of the operation that produces the error, since a tuple is immutable. -When you write something like:: +When you write something like: >>> a_tuple = (['foo'], 'bar') >>> a_tuple[0] += ['item'] @@ -1272,7 +1274,7 @@ TypeError: 'tuple' object does not support item assignment The exception is a bit more surprising, and even more surprising is the fact -that even though there was an error, the append worked:: +that even though there was an error, the append worked: >>> a_tuple[0] ['foo', 'item'] @@ -1282,14 +1284,14 @@ is executed, and its return value is what gets used in the assignment statement; and (b) for lists, ``__iadd__`` is equivalent to calling ``extend`` on the list and returning the list. That's why we say that for lists, ``+=`` is a -"shorthand" for ``list.extend``:: +"shorthand" for ``list.extend``: >>> a_list = [] >>> a_list += [1] >>> a_list [1] -This is equivalent to:: +This is equivalent to: >>> result = a_list.__iadd__([1]) >>> a_list = result @@ -1299,7 +1301,7 @@ assignment is a no-op, since it is a pointer to the same object that ``a_list`` was previously pointing to, but the assignment still happens. -Thus, in our tuple example what is happening is equivalent to:: +Thus, in our tuple example what is happening is equivalent to: >>> result = a_tuple[0].__iadd__(['item']) >>> a_tuple[0] = result @@ -1335,7 +1337,9 @@ ---------------------------------------------------- Merge them into an iterator of tuples, sort the resulting list, and then pick -out the element you want. :: +out the element you want. + +.. doctest:: >>> list1 = ["what", "I'm", "sorting", "by"] >>> list2 = ["something", "else", "to", "sort"] @@ -1348,7 +1352,7 @@ ['else', 'sort', 'to', 'something'] -An alternative for the last step is:: +An alternative for the last step is: >>> result = [] >>> for p in pairs: result.append(p[1]) @@ -1851,18 +1855,34 @@ updated to use the new class definition. This can result in the following paradoxical behaviour: +.. testsetup:: reload + + import sys + import os + import faq.programming.cls as cls + cls_dir = os.path.dirname(cls.__file__) + sys.path.append(cls_dir) + +.. testcleanup:: reload + + sys.path.remove(cls_dir) + +.. doctest:: reload + >>> import importlib >>> import cls >>> c = cls.C() # Create an instance of C >>> importlib.reload(cls) - + >>> isinstance(c, cls.C) # isinstance is false?!? False The nature of the problem is made clear if you print out the "identity" of the class objects: - >>> hex(id(c.__class__)) +.. doctest:: reload + + >>> hex(id(c.__class__)) # doctest: +SKIP '0x7352a0' - >>> hex(id(cls.C)) + >>> hex(id(cls.C)) # doctest: +SKIP '0x4198d0' diff --git a/Doc/includes/faq/programming/cls.py b/Doc/includes/faq/programming/cls.py new file mode 100644 --- /dev/null +++ b/Doc/includes/faq/programming/cls.py @@ -0,0 +1,2 @@ +class C: + pass diff --git a/Doc/includes/pathlib/bar b/Doc/includes/pathlib/bar new file mode 100644 --- /dev/null +++ b/Doc/includes/pathlib/bar @@ -0,0 +1,1 @@ +some text \ No newline at end of file diff --git a/Doc/includes/pathlib/build/lib/pathlib.py b/Doc/includes/pathlib/build/lib/pathlib.py new file mode 100644 diff --git a/Doc/includes/pathlib/docs/conf.py b/Doc/includes/pathlib/docs/conf.py new file mode 100644 diff --git a/Doc/includes/pathlib/eggs b/Doc/includes/pathlib/eggs new file mode 100644 diff --git a/Doc/includes/pathlib/my_binary_file b/Doc/includes/pathlib/my_binary_file new file mode 100644 --- /dev/null +++ b/Doc/includes/pathlib/my_binary_file @@ -0,0 +1,1 @@ +Binary file contents \ No newline at end of file diff --git a/Doc/includes/pathlib/my_text_file b/Doc/includes/pathlib/my_text_file new file mode 100644 --- /dev/null +++ b/Doc/includes/pathlib/my_text_file @@ -0,0 +1,1 @@ +Text file contents \ No newline at end of file diff --git a/Doc/includes/pathlib/pathlib.py b/Doc/includes/pathlib/pathlib.py new file mode 100644 diff --git a/Doc/includes/pathlib/setup.py b/Doc/includes/pathlib/setup.py new file mode 100644 --- /dev/null +++ b/Doc/includes/pathlib/setup.py @@ -0,0 +1,1 @@ +# A dummy setup file diff --git a/Doc/includes/pathlib/spam b/Doc/includes/pathlib/spam new file mode 100644 diff --git a/Doc/includes/pathlib/test_pathlib.py b/Doc/includes/pathlib/test_pathlib.py new file mode 100644 diff --git a/Doc/includes/tzinfo-examples.py b/Doc/includes/tzinfo-examples.py deleted file mode 100644 --- a/Doc/includes/tzinfo-examples.py +++ /dev/null @@ -1,175 +0,0 @@ -from datetime import tzinfo, timedelta, datetime, timezone - -ZERO = timedelta(0) -HOUR = timedelta(hours=1) -SECOND = timedelta(seconds=1) - -# A class capturing the platform's idea of local time. -# (May result in wrong values on historical times in -# timezones where UTC offset and/or the DST rules had -# changed in the past.) -import time as _time - -STDOFFSET = timedelta(seconds = -_time.timezone) -if _time.daylight: - DSTOFFSET = timedelta(seconds = -_time.altzone) -else: - DSTOFFSET = STDOFFSET - -DSTDIFF = DSTOFFSET - STDOFFSET - -class LocalTimezone(tzinfo): - - def fromutc(self, dt): - assert dt.tzinfo is self - stamp = (dt - datetime(1970, 1, 1, tzinfo=self)) // SECOND - args = _time.localtime(stamp)[:6] - dst_diff = DSTDIFF // SECOND - # Detect fold - fold = (args == _time.localtime(stamp - dst_diff)) - return datetime(*args, microsecond=dt.microsecond, - tzinfo=self, fold=fold) - - def utcoffset(self, dt): - if self._isdst(dt): - return DSTOFFSET - else: - return STDOFFSET - - def dst(self, dt): - if self._isdst(dt): - return DSTDIFF - else: - return ZERO - - def tzname(self, dt): - return _time.tzname[self._isdst(dt)] - - def _isdst(self, dt): - tt = (dt.year, dt.month, dt.day, - dt.hour, dt.minute, dt.second, - dt.weekday(), 0, 0) - stamp = _time.mktime(tt) - tt = _time.localtime(stamp) - return tt.tm_isdst > 0 - -Local = LocalTimezone() - - -# A complete implementation of current DST rules for major US time zones. - -def first_sunday_on_or_after(dt): - days_to_go = 6 - dt.weekday() - if days_to_go: - dt += timedelta(days_to_go) - return dt - - -# US DST Rules -# -# This is a simplified (i.e., wrong for a few cases) set of rules for US -# DST start and end times. For a complete and up-to-date set of DST rules -# and timezone definitions, visit the Olson Database (or try pytz): -# http://www.twinsun.com/tz/tz-link.htm -# http://sourceforge.net/projects/pytz/ (might not be up-to-date) -# -# In the US, since 2007, DST starts at 2am (standard time) on the second -# Sunday in March, which is the first Sunday on or after Mar 8. -DSTSTART_2007 = datetime(1, 3, 8, 2) -# and ends at 2am (DST time) on the first Sunday of Nov. -DSTEND_2007 = datetime(1, 11, 1, 2) -# From 1987 to 2006, DST used to start at 2am (standard time) on the first -# Sunday in April and to end at 2am (DST time) on the last -# Sunday of October, which is the first Sunday on or after Oct 25. -DSTSTART_1987_2006 = datetime(1, 4, 1, 2) -DSTEND_1987_2006 = datetime(1, 10, 25, 2) -# From 1967 to 1986, DST used to start at 2am (standard time) on the last -# Sunday in April (the one on or after April 24) and to end at 2am (DST time) -# on the last Sunday of October, which is the first Sunday -# on or after Oct 25. -DSTSTART_1967_1986 = datetime(1, 4, 24, 2) -DSTEND_1967_1986 = DSTEND_1987_2006 - -def us_dst_range(year): - # Find start and end times for US DST. For years before 1967, return - # start = end for no DST. - if 2006 < year: - dststart, dstend = DSTSTART_2007, DSTEND_2007 - elif 1986 < year < 2007: - dststart, dstend = DSTSTART_1987_2006, DSTEND_1987_2006 - elif 1966 < year < 1987: - dststart, dstend = DSTSTART_1967_1986, DSTEND_1967_1986 - else: - return (datetime(year, 1, 1), ) * 2 - - start = first_sunday_on_or_after(dststart.replace(year=year)) - end = first_sunday_on_or_after(dstend.replace(year=year)) - return start, end - - -class USTimeZone(tzinfo): - - def __init__(self, hours, reprname, stdname, dstname): - self.stdoffset = timedelta(hours=hours) - self.reprname = reprname - self.stdname = stdname - self.dstname = dstname - - def __repr__(self): - return self.reprname - - def tzname(self, dt): - if self.dst(dt): - return self.dstname - else: - return self.stdname - - def utcoffset(self, dt): - return self.stdoffset + self.dst(dt) - - def dst(self, dt): - if dt is None or dt.tzinfo is None: - # An exception may be sensible here, in one or both cases. - # It depends on how you want to treat them. The default - # fromutc() implementation (called by the default astimezone() - # implementation) passes a datetime with dt.tzinfo is self. - return ZERO - assert dt.tzinfo is self - start, end = us_dst_range(dt.year) - # Can't compare naive to aware objects, so strip the timezone from - # dt first. - dt = dt.replace(tzinfo=None) - if start + HOUR <= dt < end - HOUR: - # DST is in effect. - return HOUR - if end - HOUR <= dt < end: - # Fold (an ambiguous hour): use dt.fold to disambiguate. - return ZERO if dt.fold else HOUR - if start <= dt < start + HOUR: - # Gap (a non-existent hour): reverse the fold rule. - return HOUR if dt.fold else ZERO - # DST is off. - return ZERO - - def fromutc(self, dt): - assert dt.tzinfo is self - start, end = us_dst_range(dt.year) - start = start.replace(tzinfo=self) - end = end.replace(tzinfo=self) - std_time = dt + self.stdoffset - dst_time = std_time + HOUR - if end <= dst_time < end + HOUR: - # Repeated hour - return std_time.replace(fold=1) - if std_time < start or dst_time >= end: - # Standard time - return std_time - if start <= std_time < end - HOUR: - # Daylight saving time - return dst_time - - -Eastern = USTimeZone(-5, "Eastern", "EST", "EDT") -Central = USTimeZone(-6, "Central", "CST", "CDT") -Mountain = USTimeZone(-7, "Mountain", "MST", "MDT") -Pacific = USTimeZone(-8, "Pacific", "PST", "PDT") diff --git a/Doc/includes/tzinfo_examples.py b/Doc/includes/tzinfo_examples.py new file mode 100644 --- /dev/null +++ b/Doc/includes/tzinfo_examples.py @@ -0,0 +1,175 @@ +from datetime import tzinfo, timedelta, datetime, timezone + +ZERO = timedelta(0) +HOUR = timedelta(hours=1) +SECOND = timedelta(seconds=1) + +# A class capturing the platform's idea of local time. +# (May result in wrong values on historical times in +# timezones where UTC offset and/or the DST rules had +# changed in the past.) +import time as _time + +STDOFFSET = timedelta(seconds = -_time.timezone) +if _time.daylight: + DSTOFFSET = timedelta(seconds = -_time.altzone) +else: + DSTOFFSET = STDOFFSET + +DSTDIFF = DSTOFFSET - STDOFFSET + +class LocalTimezone(tzinfo): + + def fromutc(self, dt): + assert dt.tzinfo is self + stamp = (dt - datetime(1970, 1, 1, tzinfo=self)) // SECOND + args = _time.localtime(stamp)[:6] + dst_diff = DSTDIFF // SECOND + # Detect fold + fold = (args == _time.localtime(stamp - dst_diff)) + return datetime(*args, microsecond=dt.microsecond, + tzinfo=self, fold=fold) + + def utcoffset(self, dt): + if self._isdst(dt): + return DSTOFFSET + else: + return STDOFFSET + + def dst(self, dt): + if self._isdst(dt): + return DSTDIFF + else: + return ZERO + + def tzname(self, dt): + return _time.tzname[self._isdst(dt)] + + def _isdst(self, dt): + tt = (dt.year, dt.month, dt.day, + dt.hour, dt.minute, dt.second, + dt.weekday(), 0, 0) + stamp = _time.mktime(tt) + tt = _time.localtime(stamp) + return tt.tm_isdst > 0 + +Local = LocalTimezone() + + +# A complete implementation of current DST rules for major US time zones. + +def first_sunday_on_or_after(dt): + days_to_go = 6 - dt.weekday() + if days_to_go: + dt += timedelta(days_to_go) + return dt + + +# US DST Rules +# +# This is a simplified (i.e., wrong for a few cases) set of rules for US +# DST start and end times. For a complete and up-to-date set of DST rules +# and timezone definitions, visit the Olson Database (or try pytz): +# http://www.twinsun.com/tz/tz-link.htm +# http://sourceforge.net/projects/pytz/ (might not be up-to-date) +# +# In the US, since 2007, DST starts at 2am (standard time) on the second +# Sunday in March, which is the first Sunday on or after Mar 8. +DSTSTART_2007 = datetime(1, 3, 8, 2) +# and ends at 2am (DST time) on the first Sunday of Nov. +DSTEND_2007 = datetime(1, 11, 1, 2) +# From 1987 to 2006, DST used to start at 2am (standard time) on the first +# Sunday in April and to end at 2am (DST time) on the last +# Sunday of October, which is the first Sunday on or after Oct 25. +DSTSTART_1987_2006 = datetime(1, 4, 1, 2) +DSTEND_1987_2006 = datetime(1, 10, 25, 2) +# From 1967 to 1986, DST used to start at 2am (standard time) on the last +# Sunday in April (the one on or after April 24) and to end at 2am (DST time) +# on the last Sunday of October, which is the first Sunday +# on or after Oct 25. +DSTSTART_1967_1986 = datetime(1, 4, 24, 2) +DSTEND_1967_1986 = DSTEND_1987_2006 + +def us_dst_range(year): + # Find start and end times for US DST. For years before 1967, return + # start = end for no DST. + if 2006 < year: + dststart, dstend = DSTSTART_2007, DSTEND_2007 + elif 1986 < year < 2007: + dststart, dstend = DSTSTART_1987_2006, DSTEND_1987_2006 + elif 1966 < year < 1987: + dststart, dstend = DSTSTART_1967_1986, DSTEND_1967_1986 + else: + return (datetime(year, 1, 1), ) * 2 + + start = first_sunday_on_or_after(dststart.replace(year=year)) + end = first_sunday_on_or_after(dstend.replace(year=year)) + return start, end + + +class USTimeZone(tzinfo): + + def __init__(self, hours, reprname, stdname, dstname): + self.stdoffset = timedelta(hours=hours) + self.reprname = reprname + self.stdname = stdname + self.dstname = dstname + + def __repr__(self): + return self.reprname + + def tzname(self, dt): + if self.dst(dt): + return self.dstname + else: + return self.stdname + + def utcoffset(self, dt): + return self.stdoffset + self.dst(dt) + + def dst(self, dt): + if dt is None or dt.tzinfo is None: + # An exception may be sensible here, in one or both cases. + # It depends on how you want to treat them. The default + # fromutc() implementation (called by the default astimezone() + # implementation) passes a datetime with dt.tzinfo is self. + return ZERO + assert dt.tzinfo is self + start, end = us_dst_range(dt.year) + # Can't compare naive to aware objects, so strip the timezone from + # dt first. + dt = dt.replace(tzinfo=None) + if start + HOUR <= dt < end - HOUR: + # DST is in effect. + return HOUR + if end - HOUR <= dt < end: + # Fold (an ambiguous hour): use dt.fold to disambiguate. + return ZERO if dt.fold else HOUR + if start <= dt < start + HOUR: + # Gap (a non-existent hour): reverse the fold rule. + return HOUR if dt.fold else ZERO + # DST is off. + return ZERO + + def fromutc(self, dt): + assert dt.tzinfo is self + start, end = us_dst_range(dt.year) + start = start.replace(tzinfo=self) + end = end.replace(tzinfo=self) + std_time = dt + self.stdoffset + dst_time = std_time + HOUR + if end <= dst_time < end + HOUR: + # Repeated hour + return std_time.replace(fold=1) + if std_time < start or dst_time >= end: + # Standard time + return std_time + if start <= std_time < end - HOUR: + # Daylight saving time + return dst_time + + +Eastern = USTimeZone(-5, "Eastern", "EST", "EDT") +Central = USTimeZone(-6, "Central", "CST", "CDT") +Mountain = USTimeZone(-7, "Mountain", "MST", "MDT") +Pacific = USTimeZone(-8, "Pacific", "PST", "PDT") diff --git a/Doc/includes/unittest_mock/mymodule.py b/Doc/includes/unittest_mock/mymodule.py new file mode 100644 --- /dev/null +++ b/Doc/includes/unittest_mock/mymodule.py @@ -0,0 +1,9 @@ +def frob(val): + pass + +def grob(val): + "First frob and then clear val" + frob(val) + val.clear() + +Class1 = Class2 = Foo = Bar = Spam = SomeClass = date = None diff --git a/Doc/includes/unittest_mock/package/module.py b/Doc/includes/unittest_mock/package/module.py new file mode 100644 --- /dev/null +++ b/Doc/includes/unittest_mock/package/module.py @@ -0,0 +1,11 @@ +attribute = 'attr' + +class ClassName: + attribute = None + + +class ClassName1: + pass + +class ClassName2: + pass diff --git a/Doc/library/configparser.rst b/Doc/library/configparser.rst --- a/Doc/library/configparser.rst +++ b/Doc/library/configparser.rst @@ -116,13 +116,13 @@ 'no' >>> topsecret['Port'] '50022' - >>> for key in config['bitbucket.org']: print(key) - ... + >>> for key in sorted(config['bitbucket.org']): + ... print(key) + compression + compressionlevel + forwardx11 + serveraliveinterval user - compressionlevel - serveraliveinterval - compression - forwardx11 >>> config['bitbucket.org']['ForwardX11'] 'yes' @@ -469,10 +469,10 @@ ... 'bar': 'y', ... 'baz': 'z'} ... }) - >>> parser.sections() - ['section3', 'section2', 'section1'] - >>> [option for option in parser['section3']] - ['baz', 'foo', 'bar'] + >>> sorted(parser.sections()) + ['section1', 'section2', 'section3'] + >>> sorted(option for option in parser['section3']) + ['bar', 'baz', 'foo'] In these operations you need to use an ordered dictionary as well: @@ -514,8 +514,6 @@ .. doctest:: - >>> import configparser - >>> sample_config = """ ... [mysqld] ... user = mysql @@ -571,7 +569,9 @@ values with characters used as comment prefixes. When in doubt, avoid setting *inline_comment_prefixes*. In any circumstances, the only way of storing comment prefix characters at the beginning of a line in multiline - values is to interpolate the prefix, for example:: + values is to interpolate the prefix, for example: + + .. doctest:: >>> from configparser import ConfigParser, ExtendedInterpolation >>> parser = ConfigParser(interpolation=ExtendedInterpolation()) @@ -597,11 +597,11 @@ ... line #3 ... """) >>> print(parser['hashes']['shebang']) - + #!/usr/bin/env python # -*- coding: utf-8 -*- >>> print(parser['hashes']['extensions']) - + enabled_extension another_extension yet_another_extension @@ -755,6 +755,7 @@ .. doctest:: + >>> import re >>> config = """ ... [Section 1] ... option = value @@ -762,11 +763,11 @@ ... [ Section 2 ] ... another = val ... """ - >>> typical = ConfigParser() + >>> typical = configparser.ConfigParser() >>> typical.read_string(config) >>> typical.sections() ['Section 1', ' Section 2 '] - >>> custom = ConfigParser() + >>> custom = configparser.ConfigParser() >>> custom.SECTCRE = re.compile(r"\[ *(?P
[^]]+?) *\]") >>> custom.read_string(config) >>> custom.sections() diff --git a/Doc/library/copyreg.rst b/Doc/library/copyreg.rst --- a/Doc/library/copyreg.rst +++ b/Doc/library/copyreg.rst @@ -48,6 +48,8 @@ The example below would like to show how to register a pickle function and how it will be used: +.. doctest:: + >>> import copyreg, copy, pickle >>> class C(object): ... def __init__(self, a): @@ -59,6 +61,20 @@ ... >>> copyreg.pickle(C, pickle_c) >>> c = C(1) + +.. doctest:: + :hide: + + >>> import builtins + >>> builtins.__dict__['C'] = C + +.. Why does it look for C in builtins? + +As we can see, the ``pickle_c()`` function is called every time we pickle +a ``C`` instance: + +.. doctest:: + >>> d = copy.copy(c) pickling a C instance... >>> p = pickle.dumps(c) diff --git a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst --- a/Doc/library/ctypes.rst +++ b/Doc/library/ctypes.rst @@ -1408,6 +1408,10 @@ accessing it repeatedly returns the same object each time. On the other hand, accessing it through an index returns a new object each time: +.. doctest:: + + >>> from ctypes import CDLL + >>> libc = CDLL("libc.so.6") # On Linux >>> libc.time == libc.time True >>> libc['time'] == libc['time'] diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -1221,7 +1221,7 @@ >>> from datetime import datetime - >>> datetime.now().isoformat(timespec='minutes') + >>> datetime.now().isoformat(timespec='minutes') # doctest: +SKIP '2002-12-25T00:00' >>> dt = datetime(2015, 1, 1, 12, 30, 59, 0) >>> dt.isoformat(timespec='microseconds') @@ -1368,8 +1368,8 @@ .. _datetime-time: -:class:`.time` Objects ----------------------- +:class:`time` Objects +--------------------- A time object represents a (local) time of day, independent of any particular day, and subject to adjustment via a :class:`tzinfo` object. @@ -1466,7 +1466,7 @@ ``!=``. The latter cases return :const:`False` or :const:`True`, respectively. .. versionchanged:: 3.3 - Equality comparisons between naive and aware :class:`~datetime.time` instances + Equality comparisons between naive and aware :class:`time` instances don't raise :exc:`TypeError`. * hash, use as dict key @@ -1781,9 +1781,11 @@ else: return dt -Example :class:`tzinfo` classes: - -.. literalinclude:: ../includes/tzinfo-examples.py +In the following :download:`tzinfo_example.py +<../includes/tzinfo_examples.py>` file there are some examples of +:class:`tzinfo` classes: + +.. literalinclude:: ../includes/tzinfo_examples.py Note that there are unavoidable subtleties twice per year in a :class:`tzinfo` subclass accounting for both standard and daylight time, at the DST transition @@ -1802,8 +1804,12 @@ When DST starts (the "start" line), the local wall clock leaps from 1:59 to 3:00. A wall time of the form 2:MM doesn't really make sense on that day, so ``astimezone(Eastern)`` won't deliver a result with ``hour == 2`` on the day DST -begins. For example, at the Spring forward transition of 2016, we get - +begins. For example, at the Spring forward transition of 2016, we get: + +.. doctest:: astimezone + + >>> from datetime import datetime, timezone + >>> from tzinfo_examples import HOUR, Eastern >>> u0 = datetime(2016, 3, 13, 5, tzinfo=timezone.utc) >>> for i in range(4): ... u = u0 + i*HOUR @@ -1825,7 +1831,9 @@ hours into the same local hour then. In the Eastern example, UTC times of the form 5:MM and 6:MM both map to 1:MM when converted to Eastern, but earlier times have the :attr:`~datetime.fold` attribute set to 0 and the later times have it set to 1. -For example, at the Fall back transition of 2016, we get +For example, at the Fall back transition of 2016, we get: + +.. doctest:: astimezone >>> u0 = datetime(2016, 11, 6, 4, tzinfo=timezone.utc) >>> for i in range(4): diff --git a/Doc/library/email.compat32-message.rst b/Doc/library/email.compat32-message.rst --- a/Doc/library/email.compat32-message.rst +++ b/Doc/library/email.compat32-message.rst @@ -660,10 +660,10 @@ .. testsetup:: - >>> from email import message_from_binary_file - >>> with open('Lib/test/test_email/data/msg_16.txt', 'rb') as f: - ... msg = message_from_binary_file(f) - >>> from email.iterators import _structure + from email import message_from_binary_file + with open('../Lib/test/test_email/data/msg_16.txt', 'rb') as f: + msg = message_from_binary_file(f) + from email.iterators import _structure .. doctest:: @@ -686,7 +686,7 @@ .. doctest:: >>> for part in msg.walk(): - ... print(part.get_content_maintype() == 'multipart'), + ... print(part.get_content_maintype() == 'multipart', ... part.is_multipart()) True True False False @@ -698,11 +698,11 @@ >>> _structure(msg) multipart/report text/plain - message/delivery-status - text/plain - text/plain - message/rfc822 - text/plain + message/delivery-status + text/plain + text/plain + message/rfc822 + text/plain Here the ``message`` parts are not ``multiparts``, but they do contain subparts. ``is_multipart()`` returns ``True`` and ``walk`` descends diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -327,14 +327,17 @@ The resulting list is sorted alphabetically. For example: + .. doctest:: struct + :options: +NORMALIZE_WHITESPACE + >>> import struct - >>> dir() # show the names in the module namespace + >>> dir() # show the names in the module namespace # doctest: +SKIP ['__builtins__', '__name__', 'struct'] - >>> dir(struct) # show the names in the struct module # doctest: +SKIP - ['Struct', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', - '__initializing__', '__loader__', '__name__', '__package__', - '_clearcache', 'calcsize', 'error', 'pack', 'pack_into', - 'unpack', 'unpack_from'] + >>> dir(struct) # show the names in the struct module + ['Struct', '__all__', '__builtins__', '__cached__', '__doc__', + '__file__', '__loader__', '__name__', '__package__', '__spec__', + '_clearcache', 'calcsize', 'error', 'iter_unpack', 'pack', 'pack_into', + 'unpack', 'unpack_from'] >>> class Shape: ... def __dir__(self): ... return ['area', 'perimeter', 'location'] @@ -519,7 +522,7 @@ If no argument is given, ``0.0`` is returned. - Examples:: + Examples: >>> float('+1.23') 1.23 diff --git a/Doc/library/ipaddress.rst b/Doc/library/ipaddress.rst --- a/Doc/library/ipaddress.rst +++ b/Doc/library/ipaddress.rst @@ -25,9 +25,10 @@ .. versionadded:: 3.3 .. testsetup:: - >>> import ipaddress - >>> from ipaddress import (ip_network, IPv4Address, IPv4Interface, - ... IPv4Network) + + import ipaddress + from ipaddress import (ip_network, IPv4Address, IPv4Interface, + IPv4Network) Convenience factory functions ----------------------------- @@ -43,6 +44,7 @@ A :exc:`ValueError` is raised if *address* does not represent a valid IPv4 or IPv6 address. + >>> import ipaddress >>> ipaddress.ip_address('192.168.0.1') IPv4Address('192.168.0.1') >>> ipaddress.ip_address('2001:db8::') diff --git a/Doc/library/pathlib.rst b/Doc/library/pathlib.rst --- a/Doc/library/pathlib.rst +++ b/Doc/library/pathlib.rst @@ -43,46 +43,72 @@ :mod:`os.path` module. + Basic use --------- -Importing the main class:: +.. testsetup:: + + from pathlib import Path + import os + curdir_backup = os.getcwd() + os.chdir('includes/pathlib') + p_ = Path('setup.py') + p_.chmod(33277) + +.. testcleanup:: + + os.chdir(curdir_backup) + + +Importing the main class: + +.. doctest:: >>> from pathlib import Path -Listing subdirectories:: +Listing subdirectories: + +.. doctest:: >>> p = Path('.') >>> [x for x in p.iterdir() if x.is_dir()] - [PosixPath('.hg'), PosixPath('docs'), PosixPath('dist'), - PosixPath('__pycache__'), PosixPath('build')] + [PosixPath('docs'), PosixPath('build')] -Listing Python source files in this directory tree:: +Listing Python source files in this directory tree: - >>> list(p.glob('**/*.py')) - [PosixPath('test_pathlib.py'), PosixPath('setup.py'), - PosixPath('pathlib.py'), PosixPath('docs/conf.py'), +.. doctest:: + + >>> list(p.glob('**/*.py')) # doctest: +NORMALIZE_WHITESPACE + [PosixPath('test_pathlib.py'), PosixPath('pathlib.py'), + PosixPath('setup.py'), PosixPath('docs/conf.py'), PosixPath('build/lib/pathlib.py')] -Navigating inside a directory tree:: +Navigating inside a directory tree: + +.. doctest:: >>> p = Path('/etc') >>> q = p / 'init.d' / 'reboot' >>> q PosixPath('/etc/init.d/reboot') >>> q.resolve() - PosixPath('/etc/rc.d/init.d/halt') + PosixPath('/etc/init.d/reboot') -Querying path properties:: +Querying path properties: + +.. doctest:: >>> q.exists() True >>> q.is_dir() False -Opening a file:: +Opening a file: - >>> with q.open() as f: f.readline() +.. doctest:: + + >>> with q.open() as f: f.readline() # doctest: +SKIP ... '#!/bin/bash\n' @@ -99,28 +125,39 @@ .. class:: PurePath(*pathsegments) A generic class that represents the system's path flavour (instantiating - it creates either a :class:`PurePosixPath` or a :class:`PureWindowsPath`):: + it creates either a :class:`PurePosixPath` or a :class:`PureWindowsPath`): + .. doctest:: + + >>> from pathlib import PurePath >>> PurePath('setup.py') # Running on a Unix machine PurePosixPath('setup.py') Each element of *pathsegments* can be either a string representing a path segment, an object implementing the :class:`os.PathLike` interface - which returns a string, or another path object:: + which returns a string, or another path object: + .. doctest:: + + >>> from pathlib import Path >>> PurePath('foo', 'some/path', 'bar') PurePosixPath('foo/some/path/bar') >>> PurePath(Path('foo'), Path('bar')) PurePosixPath('foo/bar') - When *pathsegments* is empty, the current directory is assumed:: + When *pathsegments* is empty, the current directory is assumed: + + .. doctest:: >>> PurePath() PurePosixPath('.') When several absolute paths are given, the last is taken as an anchor - (mimicking :func:`os.path.join`'s behaviour):: + (mimicking :func:`os.path.join`'s behaviour): + .. doctest:: + + >>> from pathlib import PureWindowsPath >>> PurePath('/etc', '/usr', 'lib64') PurePosixPath('/usr/lib64') >>> PureWindowsPath('c:/Windows', 'd:bar') @@ -134,7 +171,9 @@ Spurious slashes and single dots are collapsed, but double dots (``'..'``) are not, since this would change the meaning of a path in the face of - symbolic links:: + symbolic links: + + .. doctest:: >>> PurePath('foo//bar') PurePosixPath('foo/bar') @@ -156,8 +195,11 @@ .. class:: PurePosixPath(*pathsegments) A subclass of :class:`PurePath`, this path flavour represents non-Windows - filesystem paths:: + filesystem paths: + .. doctest:: + + >>> from pathlib import PurePosixPath >>> PurePosixPath('/etc') PurePosixPath('/etc') @@ -166,7 +208,9 @@ .. class:: PureWindowsPath(*pathsegments) A subclass of :class:`PurePath`, this path flavour represents Windows - filesystem paths:: + filesystem paths: + + .. doctest:: >>> PureWindowsPath('c:/Program Files/') PureWindowsPath('c:/Program Files') @@ -182,7 +226,9 @@ Paths are immutable and hashable. Paths of a same flavour are comparable and orderable. These properties respect the flavour's case-folding -semantics:: +semantics: + +.. doctest:: >>> PurePosixPath('foo') == PurePosixPath('FOO') False @@ -193,7 +239,9 @@ >>> PureWindowsPath('C:') < PureWindowsPath('d:') True -Paths of a different flavour compare unequal and cannot be ordered:: +Paths of a different flavour compare unequal and cannot be ordered: + +.. doctest:: >>> PureWindowsPath('foo') == PurePosixPath('foo') False @@ -206,7 +254,9 @@ Operators ^^^^^^^^^ -The slash operator helps create child paths, similarly to :func:`os.path.join`:: +The slash operator helps create child paths, similarly to :func:`os.path.join`: + +.. doctest:: >>> p = PurePath('/etc') >>> p @@ -218,7 +268,9 @@ PurePosixPath('/usr/bin') A path object can be used anywhere an object implementing :class:`os.PathLike` -is accepted:: +is accepted: + +.. doctest:: >>> import os >>> p = PurePath('/etc') @@ -227,7 +279,9 @@ The string representation of a path is the raw filesystem path itself (in native form, e.g. with backslashes under Windows), which you can -pass to any function taking a file path as a string:: +pass to any function taking a file path as a string: + +.. doctest:: >>> p = PurePath('/etc') >>> str(p) @@ -237,10 +291,12 @@ 'c:\\Program Files' Similarly, calling :class:`bytes` on a path gives the raw filesystem path as a -bytes object, as encoded by :func:`os.fsencode`:: +bytes object, as encoded by :func:`os.fsencode`: + +.. doctest:: >>> bytes(p) - b'/etc' + b'c:\\Program Files' .. note:: Calling :class:`bytes` is only recommended under Unix. Under Windows, @@ -255,7 +311,9 @@ .. data:: PurePath.parts - A tuple giving access to the path's various components:: + A tuple giving access to the path's various components: + + .. doctest:: >>> p = PurePath('/usr/bin/python3') >>> p.parts @@ -275,7 +333,9 @@ .. data:: PurePath.drive - A string representing the drive letter or name, if any:: + A string representing the drive letter or name, if any: + + .. doctest:: >>> PureWindowsPath('c:/Program Files/').drive 'c:' @@ -284,14 +344,18 @@ >>> PurePosixPath('/etc').drive '' - UNC shares are also considered drives:: + UNC shares are also considered drives: + + .. doctest:: >>> PureWindowsPath('//host/share/foo.txt').drive '\\\\host\\share' .. data:: PurePath.root - A string representing the (local or global) root, if any:: + A string representing the (local or global) root, if any: + + .. doctest:: >>> PureWindowsPath('c:/Program Files/').root '\\' @@ -300,14 +364,18 @@ >>> PurePosixPath('/etc').root '/' - UNC shares always have a root:: + UNC shares always have a root: + + .. doctest:: >>> PureWindowsPath('//host/share').root '\\' .. data:: PurePath.anchor - The concatenation of the drive and root:: + The concatenation of the drive and root: + + .. doctest:: >>> PureWindowsPath('c:/Program Files/').anchor 'c:\\' @@ -322,7 +390,9 @@ .. data:: PurePath.parents An immutable sequence providing access to the logical ancestors of - the path:: + the path: + + .. doctest:: >>> p = PureWindowsPath('c:/foo/bar/setup.py') >>> p.parents[0] @@ -335,13 +405,17 @@ .. data:: PurePath.parent - The logical parent of the path:: + The logical parent of the path: + + .. doctest:: >>> p = PurePosixPath('/a/b/c/d') >>> p.parent PurePosixPath('/a/b/c') - You cannot go past an anchor, or empty path:: + You cannot go past an anchor, or empty path: + + .. doctest:: >>> p = PurePosixPath('/') >>> p.parent @@ -351,7 +425,9 @@ PurePosixPath('.') .. note:: - This is a purely lexical operation, hence the following behaviour:: + This is a purely lexical operation, hence the following behaviour: + + .. doctest:: >>> p = PurePosixPath('foo/..') >>> p.parent @@ -365,12 +441,16 @@ .. data:: PurePath.name A string representing the final path component, excluding the drive and - root, if any:: + root, if any: + + .. doctest:: >>> PurePosixPath('my/library/setup.py').name 'setup.py' - UNC drive names are not considered:: + UNC drive names are not considered: + + .. doctest:: >>> PureWindowsPath('//some/share/setup.py').name 'setup.py' @@ -380,7 +460,9 @@ .. data:: PurePath.suffix - The file extension of the final component, if any:: + The file extension of the final component, if any: + + .. doctest:: >>> PurePosixPath('my/library/setup.py').suffix '.py' @@ -392,7 +474,9 @@ .. data:: PurePath.suffixes - A list of the path's file extensions:: + A list of the path's file extensions: + + .. doctest:: >>> PurePosixPath('my/library.tar.gar').suffixes ['.tar', '.gar'] @@ -404,7 +488,9 @@ .. data:: PurePath.stem - The final path component, without its suffix:: + The final path component, without its suffix: + + .. doctest:: >>> PurePosixPath('my/library.tar.gz').stem 'library.tar' @@ -416,7 +502,9 @@ .. method:: PurePath.as_posix() - Return a string representation of the path with forward slashes (``/``):: + Return a string representation of the path with forward slashes (``/``): + + .. doctest:: >>> p = PureWindowsPath('c:\\windows') >>> str(p) @@ -430,6 +518,9 @@ Represent the path as a ``file`` URI. :exc:`ValueError` is raised if the path isn't absolute. + .. doctest:: + + >>> from pathlib import PurePosixPath, PureWindowsPath >>> p = PurePosixPath('/etc/passwd') >>> p.as_uri() 'file:///etc/passwd' @@ -441,7 +532,9 @@ .. method:: PurePath.is_absolute() Return whether the path is absolute or not. A path is considered absolute - if it has both a root and (if the flavour allows) a drive:: + if it has both a root and (if the flavour allows) a drive: + + .. doctest:: >>> PurePosixPath('/a/b').is_absolute() True @@ -464,6 +557,8 @@ reserved under Windows, ``False`` otherwise. With :class:`PurePosixPath`, ``False`` is always returned. + .. doctest:: + >>> PureWindowsPath('nul').is_reserved() True >>> PurePosixPath('nul').is_reserved() @@ -476,7 +571,9 @@ .. method:: PurePath.joinpath(*other) Calling this method is equivalent to combining the path with each of - the *other* arguments in turn:: + the *other* arguments in turn: + + .. doctest:: >>> PurePosixPath('/etc').joinpath('passwd') PurePosixPath('/etc/passwd') @@ -494,7 +591,9 @@ if matching is successful, ``False`` otherwise. If *pattern* is relative, the path can be either relative or absolute, - and matching is done from the right:: + and matching is done from the right: + + .. doctest:: >>> PurePath('a/b.py').match('*.py') True @@ -504,14 +603,18 @@ False If *pattern* is absolute, the path must be absolute, and the whole path - must match:: + must match: + + .. doctest:: >>> PurePath('/a.py').match('/*.py') True >>> PurePath('a/b.py').match('/*.py') False - As with other methods, case-sensitivity is observed:: + As with other methods, case-sensitivity is observed: + + .. doctest:: >>> PureWindowsPath('b.py').match('*.PY') True @@ -520,7 +623,9 @@ .. method:: PurePath.relative_to(*other) Compute a version of this path relative to the path represented by - *other*. If it's impossible, ValueError is raised:: + *other*. If it's impossible, ValueError is raised: + + .. doctest:: >>> p = PurePosixPath('/etc/passwd') >>> p.relative_to('/') @@ -529,16 +634,16 @@ PurePosixPath('passwd') >>> p.relative_to('/usr') Traceback (most recent call last): - File "", line 1, in - File "pathlib.py", line 694, in relative_to - .format(str(self), str(formatted))) + ... ValueError: '/etc/passwd' does not start with '/usr' .. method:: PurePath.with_name(name) Return a new path with the :attr:`name` changed. If the original path - doesn't have a name, ValueError is raised:: + doesn't have a name, ValueError is raised: + + .. doctest:: >>> p = PureWindowsPath('c:/Downloads/pathlib.tar.gz') >>> p.with_name('setup.py') @@ -546,16 +651,16 @@ >>> p = PureWindowsPath('c:/') >>> p.with_name('setup.py') Traceback (most recent call last): - File "", line 1, in - File "/home/antoine/cpython/default/Lib/pathlib.py", line 751, in with_name - raise ValueError("%r has an empty name" % (self,)) + ... ValueError: PureWindowsPath('c:/') has an empty name .. method:: PurePath.with_suffix(suffix) Return a new path with the :attr:`suffix` changed. If the original path - doesn't have a suffix, the new *suffix* is appended instead:: + doesn't have a suffix, the new *suffix* is appended instead: + + .. doctest:: >>> p = PureWindowsPath('c:/Downloads/pathlib.tar.gz') >>> p.with_suffix('.bz2') @@ -579,7 +684,9 @@ A subclass of :class:`PurePath`, this class represents concrete paths of the system's path flavour (instantiating it creates either a - :class:`PosixPath` or a :class:`WindowsPath`):: + :class:`PosixPath` or a :class:`WindowsPath`): + + .. doctest:: >>> Path('setup.py') PosixPath('setup.py') @@ -589,8 +696,11 @@ .. class:: PosixPath(*pathsegments) A subclass of :class:`Path` and :class:`PurePosixPath`, this class - represents concrete non-Windows filesystem paths:: + represents concrete non-Windows filesystem paths: + .. doctest:: + + >>> from pathlib import PosixPath >>> PosixPath('/etc') PosixPath('/etc') @@ -599,16 +709,21 @@ .. class:: WindowsPath(*pathsegments) A subclass of :class:`Path` and :class:`PureWindowsPath`, this class - represents concrete Windows filesystem paths:: + represents concrete Windows filesystem paths: - >>> WindowsPath('c:/Program Files/') + .. doctest:: + + >>> from pathlib import WindowsPath + >>> WindowsPath('c:/Program Files/') # doctest: +SKIP WindowsPath('c:/Program Files') *pathsegments* is specified similarly to :class:`PurePath`. You can only instantiate the class flavour that corresponds to your system (allowing system calls on non-compatible path flavours could lead to -bugs or failures in your application):: +bugs or failures in your application): + +.. doctest:: >>> import os >>> os.name @@ -619,9 +734,7 @@ PosixPath('setup.py') >>> WindowsPath('setup.py') Traceback (most recent call last): - File "", line 1, in - File "pathlib.py", line 798, in __new__ - % (cls.__name__,)) + ... NotImplementedError: cannot instantiate 'WindowsPath' on your system @@ -635,18 +748,33 @@ .. classmethod:: Path.cwd() Return a new path object representing the current directory (as returned - by :func:`os.getcwd`):: + by :func:`os.getcwd`): + + .. testsetup:: cwd + + from pathlib import Path + import os + curdir_backup = os.getcwd() + os.chdir('/home') + + .. testcleanup:: cwd + + os.chdir(curdir_backup) + + .. doctest:: cwd >>> Path.cwd() - PosixPath('/home/antoine/pathlib') + PosixPath('/home') .. classmethod:: Path.home() Return a new path object representing the user's home directory (as - returned by :func:`os.path.expanduser` with ``~`` construct):: + returned by :func:`os.path.expanduser` with ``~`` construct): - >>> Path.home() + .. doctest:: + + >>> Path.home() # doctest: +SKIP PosixPath('/home/antoine') .. versionadded:: 3.5 @@ -657,16 +785,20 @@ Return information about this path (similarly to :func:`os.stat`). The result is looked up at each call to this method. + .. doctest:: + >>> p = Path('setup.py') >>> p.stat().st_size - 956 - >>> p.stat().st_mtime + 21 + >>> p.stat().st_mtime # doctest: +SKIP 1327883547.852554 .. method:: Path.chmod(mode) - Change the file mode and permissions, like :func:`os.chmod`:: + Change the file mode and permissions, like :func:`os.chmod`: + + .. doctest:: >>> p = Path('setup.py') >>> p.stat().st_mode @@ -678,7 +810,9 @@ .. method:: Path.exists() - Whether the path points to an existing file or directory:: + Whether the path points to an existing file or directory: + + .. doctest:: >>> Path('.').exists() True @@ -697,10 +831,12 @@ .. method:: Path.expanduser() Return a new path with expanded ``~`` and ``~user`` constructs, - as returned by :meth:`os.path.expanduser`:: + as returned by :meth:`os.path.expanduser`: + + .. doctest:: >>> p = PosixPath('~/films/Monty Python') - >>> p.expanduser() + >>> p.expanduser() # doctest: +SKIP PosixPath('/home/eric/films/Monty Python') .. versionadded:: 3.5 @@ -709,7 +845,9 @@ .. method:: Path.glob(pattern) Glob the given *pattern* in the directory represented by this path, - yielding all matching files (of any kind):: + yielding all matching files (of any kind): + + .. doctest:: >>> sorted(Path('.').glob('*.py')) [PosixPath('pathlib.py'), PosixPath('setup.py'), PosixPath('test_pathlib.py')] @@ -717,9 +855,11 @@ [PosixPath('docs/conf.py')] The "``**``" pattern means "this directory and all subdirectories, - recursively". In other words, it enables recursive globbing:: + recursively". In other words, it enables recursive globbing: - >>> sorted(Path('.').glob('**/*.py')) + .. doctest:: + + >>> sorted(Path('.').glob('**/*.py')) # doctest: +NORMALIZE_WHITESPACE [PosixPath('build/lib/pathlib.py'), PosixPath('docs/conf.py'), PosixPath('pathlib.py'), @@ -802,18 +942,14 @@ .. method:: Path.iterdir() When the path points to a directory, yield path objects of the directory - contents:: + contents: + + .. doctest:: >>> p = Path('docs') >>> for child in p.iterdir(): child ... PosixPath('docs/conf.py') - PosixPath('docs/_templates') - PosixPath('docs/make.bat') - PosixPath('docs/index.rst') - PosixPath('docs/_build') - PosixPath('docs/_static') - PosixPath('docs/Makefile') .. method:: Path.lchmod(mode) @@ -855,13 +991,15 @@ .. method:: Path.open(mode='r', buffering=-1, encoding=None, errors=None, newline=None) Open the file pointed to by the path, like the built-in :func:`open` - function does:: + function does: + + .. doctest:: >>> p = Path('setup.py') >>> with p.open() as f: ... f.readline() ... - '#!/usr/bin/env python3\n' + '# A dummy setup file\n' .. method:: Path.owner() @@ -872,7 +1010,9 @@ .. method:: Path.read_bytes() - Return the binary contents of the pointed-to file as a bytes object:: + Return the binary contents of the pointed-to file as a bytes object: + + .. doctest:: >>> p = Path('my_binary_file') >>> p.write_bytes(b'Binary file contents') @@ -885,7 +1025,9 @@ .. method:: Path.read_text(encoding=None, errors=None) - Return the decoded contents of the pointed-to file as a string:: + Return the decoded contents of the pointed-to file as a string: + + .. doctest:: >>> p = Path('my_text_file') >>> p.write_text('Text file contents') @@ -902,7 +1044,9 @@ Rename this file or directory to the given *target*. On Unix, if *target* exists and is a file, it will be replaced silently if the user - has permission. *target* can be either a string or another path object:: + has permission. *target* can be either a string or another path object: + + .. doctest:: >>> p = Path('foo') >>> p.open('w').write('some text') @@ -922,18 +1066,22 @@ .. method:: Path.resolve(strict=False) Make the path absolute, resolving any symlinks. A new path object is - returned:: + returned: + + .. doctest:: >>> p = Path() >>> p PosixPath('.') - >>> p.resolve() + >>> p.resolve() # doctest: +SKIP PosixPath('/home/antoine/pathlib') - "``..``" components are also eliminated (this is the only method to do so):: + "``..``" components are also eliminated (this is the only method to do so): + + .. doctest:: >>> p = Path('docs/../setup.py') - >>> p.resolve() + >>> p.resolve() # doctest: +SKIP PosixPath('/home/antoine/pathlib/setup.py') If the path doesn't exist and *strict* is ``True``, :exc:`FileNotFoundError` @@ -950,7 +1098,9 @@ This is like calling :meth:`Path.glob` with "``**``" added in front of the given *pattern*: - >>> sorted(Path().rglob("*.py")) + .. doctest:: + + >>> sorted(Path().rglob("*.py")) # doctest: +NORMALIZE_WHITESPACE [PosixPath('build/lib/pathlib.py'), PosixPath('docs/conf.py'), PosixPath('pathlib.py'), @@ -972,6 +1122,8 @@ An :exc:`OSError` can be raised if either file cannot be accessed for some reason. + .. doctest:: + >>> p = Path('spam') >>> q = Path('eggs') >>> p.samefile(q) @@ -988,12 +1140,26 @@ *target_is_directory* must be true (default ``False``) if the link's target is a directory. Under POSIX, *target_is_directory*'s value is ignored. +.. testsetup:: symlink + + from pathlib import Path + import os + curdir_backup = os.getcwd() + os.chdir('includes/pathlib') + +.. testcleanup:: symlink + + os.remove('mylink') + os.chdir(curdir_backup) + +.. doctest:: symlink + >>> p = Path('mylink') >>> p.symlink_to('setup.py') - >>> p.resolve() + >>> p.resolve() # doctest: +SKIP PosixPath('/home/antoine/pathlib/setup.py') >>> p.stat().st_size - 956 + 21 >>> p.lstat().st_size 8 @@ -1020,7 +1186,9 @@ .. method:: Path.write_bytes(data) Open the file pointed to in bytes mode, write *data* to it, and close the - file:: + file: + + .. doctest:: >>> p = Path('my_binary_file') >>> p.write_bytes(b'Binary file contents') @@ -1036,7 +1204,9 @@ .. method:: Path.write_text(data, encoding=None, errors=None) Open the file pointed to in text mode, write *data* to it, and close the - file:: + file: + + .. doctest:: >>> p = Path('my_text_file') >>> p.write_text('Text file contents') diff --git a/Doc/library/reprlib.rst b/Doc/library/reprlib.rst --- a/Doc/library/reprlib.rst +++ b/Doc/library/reprlib.rst @@ -48,6 +48,7 @@ same thread. If a recursive call is made, the *fillvalue* is returned, otherwise, the usual :meth:`__repr__` call is made. For example: + >>> from reprlib import recursive_repr >>> class MyList(list): ... @recursive_repr() ... def __repr__(self): diff --git a/Doc/library/shlex.rst b/Doc/library/shlex.rst --- a/Doc/library/shlex.rst +++ b/Doc/library/shlex.rst @@ -43,15 +43,20 @@ string that can safely be used as one token in a shell command line, for cases where you cannot use a list. - This idiom would be unsafe:: + This idiom would be unsafe: + + .. doctest:: >>> filename = 'somefile; rm -rf ~' >>> command = 'ls -l {}'.format(filename) >>> print(command) # executed by a shell: boom! ls -l somefile; rm -rf ~ - :func:`quote` lets you plug the security hole:: + :func:`quote` lets you plug the security hole: + .. doctest:: + + >>> from shlex import quote >>> command = 'ls -l {}'.format(quote(filename)) >>> print(command) ls -l 'somefile; rm -rf ~' @@ -61,6 +66,9 @@ The quoting is compatible with UNIX shells and with :func:`split`: + .. doctest:: + + >>> from shlex import split >>> remote_command = split(remote_command) >>> remote_command ['ssh', 'home', "ls -l 'somefile; rm -rf ~'"] @@ -397,7 +405,7 @@ Instead of passing ``True`` as the value for the punctuation_chars parameter, you can pass a string with specific characters, which will be used to determine -which characters constitute punctuation. For example:: +which characters constitute punctuation. For example: >>> import shlex >>> s = shlex.shlex("a && b || c", punctuation_chars="|") @@ -407,7 +415,7 @@ .. note:: When ``punctuation_chars`` is specified, the :attr:`~shlex.wordchars` attribute is augmented with the characters ``~-./*?=``. That is because these characters can appear in file names (including wildcards) and command-line - arguments (e.g. ``--color=auto``). Hence:: + arguments (e.g. ``--color=auto``). Hence: >>> import shlex >>> s = shlex.shlex('~/a && b-c --color=auto || d *.py?', diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -215,7 +215,7 @@ The *ciphers* parameter sets the available ciphers for this SSL object. It should be a string in the `OpenSSL cipher list format - `_. + `_. The parameter ``do_handshake_on_connect`` specifies whether to do the SSL handshake automatically after doing a :meth:`socket.connect`, or whether the @@ -379,14 +379,16 @@ SSL-based protocols such as FTPS, IMAPS, POPS and others. :exc:`CertificateError` is raised on failure. On success, the function - returns nothing:: - + returns nothing: + + .. doctest:: + + >>> import ssl >>> cert = {'subject': ((('commonName', 'example.com'),),)} >>> ssl.match_hostname(cert, "example.com") >>> ssl.match_hostname(cert, "example.org") Traceback (most recent call last): - File "", line 1, in - File "/home/py3k/Lib/ssl.py", line 130, in match_hostname + ... ssl.CertificateError: hostname 'example.org' doesn't match 'example.com' .. versionadded:: 3.2 @@ -1360,8 +1362,8 @@ Example:: >>> ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23) - >>> ctx.set_ciphers('ECDHE+AESGCM:!ECDSA') - >>> ctx.get_ciphers() # OpenSSL 1.0.x + >>> ctx.set_ciphers('ECDHE+AESGCM:!ECDSA') # doctest: +SKIP + >>> ctx.get_ciphers() # OpenSSL 1.0.x # doctest: +SKIP [{'alg_bits': 256, 'description': 'ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=RSA ' 'Enc=AESGCM(256) Mac=AEAD', @@ -1378,6 +1380,7 @@ 'strength_bits': 128}] On OpenSSL 1.1 and newer the cipher dict contains additional fields:: + >>> ctx.get_ciphers() # OpenSSL 1.1+ [{'aead': True, 'alg_bits': 256, @@ -1420,8 +1423,7 @@ .. method:: SSLContext.set_ciphers(ciphers) Set the available ciphers for sockets created with this context. - It should be a string in the `OpenSSL cipher list format - `_. + It should be a string in the `OpenSSL cipher list format`_. If no cipher can be selected (because compile-time options or other configuration forbids use of all the specified ciphers), an :class:`SSLError` will be raised. @@ -1638,7 +1640,7 @@ .. versionchanged:: 3.6 :attr:`SSLContext.options` returns :class:`Options` flags: - >>> ssl.create_default_context().options + >>> ssl.create_default_context().options # doctest: +SKIP .. attribute:: SSLContext.protocol @@ -1658,7 +1660,7 @@ .. versionchanged:: 3.6 :attr:`SSLContext.verify_flags` returns :class:`VerifyFlags` flags: - >>> ssl.create_default_context().verify_flags + >>> ssl.create_default_context().verify_flags # doctest: +SKIP .. attribute:: SSLContext.verify_mode diff --git a/Doc/library/statistics.rst b/Doc/library/statistics.rst --- a/Doc/library/statistics.rst +++ b/Doc/library/statistics.rst @@ -15,6 +15,9 @@ from statistics import * __name__ = '' + from decimal import setcontext, Context + setcontext(Context()) # In case external tests changed the context + -------------- diff --git a/Doc/library/turtle.rst b/Doc/library/turtle.rst --- a/Doc/library/turtle.rst +++ b/Doc/library/turtle.rst @@ -939,7 +939,7 @@ >>> col = turtle.pencolor() >>> col (50.0, 193.0, 143.0) - >>> turtle.fillcolor(col) + >>> turtle.fillcolor((50, 193, 143)) # Integers, not floats >>> turtle.fillcolor() (50.0, 193.0, 143.0) >>> turtle.fillcolor('#ffffff') diff --git a/Doc/library/unittest.mock-examples.rst b/Doc/library/unittest.mock-examples.rst --- a/Doc/library/unittest.mock-examples.rst +++ b/Doc/library/unittest.mock-examples.rst @@ -6,6 +6,21 @@ .. versionadded:: 3.3 +.. testsetup:: + + from unittest_mock import package, mymodule + # The examples require ``mymodule`` to have the following attributes + for attr in ['Class1', 'Class2', 'Foo', 'Bar', 'Spam', 'SomeClass', 'date']: + setattr(mymodule, attr, None) + + # This allows us to import mymodule as ``import mymodule`` + import sys + sys.modules['mymodule'] = mymodule + sys.modules['package'] = package + + class SomeClass: + attribute = None + .. _getting-started: @@ -23,6 +38,9 @@ You might want to replace a method on an object to check that it is called with the correct arguments by another part of the system: +.. doctest:: + + >>> from unittest.mock import MagicMock >>> real = SomeClass() >>> real.method = MagicMock(name='method') >>> real.method(3, 4, 5, key='value') @@ -45,6 +63,8 @@ This example tests that calling ``ProductionClass().method`` results in a call to the ``something`` method: +.. doctest:: + >>> class ProductionClass: ... def method(self): ... self.something(1, 2, 3) @@ -69,6 +89,8 @@ The simple ``ProductionClass`` below has a ``closer`` method. If it is called with an object then it calls ``close`` on it. +.. doctest:: + >>> class ProductionClass: ... def closer(self, something): ... something.close() @@ -77,6 +99,9 @@ So to test it we need to pass in an object with a ``close`` method and check that it was called correctly. +.. doctest:: + + >>> from unittest.mock import Mock >>> real = ProductionClass() >>> mock = Mock() >>> real.closer(mock) @@ -101,11 +126,14 @@ mock. The ``Foo`` instance is the result of calling the mock, so it is configured by modifying the mock :attr:`~Mock.return_value`. +.. doctest:: + >>> def some_function(): - ... instance = module.Foo() + ... instance = mymodule.Foo() ... return instance.method() ... - >>> with patch('module.Foo') as mock: + >>> from unittest.mock import patch + >>> with patch('mymodule.Foo') as mock: ... instance = mock.return_value ... instance.method.return_value = 'the result' ... result = some_function() @@ -119,6 +147,8 @@ the mock and can be helpful when the mock appears in test failure messages. The name is also propagated to attributes or methods of the mock: +.. doctest:: + >>> mock = MagicMock(name='foo') >>> mock @@ -133,6 +163,8 @@ :attr:`~Mock.mock_calls` attribute records all calls to child attributes of the mock - and also to their children. +.. doctest:: + >>> mock = MagicMock() >>> mock.method() @@ -149,6 +181,9 @@ You use the :data:`call` object to construct lists for comparing with ``mock_calls``: +.. doctest:: + + >>> from unittest.mock import call >>> expected = [call.method(), call.attribute.method(10, x=53)] >>> mock.mock_calls == expected True @@ -159,6 +194,8 @@ Setting the return values on a mock object is trivially easy: +.. doctest:: + >>> mock = Mock() >>> mock.return_value = 3 >>> mock() @@ -166,6 +203,8 @@ Of course you can do the same for methods on the mock: +.. doctest:: + >>> mock = Mock() >>> mock.method.return_value = 3 >>> mock.method() @@ -173,12 +212,16 @@ The return value can also be set in the constructor: +.. doctest:: + >>> mock = Mock(return_value=3) >>> mock() 3 If you need an attribute setting on your mock, just do it: +.. doctest:: + >>> mock = Mock() >>> mock.x = 3 >>> mock.x @@ -191,11 +234,14 @@ We can use :data:`call` to construct the set of calls in a "chained call" like this for easy assertion afterwards: +.. doctest:: + >>> mock = Mock() >>> cursor = mock.connection.cursor.return_value >>> cursor.execute.return_value = ['foo'] >>> mock.connection.cursor().execute("SELECT 1") ['foo'] + >>> from unittest.mock import call >>> expected = call.connection.cursor().execute("SELECT 1").call_list() >>> mock.mock_calls [call.connection.cursor(), call.connection.cursor().execute('SELECT 1')] @@ -213,6 +259,8 @@ exception class or instance then the exception will be raised when the mock is called. +.. doctest:: + >>> mock = Mock(side_effect=Exception('Boom!')) >>> mock() Traceback (most recent call last): @@ -229,6 +277,8 @@ ``side_effect`` to an iterable every call to the mock returns the next value from the iterable: +.. doctest:: + >>> mock = MagicMock(side_effect=[4, 5, 6]) >>> mock() 4 @@ -243,6 +293,8 @@ The function will be called with the same arguments as the mock. Whatever the function returns is what the call returns: +.. doctest:: + >>> vals = {(1, 2): 1, (2, 3): 2} >>> def side_effect(*args): ... return vals[args] @@ -271,6 +323,8 @@ tests that use that class will start failing immediately without you having to instantiate the class in those tests. +.. doctest:: + >>> mock = Mock(spec=SomeClass) >>> mock.old_method() Traceback (most recent call last): @@ -279,13 +333,15 @@ Using a specification also enables a smarter matching of calls made to the mock, regardless of whether some parameters were passed as positional or -named arguments:: +named arguments: + +.. doctest:: >>> def f(a, b, c): pass ... >>> mock = Mock(spec=f) >>> mock(1, 2, 3) - + >>> mock.assert_called_with(a=1, b=2, c=3) If you want this smarter matching to also work with method calls on the mock, @@ -323,6 +379,9 @@ ``patch.object``: +.. doctest:: + + >>> from unittest.mock import sentinel >>> original = SomeClass.attribute >>> @patch.object(SomeClass, 'attribute', sentinel.attribute) ... def test(): @@ -341,6 +400,8 @@ If you are patching a module (including :mod:`builtins`) then use :func:`patch` instead of :func:`patch.object`: +.. doctest:: + >>> mock = MagicMock(return_value=sentinel.file_handle) >>> with patch('builtins.open', mock): ... handle = open('filename', 'r') @@ -350,6 +411,8 @@ The module name can be 'dotted', in the form ``package.module`` if needed: +.. doctest:: + >>> @patch('package.module.ClassName.attribute', sentinel.attribute) ... def test(): ... from package.module import ClassName @@ -359,6 +422,9 @@ A nice pattern is to actually decorate test methods themselves: +.. doctest:: + + >>> import unittest >>> class MyTest(unittest.TestCase): ... @patch.object(SomeClass, 'attribute', sentinel.attribute) ... def test_something(self): @@ -372,6 +438,12 @@ (or :func:`patch.object` with two arguments). The mock will be created for you and passed into the test function / method: +.. doctest:: + + >>> class SomeClass: + ... def static_method(): + ... pass + ... >>> class MyTest(unittest.TestCase): ... @patch.object(SomeClass, 'static_method') ... def test_something(self, mock_method): @@ -382,6 +454,8 @@ You can stack up multiple patch decorators using this pattern: +.. doctest:: + >>> class MyTest(unittest.TestCase): ... @patch('package.module.ClassName1') ... @patch('package.module.ClassName2') @@ -400,6 +474,8 @@ during a scope and restoring the dictionary to its original state when the test ends: +.. doctest:: + >>> foo = {'key': 'value'} >>> original = foo.copy() >>> with patch.dict(foo, {'newkey': 'newvalue'}, clear=True): @@ -412,6 +488,8 @@ Where you use :func:`patch` to create a mock for you, you can get a reference to the mock using the "as" form of the with statement: +.. doctest:: + >>> class ProductionClass: ... def method(self): ... pass @@ -449,6 +527,8 @@ This means that you can see how the object returned from a call to a mocked object has been used by interrogating the ``return_value`` mock: +.. doctest:: + >>> mock = Mock() >>> mock().foo(a=2, b=3) @@ -460,6 +540,18 @@ So, suppose we have some code that looks a little bit like this: +.. testsetup:: backend_provider + + class BackendProvider: + def get_endpoint(self, par): + class Endpoint: + def create_call(self, par1, par2): + class Call: + def start_call(self): + ... + +.. doctest:: backend_provider + >>> class Something: ... def __init__(self): ... self.backend = BackendProvider() @@ -487,6 +579,9 @@ We can do that in a slightly nicer way using the :meth:`~Mock.configure_mock` method to directly set the return value for us: +.. doctest:: backend_provider + + >>> from unittest.mock import Mock >>> something = Something() >>> mock_response = Mock(spec=open) >>> mock_backend = Mock() @@ -496,6 +591,8 @@ With these we monkey patch the "mock backend" in place and can make the real call: +.. doctest:: backend_provider + >>> something.backend = mock_backend >>> something.method() @@ -504,6 +601,9 @@ several entries in ``mock_calls``. We can use :meth:`call.call_list` to create this list of calls for us: +.. doctest:: backend_provider + + >>> from unittest.mock import call >>> chained = call.get_endpoint('foobar').create_call('spam', 'eggs').start_call() >>> call_list = chained.call_list() >>> assert mock_backend.mock_calls == call_list @@ -527,6 +627,8 @@ a real date. When the mock date class is called a real date will be constructed and returned by ``side_effect``. +.. doctest:: + >>> from datetime import date >>> with patch('mymodule.date') as mock_date: ... mock_date.today.return_value = date(2010, 10, 8) @@ -565,6 +667,8 @@ Here's an example class with an "iter" method implemented as a generator: +.. doctest:: + >>> class Foo: ... def iter(self): ... for i in [1, 2, 3]: @@ -580,6 +684,8 @@ To configure the values returned from the iteration (implicit in the call to :class:`list`), we need to configure the object returned by the call to ``foo.iter()``. +.. doctest:: + >>> mock_foo = MagicMock() >>> mock_foo.iter.return_value = iter([1, 2, 3]) >>> list(mock_foo.iter()) @@ -602,8 +708,11 @@ methods on the class. A test method is identified by methods whose names start with ``test``: +.. doctest:: + + >>> import mymodule >>> @patch('mymodule.SomeClass') - ... class MyTest(TestCase): + ... class MyTest(unittest.TestCase): ... ... def test_one(self, MockSomeClass): ... self.assertIs(mymodule.SomeClass, MockSomeClass) @@ -622,7 +731,9 @@ An alternative way of managing patches is to use the :ref:`start-and-stop`. These allow you to move the patching into your ``setUp`` and ``tearDown`` methods. - >>> class MyTest(TestCase): +.. doctest:: + + >>> class MyTest(unittest.TestCase): ... def setUp(self): ... self.patcher = patch('mymodule.foo') ... self.mock_foo = self.patcher.start() @@ -634,13 +745,16 @@ ... self.patcher.stop() ... >>> MyTest('test_foo').run() + If you use this technique you must ensure that the patching is "undone" by calling ``stop``. This can be fiddlier than you might think, because if an exception is raised in the setUp then tearDown is not called. :meth:`unittest.TestCase.addCleanup` makes this easier: - >>> class MyTest(TestCase): +.. doctest:: + + >>> class MyTest(unittest.TestCase): ... def setUp(self): ... patcher = patch('mymodule.foo') ... self.addCleanup(patcher.stop) @@ -650,6 +764,7 @@ ... self.assertIs(mymodule.foo, self.mock_foo) ... >>> MyTest('test_foo').run() + Mocking Unbound Methods @@ -675,6 +790,8 @@ It will have ``self`` passed in as the first argument, which is exactly what I wanted: +.. doctest:: + >>> class Foo: ... def foo(self): ... pass @@ -696,6 +813,8 @@ mock has a nice API for making assertions about how your mock objects are used. +.. doctest:: + >>> mock = Mock() >>> mock.foo_bar.return_value = None >>> mock.foo_bar('baz', spam='eggs') @@ -705,6 +824,8 @@ :meth:`assert_called_once_with` method that also asserts that the :attr:`call_count` is one. +.. doctest:: + >>> mock.foo_bar.assert_called_once_with('baz', spam='eggs') >>> mock.foo_bar() >>> mock.foo_bar.assert_called_once_with('baz', spam='eggs') @@ -717,6 +838,8 @@ you want to make assertions about *all* those calls you can use :attr:`~Mock.call_args_list`: +.. doctest:: + >>> mock = Mock(return_value=None) >>> mock(1, 2, 3) >>> mock(4, 5, 6) @@ -728,6 +851,8 @@ can build up a list of expected calls and compare it to ``call_args_list``. This looks remarkably similar to the repr of the ``call_args_list``: +.. doctest:: + >>> expected = [call(1, 2, 3), call(4, 5, 6), call()] >>> mock.call_args_list == expected True @@ -742,19 +867,16 @@ longer make assertions about what the values were when the mock was called. Here's some example code that shows the problem. Imagine the following functions -defined in 'mymodule':: +defined in :download:`mymodule.py <../includes/unittest_mock/mymodule.py>`: - def frob(val): - pass - - def grob(val): - "First frob and then clear val" - frob(val) - val.clear() +.. literalinclude:: ../includes/unittest_mock/mymodule.py When we try to test that ``grob`` calls ``frob`` with the correct argument look what happens: +.. doctest:: + + >>> import mymodule >>> with patch('mymodule.frob') as mock_frob: ... val = {6} ... mymodule.grob(val) @@ -779,6 +901,8 @@ mock methods for doing the assertion. Again a helper function sets this up for me. +.. doctest:: + >>> from copy import deepcopy >>> from unittest.mock import Mock, patch, DEFAULT >>> def copy_call_args(mock): @@ -797,7 +921,7 @@ ... mymodule.grob(val) ... >>> new_mock.assert_called_with({6}) - >>> new_mock.call_args + >>> new_mock.call_args call({6}) ``copy_call_args`` is called with the mock that will be called. It returns a new @@ -810,6 +934,8 @@ checking arguments at the point they are called. You can simply do the checking inside a ``side_effect`` function. + .. doctest:: + >>> def side_effect(arg): ... assert arg == {6} ... @@ -824,6 +950,8 @@ :class:`MagicMock` that copies (using :func:`copy.deepcopy`) the arguments. Here's an example implementation: +.. doctest:: + >>> from copy import deepcopy >>> class CopyingMock(MagicMock): ... def __call__(self, *args, **kwargs): @@ -856,7 +984,9 @@ can end up with nested with statements indenting further and further to the right: - >>> class MyTest(TestCase): +.. doctest:: + + >>> class MyTest(unittest.TestCase): ... ... def test_foo(self): ... with patch('mymodule.Foo') as mock_foo: @@ -875,7 +1005,9 @@ method, ``create_patch``, puts the patch in place and returns the created mock for us: - >>> class MyTest(TestCase): +.. doctest:: + + >>> class MyTest(unittest.TestCase): ... ... def create_patch(self, name): ... patcher = patch(name) @@ -894,6 +1026,7 @@ ... >>> original = mymodule.Foo >>> MyTest('test_foo').run() + >>> assert mymodule.Foo is original @@ -914,6 +1047,8 @@ After the ``MagicMock`` has been used we can use attributes like :data:`~Mock.call_args_list` to assert about how the dictionary was used: +.. doctest:: + >>> my_dict = {'a': 1, 'b': 2, 'c': 3} >>> def getitem(name): ... return my_dict[name] @@ -930,6 +1065,8 @@ An alternative to using ``MagicMock`` is to use ``Mock`` and *only* provide the magic methods you specifically want: + .. doctest:: + >>> mock = Mock() >>> mock.__getitem__ = Mock(side_effect=getitem) >>> mock.__setitem__ = Mock(side_effect=setitem) @@ -938,6 +1075,8 @@ (or *spec_set*) argument so that the ``MagicMock`` created only has dictionary magic methods available: + .. doctest:: + >>> mock = MagicMock(spec_set=dict) >>> mock.__getitem__.side_effect = getitem >>> mock.__setitem__.side_effect = setitem @@ -946,6 +1085,8 @@ dictionary but recording the access. It even raises a :exc:`KeyError` if you try to access a key that doesn't exist. +.. doctest:: + >>> mock['a'] 1 >>> mock['c'] @@ -964,11 +1105,13 @@ After it has been used you can make assertions about the access using the normal mock methods and attributes: +.. doctest:: + >>> mock.__getitem__.call_args_list [call('a'), call('c'), call('d'), call('b'), call('d')] >>> mock.__setitem__.call_args_list [call('b', 'fish'), call('d', 'eggs')] - >>> my_dict + >>> my_dict # doctest: +SKIP {'a': 1, 'c': 3, 'b': 'fish', 'd': 'eggs'} @@ -978,6 +1121,8 @@ There are various reasons why you might want to subclass :class:`Mock`. One reason might be to add helper methods. Here's a silly example: +.. doctest:: + >>> class MyMock(MagicMock): ... def has_been_called(self): ... return self.called @@ -998,6 +1143,8 @@ available on the attributes and return value mock of instances of your subclass. +.. doctest:: + >>> mymock.foo >>> mymock.foo.has_been_called() @@ -1019,6 +1166,8 @@ that it takes arbitrary keyword arguments (``**kwargs``) which are then passed onto the mock constructor: +.. doctest:: + >>> class Subclass(MagicMock): ... def _get_child_mock(self, **kwargs): ... return MagicMock(**kwargs) @@ -1064,6 +1213,9 @@ Here's an example that mocks out the 'fooble' module. +.. doctest:: + + >>> import sys >>> mock = Mock() >>> with patch.dict('sys.modules', {'fooble': mock}): ... import fooble @@ -1078,6 +1230,8 @@ This also works for the ``from module import name`` form: +.. doctest:: + >>> mock = Mock() >>> with patch.dict('sys.modules', {'fooble': mock}): ... from fooble import blob @@ -1088,6 +1242,8 @@ With slightly more work you can also mock package imports: +.. doctest:: + >>> mock = Mock() >>> modules = {'package': mock, 'package.module': mock.module} >>> with patch.dict('sys.modules', modules): @@ -1111,6 +1267,8 @@ mocks from a parent one. Calls to those child mock will then all be recorded, in order, in the ``mock_calls`` of the parent: +.. doctest:: + >>> manager = Mock() >>> mock_foo = manager.foo >>> mock_bar = manager.bar @@ -1126,6 +1284,8 @@ We can then assert about the calls, including the order, by comparing with the ``mock_calls`` attribute on the manager mock: +.. doctest:: + >>> expected_calls = [call.foo.something(), call.bar.other.thing()] >>> manager.mock_calls == expected_calls True @@ -1134,6 +1294,8 @@ them to a manager mock using the :meth:`~Mock.attach_mock` method. After attaching calls will be recorded in ``mock_calls`` of the manager. +.. doctest:: + >>> manager = MagicMock() >>> with patch('mymodule.Class1') as MockClass1: ... with patch('mymodule.Class2') as MockClass2: @@ -1156,6 +1318,8 @@ with the :data:`call` object). If that sequence of calls are in :attr:`~Mock.mock_calls` then the assert succeeds. +.. doctest:: + >>> m = MagicMock() >>> m().foo().bar().baz() @@ -1171,6 +1335,8 @@ in asserting about *some* of those calls. You may not even care about the order. In this case you can pass ``any_order=True`` to ``assert_has_calls``: +.. doctest:: + >>> m = MagicMock() >>> m(1), m.two(2, 3), m.seven(7), m.fifty('50') (...) @@ -1194,6 +1360,8 @@ You can see in this example how a 'standard' call to ``assert_called_with`` isn't sufficient: +.. doctest:: + >>> class Foo: ... def __init__(self, a, b): ... self.a, self.b = a, b @@ -1208,6 +1376,8 @@ A comparison function for our ``Foo`` class might look something like this: +.. doctest:: + >>> def compare(self, other): ... if not type(self) == type(other): ... return False @@ -1221,6 +1391,8 @@ And a matcher object that can use comparison functions like this for its equality operation would look something like this: +.. doctest:: + >>> class Matcher: ... def __init__(self, compare, some_obj): ... self.compare = compare @@ -1231,6 +1403,8 @@ Putting all this together: +.. doctest:: + >>> match_foo = Matcher(compare, Foo(1, 2)) >>> mock.assert_called_with(match_foo) @@ -1240,6 +1414,8 @@ against the one we created our matcher with. If they match then ``assert_called_with`` passes, and if they don't an :exc:`AssertionError` is raised: +.. doctest:: + >>> match_wrong = Matcher(compare, Foo(3, 4)) >>> mock.assert_called_with(match_wrong) Traceback (most recent call last): diff --git a/Doc/library/unittest.mock.rst b/Doc/library/unittest.mock.rst --- a/Doc/library/unittest.mock.rst +++ b/Doc/library/unittest.mock.rst @@ -46,7 +46,13 @@ can configure them, to specify return values or limit what attributes are available, and then make assertions about how they have been used: +.. doctest:: + >>> from unittest.mock import MagicMock + >>> class ProductionClass: + ... def method(self): + ... pass + ... >>> thing = ProductionClass() >>> thing.method = MagicMock(return_value=3) >>> thing.method(3, 4, 5, key='value') @@ -56,6 +62,9 @@ :attr:`side_effect` allows you to perform side effects, including raising an exception when a mock is called: +.. doctest:: + + >>> from unittest.mock import Mock >>> mock = Mock(side_effect=KeyError('foo')) >>> mock() Traceback (most recent call last): @@ -82,6 +91,19 @@ objects in a module under test. The object you specify will be replaced with a mock (or other object) during the test and restored when the test ends: +.. testsetup:: + + from unittest_mock.package import module + from unittest_mock import package + + # This allows us to import unittest_mock.package.module as + # ``import module`` and unittest_mock.package as ``import package`` + import sys + sys.modules['module'] = module + sys.modules['package'] = package + +.. doctest:: + >>> from unittest.mock import patch >>> @patch('module.ClassName2') ... @patch('module.ClassName1') @@ -109,6 +131,8 @@ As well as a decorator :func:`patch` can be used as a context manager in a with statement: +.. doctest:: + >>> with patch.object(ProductionClass, 'method', return_value=None) as mock_method: ... thing = ProductionClass() ... thing.method(1, 2, 3) @@ -120,6 +144,8 @@ during a scope and restoring the dictionary to its original state when the test ends: +.. doctest:: + >>> foo = {'key': 'value'} >>> original = foo.copy() >>> with patch.dict(foo, {'newkey': 'newvalue'}, clear=True): @@ -131,6 +157,8 @@ easiest way of using magic methods is with the :class:`MagicMock` class. It allows you to do things like: +.. doctest:: + >>> mock = MagicMock() >>> mock.__str__.return_value = 'foobarbaz' >>> str(mock) @@ -145,6 +173,8 @@ The following is an example of using magic methods with the ordinary Mock class: +.. doctest:: + >>> mock = Mock() >>> mock.__str__ = Mock(return_value='wheeeeee') >>> str(mock) @@ -161,6 +191,8 @@ This ensures that your mocks will fail in the same way as your production code if they are used incorrectly: +.. doctest:: + >>> from unittest.mock import create_autospec >>> def function(a, b, c): ... pass @@ -266,6 +298,8 @@ Assert that the mock was called at least once. + .. doctest:: + >>> mock = Mock() >>> mock.method() @@ -277,6 +311,8 @@ Assert that the mock was called exactly once. + .. doctest:: + >>> mock = Mock() >>> mock.method() @@ -296,6 +332,8 @@ This method is a convenient way of asserting that calls are made in a particular way: + .. doctest:: + >>> mock = Mock() >>> mock.method(1, 2, 3, test='wow') @@ -306,6 +344,8 @@ Assert that the mock was called exactly once and with the specified arguments. + .. doctest:: + >>> mock = Mock(return_value=None) >>> mock('foo', bar='baz') >>> mock.assert_called_once_with('foo', bar='baz') @@ -323,6 +363,8 @@ The assert passes if the mock has *ever* been called, unlike :meth:`assert_called_with` and :meth:`assert_called_once_with` that only pass if the call is the most recent one. + + .. doctest:: >>> mock = Mock(return_value=None) >>> mock(1, 2, arg='thing') @@ -342,11 +384,14 @@ If *any_order* is true then the calls can be in any order, but they must all appear in :attr:`mock_calls`. + .. doctest:: + >>> mock = Mock(return_value=None) >>> mock(1) >>> mock(2) >>> mock(3) >>> mock(4) + >>> from unittest.mock import call >>> calls = [call(2), call(3)] >>> mock.assert_has_calls(calls) >>> calls = [call(4), call(2), call(3)] @@ -356,6 +401,8 @@ Assert the mock was never called. + .. doctest:: + >>> m = Mock() >>> m.hello.assert_not_called() >>> obj = m.hello() @@ -371,6 +418,8 @@ The reset_mock method resets all the call attributes on a mock object: + .. doctest:: + >>> mock = Mock(return_value=None) >>> mock('hello') >>> mock.called @@ -418,6 +467,8 @@ mocks using standard dot notation and unpacking a dictionary in the method call: + .. doctest:: + >>> mock = Mock() >>> attrs = {'method.return_value': 3, 'other.side_effect': KeyError} >>> mock.configure_mock(**attrs) @@ -430,6 +481,8 @@ The same thing can be achieved in the constructor call to mocks: + .. doctest:: + >>> attrs = {'method.return_value': 3, 'other.side_effect': KeyError} >>> mock = Mock(some_attribute='eggs', **attrs) >>> mock.some_attribute @@ -470,6 +523,8 @@ A boolean representing whether or not the mock object has been called: + .. doctest:: + >>> mock = Mock(return_value=None) >>> mock.called False @@ -481,6 +536,8 @@ An integer telling you how many times the mock object has been called: + .. doctest:: + >>> mock = Mock(return_value=None) >>> mock.call_count 0 @@ -494,6 +551,8 @@ Set this to configure the value returned by calling the mock: + .. doctest:: + >>> mock = Mock() >>> mock.return_value = 'fish' >>> mock() @@ -502,6 +561,9 @@ The default return value is a mock object and you can configure it in the normal way: + .. doctest:: + + >>> from unittest.mock import sentinel >>> mock = Mock() >>> mock.return_value.attribute = sentinel.Attribute >>> mock.return_value() @@ -510,6 +572,8 @@ :attr:`return_value` can also be set in the constructor: + .. doctest:: + >>> mock = Mock(return_value=3) >>> mock.return_value 3 @@ -536,6 +600,8 @@ An example of a mock that raises an exception (to test exception handling of an API): + .. doctest:: + >>> mock = Mock() >>> mock.side_effect = Exception('Boom!') >>> mock() @@ -545,6 +611,8 @@ Using :attr:`side_effect` to return a sequence of values: + .. doctest:: + >>> mock = Mock() >>> mock.side_effect = [3, 2, 1] >>> mock(), mock(), mock() @@ -552,6 +620,9 @@ Using a callable: + .. doctest:: + + >>> from unittest.mock import DEFAULT >>> mock = Mock(return_value=3) >>> def side_effect(*args, **kwargs): ... return DEFAULT @@ -563,6 +634,8 @@ :attr:`side_effect` can be set in the constructor. Here's an example that adds one to the value the mock is called with and returns it: + .. doctest:: + >>> side_effect = lambda value: value + 1 >>> mock = Mock(side_effect=side_effect) >>> mock(3) @@ -572,6 +645,8 @@ Setting :attr:`side_effect` to ``None`` clears it: + .. doctest:: + >>> m = Mock(side_effect=KeyError, return_value=3) >>> m() Traceback (most recent call last): @@ -590,6 +665,8 @@ was called with (or an empty tuple) and the second member is any keyword arguments (or an empty dictionary). + .. doctest:: + >>> mock = Mock(return_value=None) >>> print(mock.call_args) None @@ -622,6 +699,8 @@ :data:`call` object can be used for conveniently constructing lists of calls to compare with :attr:`call_args_list`. + .. doctest:: + >>> mock = Mock(return_value=None) >>> mock() >>> mock(3, 4) @@ -642,6 +721,8 @@ As well as tracking calls to themselves, mocks also track calls to methods and attributes, and *their* methods and attributes: + .. doctest:: + >>> mock = Mock() >>> mock.method() @@ -660,6 +741,8 @@ :attr:`mock_calls` records *all* calls to the mock object, its methods, magic methods *and* return value mocks. + .. doctest:: + >>> mock = MagicMock() >>> result = mock(1, 2, 3) >>> mock.first(a=3) @@ -687,6 +770,8 @@ instead. This allows mock objects to pass :func:`isinstance` tests for the object they are replacing / masquerading as: + .. doctest:: + >>> mock = Mock(spec=3) >>> isinstance(mock, int) True @@ -694,6 +779,8 @@ :attr:`__class__` is assignable to, this allows a mock to pass an :func:`isinstance` check without forcing you to use a spec: + .. doctest:: + >>> mock = Mock() >>> mock.__class__ = dict >>> isinstance(mock, dict) @@ -708,6 +795,15 @@ Mock objects that use a class or an instance as a :attr:`spec` or :attr:`spec_set` are able to pass :func:`isinstance` tests: +.. doctest:: + + >>> class SomeClass: + ... def static_method(par): + ... pass + ... @classmethod + ... def class_method(cls, par): + ... pass + ... >>> mock = Mock(spec=SomeClass) >>> isinstance(mock, SomeClass) True @@ -723,6 +819,8 @@ passed to the constructor of the mock being created. The keyword arguments are for configuring attributes of the mock: +.. doctest:: + >>> m = MagicMock(attribute=3, other='fish') >>> m.attribute 3 @@ -733,6 +831,8 @@ using dotted notation. As you can't use dotted names directly in a call you have to create a dictionary and unpack it using ``**``: +.. doctest:: + >>> attrs = {'method.return_value': 3, 'other.side_effect': KeyError} >>> mock = Mock(some_attribute='eggs', **attrs) >>> mock.some_attribute @@ -747,13 +847,15 @@ A callable mock which was created with a *spec* (or a *spec_set*) will introspect the specification object's signature when matching calls to the mock. Therefore, it can match the actual call's arguments regardless -of whether they were passed positionally or by name:: +of whether they were passed positionally or by name: + +.. doctest:: >>> def f(a, b, c): pass ... >>> mock = Mock(spec=f) >>> mock(1, 2, c=3) - + >>> mock.assert_called_with(1, 2, 3) >>> mock.assert_called_with(a=1, b=2, c=3) @@ -775,6 +877,8 @@ Fetching a :class:`PropertyMock` instance from an object calls the mock, with no args. Setting it calls the mock with the value being set. + .. doctest:: + >>> class Foo: ... @property ... def foo(self): @@ -783,6 +887,7 @@ ... def foo(self, value): ... pass ... + >>> from unittest.mock import PropertyMock >>> with patch('__main__.Foo.foo', new_callable=PropertyMock) as mock_foo: ... mock_foo.return_value = 'mockity-mock' ... this_foo = Foo() @@ -795,7 +900,9 @@ Because of the way mock attributes are stored you can't directly attach a :class:`PropertyMock` to a mock object. Instead you can attach it to the mock type -object:: +object: + +.. doctest:: >>> m = MagicMock() >>> p = PropertyMock(return_value=3) @@ -824,6 +931,8 @@ The simplest way to make a mock raise an exception when called is to make :attr:`~Mock.side_effect` an exception class or instance: +.. doctest:: + >>> m = MagicMock(side_effect=IndexError) >>> m(1, 2, 3) Traceback (most recent call last): @@ -844,6 +953,8 @@ same arguments as the mock. This allows you to vary the return value of the call dynamically, based on the input: +.. doctest:: + >>> def side_effect(value): ... return value + 1 ... @@ -859,6 +970,8 @@ any set return value, then there are two ways of doing this. Either return :attr:`mock.return_value` from inside :attr:`side_effect`, or return :data:`DEFAULT`: +.. doctest:: + >>> m = MagicMock() >>> def side_effect(*args, **kwargs): ... return m.return_value @@ -877,6 +990,8 @@ To remove a :attr:`side_effect`, and return to the default behaviour, set the :attr:`side_effect` to ``None``: +.. doctest:: + >>> m = MagicMock(return_value=6) >>> def side_effect(*args, **kwargs): ... return 3 @@ -892,6 +1007,8 @@ will return values from the iterable (until the iterable is exhausted and a :exc:`StopIteration` is raised): +.. doctest:: + >>> m = MagicMock(side_effect=[1, 2, 3]) >>> m() 1 @@ -907,6 +1024,8 @@ If any members of the iterable are exceptions they will be raised instead of returned:: +.. doctest:: + >>> iterable = (33, ValueError, 66) >>> m = MagicMock(side_effect=iterable) >>> m() @@ -934,6 +1053,8 @@ You "block" attributes by deleting them. Once deleted, accessing an attribute will raise an :exc:`AttributeError`. +.. doctest:: + >>> mock = MagicMock() >>> hasattr(mock, 'm') True @@ -953,14 +1074,18 @@ Since "name" is an argument to the :class:`Mock` constructor, if you want your mock object to have a "name" attribute you can't just pass it in at creation time. There are two alternatives. One option is to use -:meth:`~Mock.configure_mock`:: +:meth:`~Mock.configure_mock`: + +.. doctest:: >>> mock = MagicMock() >>> mock.configure_mock(name='my_name') >>> mock.name 'my_name' -A simpler option is to simply set the "name" attribute after mock creation:: +A simpler option is to simply set the "name" attribute after mock creation: + +.. doctest:: >>> mock = MagicMock() >>> mock.name = "foo" @@ -977,6 +1102,8 @@ children and allows you to make assertions about the order of calls between mocks: +.. doctest:: + >>> parent = MagicMock() >>> child1 = MagicMock(return_value=None) >>> child2 = MagicMock(return_value=None) @@ -990,6 +1117,8 @@ The exception to this is if the mock has a name. This allows you to prevent the "parenting" if for some reason you don't want it to happen. +.. doctest:: + >>> mock = MagicMock() >>> not_a_child = MagicMock(name='not-a-child') >>> mock.attribute = not_a_child @@ -1002,6 +1131,8 @@ attach mocks that have names to a parent you use the :meth:`~Mock.attach_mock` method: +.. doctest:: + >>> thing1 = object() >>> thing2 = object() >>> parent = MagicMock() @@ -1118,6 +1249,8 @@ :func:`patch` as function decorator, creating the mock for you and passing it into the decorated function: +.. doctest:: + >>> @patch('__main__.SomeClass') ... def function(normal_argument, mock_class): ... print(mock_class is SomeClass) @@ -1136,6 +1269,8 @@ To configure return values on methods of *instances* on the patched class you must do this on the :attr:`return_value`. For example: +.. doctest:: + >>> class Class: ... def method(self): ... pass @@ -1150,6 +1285,8 @@ If you use *spec* or *spec_set* and :func:`patch` is replacing a *class*, then the return value of the created mock will have the same spec. +.. doctest:: + >>> Original = Class >>> patcher = patch('__main__.Class', spec=True) >>> MockClass = patcher.start() @@ -1161,6 +1298,9 @@ class to the default :class:`MagicMock` for the created mock. For example, if you wanted a :class:`NonCallableMock` to be used: +.. doctest:: + + >>> from unittest.mock import NonCallableMock >>> thing = object() >>> with patch('__main__.thing', new_callable=NonCallableMock) as mock_thing: ... assert thing is mock_thing @@ -1172,6 +1312,8 @@ Another use case might be to replace an object with an :class:`io.StringIO` instance: +.. doctest:: + >>> from io import StringIO >>> def foo(): ... print('Something') @@ -1188,6 +1330,8 @@ in the call to patch. Any arbitrary keywords you pass into the call will be used to set attributes on the created mock: +.. doctest:: + >>> patcher = patch('__main__.thing', first='one', second='two') >>> mock_thing = patcher.start() >>> mock_thing.first @@ -1201,6 +1345,8 @@ keyword arguments, but a dictionary with these as keys can still be expanded into a :func:`patch` call using ``**``: +.. doctest:: + >>> config = {'method.return_value': 3, 'other.side_effect': KeyError} >>> patcher = patch('__main__.thing', **config) >>> mock_thing = patcher.start() @@ -1237,6 +1383,8 @@ mock is created for you and passed in as an extra argument to the decorated function: +.. doctest:: + >>> @patch.object(SomeClass, 'class_method') ... def test(mock_method): ... SomeClass.class_method(3) @@ -1280,6 +1428,8 @@ change a dictionary, and ensure the dictionary is restored when the test ends. +.. doctest:: + >>> foo = {} >>> with patch.dict(foo, {'newkey': 'newvalue'}): ... assert foo == {'newkey': 'newvalue'} @@ -1295,6 +1445,8 @@ Keywords can be used in the :func:`patch.dict` call to set values in the dictionary: +.. doctest:: + >>> mymodule = MagicMock() >>> mymodule.function.return_value = 'fish' >>> with patch.dict('sys.modules', mymodule=mymodule): @@ -1309,6 +1461,8 @@ magic methods :meth:`__getitem__`, :meth:`__setitem__`, :meth:`__delitem__` and either :meth:`__iter__` or :meth:`__contains__`. +.. doctest:: + >>> class Container: ... def __init__(self): ... self.values = {} @@ -1360,6 +1514,8 @@ :data:`DEFAULT` as the value. If you use :func:`patch.multiple` as a decorator then the created mocks are passed into the decorated function by keyword. +.. doctest:: + >>> thing = object() >>> other = object() @@ -1373,6 +1529,8 @@ :func:`patch.multiple` can be nested with other ``patch`` decorators, but put arguments passed by keyword *after* any of the standard arguments created by :func:`patch`: +.. doctest:: + >>> @patch('sys.exit') ... @patch.multiple('__main__', thing=DEFAULT, other=DEFAULT) ... def test_function(mock_exit, other, thing): @@ -1385,6 +1543,8 @@ If :func:`patch.multiple` is used as a context manager, the value returned by the context manger is a dictionary where created mocks are keyed by name: +.. doctest:: + >>> with patch.multiple('__main__', thing=DEFAULT, other=DEFAULT) as values: ... assert 'other' in repr(values['other']) ... assert 'thing' in repr(values['thing']) @@ -1409,6 +1569,8 @@ If you are using :func:`patch` to create a mock for you then it will be returned by the call to ``patcher.start``. +.. doctest:: + >>> patcher = patch('package.module.ClassName') >>> from package import module >>> original = module.ClassName @@ -1423,7 +1585,10 @@ A typical use case for this might be for doing multiple patches in the ``setUp`` method of a :class:`TestCase`: - >>> class MyTest(TestCase): +.. doctest:: + + >>> import unittest + >>> class MyTest(unittest.TestCase): ... def setUp(self): ... self.patcher1 = patch('package.module.Class1') ... self.patcher2 = patch('package.module.Class2') @@ -1439,6 +1604,7 @@ ... assert package.module.Class2 is self.MockClass2 ... >>> MyTest('test_something').run() + .. caution:: @@ -1447,7 +1613,9 @@ exception is raised in the ``setUp`` then ``tearDown`` is not called. :meth:`unittest.TestCase.addCleanup` makes this easier: - >>> class MyTest(TestCase): + .. doctest:: + + >>> class MyTest(unittest.TestCase): ... def setUp(self): ... patcher = patch('package.module.Class') ... self.MockClass = patcher.start() @@ -1475,6 +1643,13 @@ You can patch any builtins within a module. The following example patches builtin :func:`ord`: +.. testsetup:: ord + + from builtins import ord + from unittest.mock import patch + +.. doctest:: ord + >>> @patch('__main__.ord') ... def test(mock_ord): ... mock_ord.return_value = 101 @@ -1495,6 +1670,8 @@ It is possible that you want to use a different prefix for your tests. You can inform the patchers of the different prefix by setting ``patch.TEST_PREFIX``: +.. doctest:: + >>> patch.TEST_PREFIX = 'foo' >>> value = 3 >>> @@ -1522,6 +1699,15 @@ You can stack up multiple patch decorators using this pattern: +.. doctest:: + + >>> class SomeClass: + ... def static_method(par): + ... pass + ... @classmethod + ... def class_method(cls, par): + ... pass + ... >>> @patch.object(SomeClass, 'class_method') ... @patch.object(SomeClass, 'static_method') ... def test(mock1, mock2): @@ -1616,6 +1802,8 @@ or a mock instance. If you are using a function then it *must* take ``self`` as the first argument [#]_. +.. doctest:: + >>> def __str__(self): ... return 'fooble' ... @@ -1638,6 +1826,8 @@ One use case for this is for mocking objects used as context managers in a :keyword:`with` statement: +.. doctest:: + >>> mock = Mock() >>> mock.__enter__ = Mock(return_value='foo') >>> mock.__exit__ = Mock(return_value=False) @@ -1715,6 +1905,8 @@ The magic methods are setup with :class:`MagicMock` objects, so you can configure them and use them in the usual way: +.. doctest:: + >>> mock = MagicMock() >>> mock[3] = 'fish' >>> mock.__setitem__.assert_called_with(3, 'fish') @@ -1749,6 +1941,8 @@ For example: +.. doctest:: + >>> mock = MagicMock() >>> int(mock) 1 @@ -1776,6 +1970,8 @@ The return value of :meth:`MagicMock.__iter__` can be any iterable object and isn't required to be an iterator: +.. doctest:: + >>> mock = MagicMock() >>> mock.__iter__.return_value = ['a', 'b', 'c'] >>> list(mock) @@ -1786,6 +1982,8 @@ If the return value *is* an iterator, then iterating over it once will consume it and subsequent iterations will result in an empty list: +.. doctest:: + >>> mock.__iter__.return_value = iter(['a', 'b', 'c']) >>> list(mock) ['a', 'b', 'c'] @@ -1838,6 +2036,8 @@ In this example we monkey patch ``method`` to return ``sentinel.some_object``: +.. doctest:: + >>> real = ProductionClass() >>> real.method = Mock(name="method") >>> real.method.return_value = sentinel.some_object @@ -1868,6 +2068,8 @@ :attr:`~Mock.mock_calls` and :attr:`~Mock.method_calls`. :func:`call` can also be used with :meth:`~Mock.assert_has_calls`. + .. doctest:: + >>> m = MagicMock(return_value=None) >>> m(1, 2, a='foo', b='bar') >>> m() @@ -1888,6 +2090,8 @@ :meth:`~call.call_list` can construct the sequence of calls from the same chained call: +.. doctest:: + >>> m = MagicMock() >>> m(1).method(arg='foo').other('bar')(2.0) @@ -1919,13 +2123,15 @@ (an empty tuple if there are no positional arguments) and the keyword arguments are a dictionary: +.. doctest:: + >>> m = MagicMock(return_value=None) >>> m(1, 2, 3, arg='one', arg2='two') >>> kall = m.call_args >>> args, kwargs = kall >>> args (1, 2, 3) - >>> kwargs + >>> kwargs # doctest: +SKIP {'arg2': 'two', 'arg': 'one'} >>> args is kall[0] True @@ -1941,7 +2147,7 @@ 'foo' >>> args (4, 5, 6) - >>> kwargs + >>> kwargs # doctest: +SKIP {'arg2': 'three', 'arg': 'two'} >>> name is m.mock_calls[0][0] True @@ -1989,6 +2195,9 @@ :meth:`~Mock.assert_called_once_with` will then succeed no matter what was passed in. +.. doctest:: + + >>> from unittest.mock import Mock, ANY >>> mock = Mock(return_value=None) >>> mock('foo', bar=object()) >>> mock.assert_called_once_with('foo', bar=ANY) @@ -1996,6 +2205,8 @@ :data:`ANY` can also be used in comparisons with call lists like :attr:`~Mock.mock_calls`: +.. doctest:: + >>> m = MagicMock(return_value=None) >>> m(1) >>> m(1, 2) @@ -2022,12 +2233,15 @@ attributes from the original are shown, even if they haven't been accessed yet: +.. doctest:: + :options: +NORMALIZE_WHITESPACE + >>> dir(Mock()) ['assert_any_call', + 'assert_called', + 'assert_called_once', 'assert_called_once_with', 'assert_called_with', - 'assert_has_calls', - 'attach_mock', ... >>> from urllib import request >>> dir(Mock(spec=request)) @@ -2043,6 +2257,9 @@ behaviour you can switch it off by setting the module level switch :data:`FILTER_DIR`: +.. doctest:: + :options: +NORMALIZE_WHITESPACE + >>> from unittest import mock >>> mock.FILTER_DIR = False >>> dir(mock.Mock()) @@ -2103,6 +2320,14 @@ Mocking context managers with a :class:`MagicMock` is common enough and fiddly enough that a helper function is useful. +.. testsetup:: open + + from builtins import open + from unittest.mock import patch + +.. doctest:: open + + >>> from unittest.mock import mock_open, call >>> m = mock_open() >>> with patch('__main__.open', m): ... with open('foo', 'w') as h: @@ -2119,6 +2344,8 @@ And for reading files: +.. doctest:: open + >>> with patch('__main__.open', mock_open(read_data='bibble')) as m: ... with open('foo') as h: ... result = h.read() @@ -2150,6 +2377,8 @@ extremely handy: :meth:`~Mock.assert_called_with` and :meth:`~Mock.assert_called_once_with`. +.. doctest:: + >>> mock = Mock(name='Thing', return_value=None) >>> mock(1, 2, 3) >>> mock.assert_called_once_with(1, 2, 3) @@ -2163,11 +2392,12 @@ with arbitrary arguments, if you misspell one of these assert methods then your assertion is gone: -.. code-block:: pycon +.. doctest:: >>> mock = Mock(name='Thing', return_value=None) >>> mock(1, 2, 3) - >>> mock.assret_called_once_with(4, 5, 6) + >>> mock.asset_called_once_with(4, 5, 6) + Your tests can pass silently and incorrectly because of the typo. @@ -2185,21 +2415,24 @@ use a class or instance as the :attr:`spec` for a mock then you can only access attributes on the mock that exist on the real class: +.. doctest:: + >>> from urllib import request >>> mock = Mock(spec=request.Request) - >>> mock.assret_called_with + >>> mock.asset_called_with Traceback (most recent call last): ... - AttributeError: Mock object has no attribute 'assret_called_with' + AttributeError: Mock object has no attribute 'asset_called_with' The spec only applies to the mock itself, so we still have the same issue with any methods on the mock: -.. code-block:: pycon - - >>> mock.has_data() - - >>> mock.has_data.assret_called_with() +.. doctest:: + + >>> mock.has_proxy() + + >>> mock.has_proxy().asset_called_with() + Auto-speccing solves this problem. You can either pass ``autospec=True`` to :func:`patch` / :func:`patch.object` or use the :func:`create_autospec` function to create a @@ -2212,6 +2445,8 @@ Here's an example of it in use: +.. doctest:: + >>> from urllib import request >>> patcher = patch('__main__.request', autospec=True) >>> mock_request = patcher.start() @@ -2224,6 +2459,8 @@ arguments in the constructor (one of which is *self*). Here's what happens if we try to call it incorrectly: +.. doctest:: + >>> req = request.Request() Traceback (most recent call last): ... @@ -2232,6 +2469,8 @@ The spec also applies to instantiated classes (i.e. the return value of specced mocks): +.. doctest:: + >>> req = request.Request('foo') >>> req @@ -2240,6 +2479,8 @@ mocked out :class:`request.Request` is a non-callable mock. With the spec in place any typos in our asserts will raise the correct error: +.. doctest:: + >>> req.add_header('spam', 'eggs') >>> req.add_header.assret_called_with @@ -2255,6 +2496,8 @@ As well as using *autospec* through :func:`patch` there is a :func:`create_autospec` for creating autospecced mocks directly: +.. doctest:: + >>> from urllib import request >>> mock_request = create_autospec(request) >>> mock_request.Request('foo', 'bar') @@ -2274,6 +2517,8 @@ *autospec* can't know about any dynamically created attributes and restricts the api to visible attributes. +.. doctest:: + >>> class Something: ... def __init__(self): ... self.a = 33 @@ -2292,6 +2537,8 @@ you to fetch attributes that don't exist on the spec it doesn't prevent you setting them: +.. doctest:: + >>> with patch('__main__.Something', autospec=True): ... thing = Something() ... thing.a = 33 @@ -2302,6 +2549,8 @@ ensure your code only *sets* valid attributes too, but obviously it prevents this particular scenario: +.. doctest:: + >>> with patch('__main__.Something', autospec=True, spec_set=True): ... thing = Something() ... thing.a = 33 @@ -2328,6 +2577,8 @@ autospec doesn't use a spec for members that are set to ``None``. These will just be ordinary mocks (well - MagicMocks): +.. doctest:: + >>> class Something: ... member = None ... @@ -2343,6 +2594,8 @@ the spec. Thankfully :func:`patch` supports this - you can simply pass the alternative object as the *autospec* argument: +.. doctest:: + >>> class Something: ... def __init__(self): ... self.a = 33 diff --git a/Doc/library/urllib.parse.rst b/Doc/library/urllib.parse.rst --- a/Doc/library/urllib.parse.rst +++ b/Doc/library/urllib.parse.rst @@ -64,16 +64,19 @@ input is presumed to be a relative URL and thus to start with a path component. + .. doctest:: + :options: +NORMALIZE_WHITESPACE + >>> from urllib.parse import urlparse >>> urlparse('//www.cwi.nl:80/%7Eguido/Python.html') ParseResult(scheme='', netloc='www.cwi.nl:80', path='/%7Eguido/Python.html', - params='', query='', fragment='') + params='', query='', fragment='') >>> urlparse('www.cwi.nl/%7Eguido/Python.html') ParseResult(scheme='', netloc='', path='www.cwi.nl/%7Eguido/Python.html', - params='', query='', fragment='') + params='', query='', fragment='') >>> urlparse('help/Python.html') ParseResult(scheme='', netloc='', path='help/Python.html', params='', - query='', fragment='') + query='', fragment='') The *scheme* argument gives the default addressing scheme, to be used only if the URL does not specify one. It should be the same type diff --git a/Doc/library/weakref.rst b/Doc/library/weakref.rst --- a/Doc/library/weakref.rst +++ b/Doc/library/weakref.rst @@ -475,10 +475,12 @@ method. This kills the finalizer and returns the arguments passed to the constructor when it was created. +.. doctest:: + >>> obj = Object() >>> f = weakref.finalize(obj, callback, 1, 2, z=3) - >>> f.detach() #doctest:+ELLIPSIS - (<__main__.Object object ...>, , (1, 2), {'z': 3}) + >>> f.detach() # doctest: +ELLIPSIS + (, , (1, 2), {'z': 3}) >>> newobj, func, args, kwargs = _ >>> assert not f.alive >>> assert newobj is obj diff --git a/Doc/whatsnew/3.2.rst b/Doc/whatsnew/3.2.rst --- a/Doc/whatsnew/3.2.rst +++ b/Doc/whatsnew/3.2.rst @@ -1384,7 +1384,7 @@ for writing. >>> import select ->>> select.PIPE_BUF +>>> select.PIPE_BUF # doctest: +SKIP 512 (Available on Unix systems. Patch by Sébastien Sablé in :issue:`9862`)