diff --git a/Doc/ACKS.txt b/Doc/ACKS.txt index f9049c51948..d0c1f31cb95 100644 --- a/Doc/ACKS.txt +++ b/Doc/ACKS.txt @@ -136,6 +136,7 @@ docs@python.org), and we'll be glad to correct the problem. * Tomas Oppelstrup * Denis S. Otkidach * Zooko O'Whielacronx + * Shriphani Palakodety * William Park * Joonas Paalasmaa * Harri Pasanen diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst index d46a8956b0b..3ac95b122d8 100644 --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -429,7 +429,7 @@ Example:: return dict(zip(('x', 'y'), self)) def __replace__(self, **kwds): 'Return a new Point object replacing specified fields with new values' - return Point(**dict(zip(('x', 'y'), self) + kwds.items())) + return Point(**dict(zip(('x', 'y'), self), **kwds)) x = property(itemgetter(0)) y = property(itemgetter(1)) diff --git a/Lib/collections.py b/Lib/collections.py index f5c524b25a8..5fb0e05d120 100644 --- a/Lib/collections.py +++ b/Lib/collections.py @@ -2,6 +2,7 @@ __all__ = ['deque', 'defaultdict', 'namedtuple'] from _collections import deque, defaultdict from operator import itemgetter as _itemgetter +from itertools import izip as _izip from keyword import iskeyword as _iskeyword import sys as _sys @@ -70,14 +71,14 @@ def namedtuple(typename, field_names, verbose=False): return dict(zip(%(field_names)r, self)) def __replace__(self, **kwds): 'Return a new %(typename)s object replacing specified fields with new values' - return %(typename)s(**dict(list(zip(%(field_names)r, self)) + list(kwds.items()))) \n''' % locals() + return %(typename)s(**dict(zip(%(field_names)r, self), **kwds)) \n''' % locals() for i, name in enumerate(field_names): template += ' %s = property(itemgetter(%d))\n' % (name, i) if verbose: print(template) # Execute the template string in a temporary namespace - namespace = dict(itemgetter=_itemgetter) + namespace = dict(itemgetter=_itemgetter, zip=_izip) try: exec(template, namespace) except SyntaxError as e: diff --git a/Lib/distutils/sysconfig.py b/Lib/distutils/sysconfig.py index 191f3d1d183..c450cd51591 100644 --- a/Lib/distutils/sysconfig.py +++ b/Lib/distutils/sysconfig.py @@ -32,7 +32,7 @@ if os.name == "nt" and "pcbuild" in project_base[-8:].lower(): # building an extension with an un-installed Python, so we use # different (hard-wired) directories. python_build = os.path.isfile(os.path.join(project_base, "Modules", - "Setup.dist")) + "Setup.local")) def get_python_version(): """Return a string containing the major and minor Python version, diff --git a/Lib/idlelib/tabbedpages.py b/Lib/idlelib/tabbedpages.py index bb8b1ae5086..f8d89a46720 100644 --- a/Lib/idlelib/tabbedpages.py +++ b/Lib/idlelib/tabbedpages.py @@ -4,7 +4,7 @@ Originally developed for use in IDLE. Based on tabpage.py. Classes exported: TabbedPageSet -- A Tkinter implementation of a tabbed-page widget. -TabBarSet -- A widget containing tabs (buttons) in one or more rows. +TabSet -- A widget containing tabs (buttons) in one or more rows. """ from Tkinter import * @@ -13,7 +13,7 @@ class InvalidNameError(Exception): pass class AlreadyExistsError(Exception): pass -class TabBarSet(Frame): +class TabSet(Frame): """A widget containing tabs (buttons) in one or more rows. Only one tab may be selected at a time. @@ -30,11 +30,11 @@ class TabBarSet(Frame): tabs -- A list of strings, the names of the tabs. Should be specified in the desired tab order. The first tab will be the default and first - active tab. If tabs is None or empty, the TabBarSet will be initialized + active tab. If tabs is None or empty, the TabSet will be initialized empty. n_rows -- Number of rows of tabs to be shown. If n_rows <= 0 or is - None, then the number of rows will be decided by TabBarSet. See + None, then the number of rows will be decided by TabSet. See _arrange_tabs() for details. max_tabs_per_row -- Used for deciding how many rows of tabs are needed, @@ -76,15 +76,15 @@ class TabBarSet(Frame): self._arrange_tabs() def remove_tab(self, tab_name): - """Remove the tab with the name given in tab_name.""" + """Remove the tab named """ if not tab_name in self._tab_names: raise KeyError("No such Tab: '%s" % page_name) self._tab_names.remove(tab_name) self._arrange_tabs() - def select_tab(self, tab_name): - """Select the tab with the name given in tab_name.""" + def set_selected_tab(self, tab_name): + """Show the tab named as the selected one""" if tab_name == self._selected_tab: return if tab_name is not None and tab_name not in self._tabs: @@ -111,14 +111,11 @@ class TabBarSet(Frame): tab_row = Frame(self) tab_row.pack(side=TOP, fill=X, expand=0) - tab_row.tab_set = self self._tab_rows.append(tab_row) for tab_name in tab_names: - def tab_command(select_command=self.select_command, - tab_name=tab_name): - return select_command(tab_name) - tab = TabBarSet.TabButton(tab_row, tab_name, tab_command) + tab = TabSet.TabButton(tab_name, self.select_command, + tab_row, self) if expand_tabs: tab.pack(side=LEFT, fill=X, expand=True) else: @@ -126,6 +123,7 @@ class TabBarSet(Frame): self._tabs[tab_name] = tab self._tab2row[tab] = tab_row + # tab is the last one created in the above loop tab.is_last_in_row = True def _reset_tab_rows(self): @@ -158,8 +156,9 @@ class TabBarSet(Frame): # calculate the required number of rows n_rows = (len(self._tab_names) - 1) // self.max_tabs_per_row + 1 - i = 0 + # not expanding the tabs with more than one row is very ugly expand_tabs = self.expand_tabs or n_rows > 1 + i = 0 # index in self._tab_names for row_index in range(n_rows): # calculate required number of tabs in this row n_tabs = (len(self._tab_names) - i - 1) // (n_rows - row_index) + 1 @@ -169,47 +168,60 @@ class TabBarSet(Frame): # re-select selected tab so it is properly displayed selected = self._selected_tab - self.select_tab(None) + self.set_selected_tab(None) if selected in self._tab_names: - self.select_tab(selected) + self.set_selected_tab(selected) class TabButton(Frame): """A simple tab-like widget.""" bw = 2 # borderwidth - def __init__(self, tab_row, name, command): + def __init__(self, name, select_command, tab_row, tab_set): """Constructor arguments: name -- The tab's name, which will appear in its button. - command -- The command to be called upon selection of the tab. It - is called with the tab's name as an argument. + select_command -- The command to be called upon selection of the + tab. It is called with the tab's name as an argument. """ - Frame.__init__(self, tab_row, borderwidth=self.bw) - self.button = Radiobutton(self, text=name, command=command, + Frame.__init__(self, tab_row, borderwidth=self.bw, relief=RAISED) + + self.name = name + self.select_command = select_command + self.tab_set = tab_set + self.is_last_in_row = False + + self.button = Radiobutton( + self, text=name, command=self._select_event, padx=5, pady=1, takefocus=FALSE, indicatoron=FALSE, highlightthickness=0, selectcolor='', borderwidth=0) self.button.pack(side=LEFT, fill=X, expand=True) - self.tab_set = tab_row.tab_set - - self.is_last_in_row = False - self._init_masks() self.set_normal() + def _select_event(self, *args): + """Event handler for tab selection. + + With TabbedPageSet, this calls TabbedPageSet.change_page, so that + selecting a tab changes the page. + + Note that this does -not- call set_selected -- it will be called by + TabSet.set_selected_tab, which should be called when whatever the + tabs are related to changes. + + """ + self.select_command(self.name) + return + def set_selected(self): """Assume selected look""" - for widget in self, self.mskl.ml, self.mskr.mr: - widget.config(relief=RAISED) self._place_masks(selected=True) def set_normal(self): """Assume normal look""" - for widget in self, self.mskl.ml, self.mskr.mr: - widget.config(relief=RAISED) self._place_masks(selected=False) def _init_masks(self): @@ -351,8 +363,8 @@ class TabbedPageSet(Frame): and first active page. If page_names is None or empty, the TabbedPageSet will be initialized empty. - n_rows, max_tabs_per_row -- Parameters for the TabBarSet which will - manage the tabs. See TabBarSet's docs for details. + n_rows, max_tabs_per_row -- Parameters for the TabSet which will + manage the tabs. See TabSet's docs for details. page_class -- Pages can be shown/hidden using three mechanisms: @@ -372,7 +384,7 @@ class TabbedPageSet(Frame): TabbedPageSet to resize when the page is changed. """ - Frame.__init__(self, parent, kw) + Frame.__init__(self, parent, **kw) self.page_class = page_class self.pages = {} @@ -390,9 +402,9 @@ class TabbedPageSet(Frame): self.pages_frame.rowconfigure(0, weight=1) # the order of the following commands is important - self._tab_set = TabBarSet(self, self.change_page, n_rows=n_rows, - max_tabs_per_row=max_tabs_per_row, - expand_tabs=expand_tabs) + self._tab_set = TabSet(self, self.change_page, n_rows=n_rows, + max_tabs_per_row=max_tabs_per_row, + expand_tabs=expand_tabs) if page_names: for name in page_names: self.add_page(name) @@ -453,7 +465,7 @@ class TabbedPageSet(Frame): self._current_page = page_name self.pages[page_name]._show() - self._tab_set.select_tab(page_name) + self._tab_set.set_selected_tab(page_name) if __name__ == '__main__': # test dialog diff --git a/Lib/idlelib/tabpage.py b/Lib/idlelib/tabpage.py deleted file mode 100644 index 105ef9093f9..00000000000 --- a/Lib/idlelib/tabpage.py +++ /dev/null @@ -1,113 +0,0 @@ -""" -a couple of classes for implementing partial tabbed-page like behaviour -""" - -from Tkinter import * - -class InvalidTabPage(Exception): pass -class AlreadyExists(Exception): pass - -class PageTab(Frame): - """ - a 'page tab' like framed button - """ - def __init__(self,parent): - Frame.__init__(self, parent,borderwidth=2,relief=RIDGE) - self.button=Radiobutton(self,padx=5,pady=5,takefocus=FALSE, - indicatoron=FALSE,highlightthickness=0, - borderwidth=0,selectcolor=self.cget('bg')) - self.button.pack() - -class TabPageSet(Frame): - """ - a set of 'pages' with TabButtons for controlling their display - """ - def __init__(self,parent,pageNames=[],**kw): - """ - pageNames - a list of strings, each string will be the dictionary key - to a page's data, and the name displayed on the page's tab. Should be - specified in desired page order. The first page will be the default - and first active page. - """ - Frame.__init__(self, parent, kw) - self.grid_location(0,0) - self.columnconfigure(0,weight=1) - self.rowconfigure(1,weight=1) - self.tabBar=Frame(self) - self.tabBar.grid(row=0,column=0,sticky=EW) - self.activePage=StringVar(self) - self.defaultPage='' - self.pages={} - for name in pageNames: - self.AddPage(name) - - def ChangePage(self,pageName=None): - if pageName: - if pageName in self.pages: - self.activePage.set(pageName) - else: - raise InvalidTabPage('Invalid TabPage Name') - ## pop up the active 'tab' only - for page in self.pages: - self.pages[page]['tab'].config(relief=RIDGE) - self.pages[self.GetActivePage()]['tab'].config(relief=RAISED) - ## switch page - self.pages[self.GetActivePage()]['page'].lift() - - def GetActivePage(self): - return self.activePage.get() - - def AddPage(self,pageName): - if pageName in self.pages.keys(): - raise AlreadyExists('TabPage Name Already Exists') - self.pages[pageName]={'tab':PageTab(self.tabBar), - 'page':Frame(self,borderwidth=2,relief=RAISED)} - self.pages[pageName]['tab'].button.config(text=pageName, - command=self.ChangePage,variable=self.activePage, - value=pageName) - self.pages[pageName]['tab'].pack(side=LEFT) - self.pages[pageName]['page'].grid(row=1,column=0,sticky=NSEW) - if len(self.pages)==1: # adding first page - self.defaultPage=pageName - self.activePage.set(self.defaultPage) - self.ChangePage() - - def RemovePage(self,pageName): - if not pageName in self.pages: - raise InvalidTabPage('Invalid TabPage Name') - self.pages[pageName]['tab'].pack_forget() - self.pages[pageName]['page'].grid_forget() - self.pages[pageName]['tab'].destroy() - self.pages[pageName]['page'].destroy() - del(self.pages[pageName]) - # handle removing last remaining, or default, or active page - if not self.pages: # removed last remaining page - self.defaultPage='' - return - if pageName==self.defaultPage: # set a new default page - self.defaultPage=\ - self.tabBar.winfo_children()[0].button.cget('text') - if pageName==self.GetActivePage(): # set a new active page - self.activePage.set(self.defaultPage) - self.ChangePage() - -if __name__ == '__main__': - #test dialog - root=Tk() - tabPage=TabPageSet(root,pageNames=['Foobar','Baz']) - tabPage.pack(expand=TRUE,fill=BOTH) - Label(tabPage.pages['Foobar']['page'],text='Foo',pady=20).pack() - Label(tabPage.pages['Foobar']['page'],text='Bar',pady=20).pack() - Label(tabPage.pages['Baz']['page'],text='Baz').pack() - entryPgName=Entry(root) - buttonAdd=Button(root,text='Add Page', - command=lambda:tabPage.AddPage(entryPgName.get())) - buttonRemove=Button(root,text='Remove Page', - command=lambda:tabPage.RemovePage(entryPgName.get())) - labelPgName=Label(root,text='name of page to add/remove:') - buttonAdd.pack(padx=5,pady=5) - buttonRemove.pack(padx=5,pady=5) - labelPgName.pack(padx=5) - entryPgName.pack(padx=5) - tabPage.ChangePage() - root.mainloop() diff --git a/Lib/test/test_deque.py b/Lib/test/test_deque.py index 890378ebe13..12f77a97a1c 100644 --- a/Lib/test/test_deque.py +++ b/Lib/test/test_deque.py @@ -29,8 +29,8 @@ class MutateCmp: class TestBasic(unittest.TestCase): def test_basics(self): - d = deque(range(100)) - d.__init__(range(100, 200)) + d = deque(range(-5125, -5000)) + d.__init__(range(200)) for i in range(200, 400): d.append(i) for i in reversed(range(-200, 0)): @@ -433,8 +433,8 @@ class DequeWithBadIter(deque): class TestSubclass(unittest.TestCase): def test_basics(self): - d = Deque(range(100)) - d.__init__(range(100, 200)) + d = Deque(range(25)) + d.__init__(range(200)) for i in range(200, 400): d.append(i) for i in reversed(range(-200, 0)): diff --git a/Lib/test/test_urlparse.py b/Lib/test/test_urlparse.py index 5cee4584c2b..de08613846c 100644 --- a/Lib/test/test_urlparse.py +++ b/Lib/test/test_urlparse.py @@ -287,7 +287,6 @@ class UrlParseTestCase(unittest.TestCase): self.assertEqual(p.port, None) self.assertEqual(p.geturl(), uri) - def test_main(): test_support.run_unittest(UrlParseTestCase) diff --git a/Lib/urlparse.py b/Lib/urlparse.py index e5de53ae8a0..431771405dc 100644 --- a/Lib/urlparse.py +++ b/Lib/urlparse.py @@ -184,7 +184,7 @@ def urlsplit(url, scheme='', allow_fragments=True): Note that we don't break the components up in smaller bits (e.g. netloc is a single string) and we don't expand % escapes.""" allow_fragments = bool(allow_fragments) - key = url, scheme, allow_fragments + key = url, scheme, allow_fragments, type(url), type(scheme) cached = _parse_cache.get(key, None) if cached: return cached diff --git a/Misc/ACKS b/Misc/ACKS index 17ef503ff0e..a4febfdab41 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -168,6 +168,7 @@ Yves Dionne Daniel Dittmar Walter Dörwald Jaromir Dolecek +Ismail Donmez Dima Dorfman Cesar Douady Dean Draayer diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c index 20c0774065a..0d1df5faa58 100644 --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -784,6 +784,7 @@ deque_init(dequeobject *deque, PyObject *args, PyObject *kwdargs) } } deque->maxlen = maxlen; + deque_clear(deque); if (iterable != NULL) { PyObject *rv = deque_extend(deque, iterable); if (rv == NULL) diff --git a/Modules/_sqlite/statement.c b/Modules/_sqlite/statement.c index f81e64299ff..126ba6f7261 100644 --- a/Modules/_sqlite/statement.c +++ b/Modules/_sqlite/statement.c @@ -231,7 +231,11 @@ int pysqlite_statement_recompile(pysqlite_Statement* self, PyObject* params) */ #ifdef SQLITE_VERSION_NUMBER #if SQLITE_VERSION_NUMBER >= 3002002 - (void)sqlite3_transfer_bindings(self->st, new_st); + /* The check for the number of parameters is necessary to not trigger a + * bug in certain SQLite versions (experienced in 3.2.8 and 3.3.4). */ + if (sqlite3_bind_parameter_count(self->st) > 0) { + (void)sqlite3_transfer_bindings(self->st, new_st); + } #endif #else statement_bind_parameters(self, params); diff --git a/Modules/_sqlite/util.c b/Modules/_sqlite/util.c index b70297b9277..5e78d588460 100644 --- a/Modules/_sqlite/util.c +++ b/Modules/_sqlite/util.c @@ -28,9 +28,15 @@ int _sqlite_step_with_busyhandler(sqlite3_stmt* statement, pysqlite_Connection* { int rc; - Py_BEGIN_ALLOW_THREADS - rc = sqlite3_step(statement); - Py_END_ALLOW_THREADS + if (statement == NULL) { + /* this is a workaround for SQLite 3.5 and later. it now apparently + * returns NULL for "no-operation" statements */ + rc = SQLITE_OK; + } else { + Py_BEGIN_ALLOW_THREADS + rc = sqlite3_step(statement); + Py_END_ALLOW_THREADS + } return rc; } diff --git a/Modules/xxmodule.c b/Modules/xxmodule.c index 6b998b13fe6..5c371fb60ee 100644 --- a/Modules/xxmodule.c +++ b/Modules/xxmodule.c @@ -349,7 +349,7 @@ initxx(void) Str_Type.tp_base = &PyUnicode_Type; /* Finalize the type object including setting type of the new type - * object; doing it here is required for portability, too. /* + * object; doing it here is required for portability, too. */ if (PyType_Ready(&Xxo_Type) < 0) return; diff --git a/configure b/configure index eb0db1839dd..08746a1b421 100755 --- a/configure +++ b/configure @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in Revision: 59247 . +# From configure.in Revision: 59484 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.61 for python 3.0. # @@ -4403,6 +4403,10 @@ then if test "$CC" != 'g++' ; then STRICT_PROTO="-Wstrict-prototypes" fi + # For gcc 4.x we need to use -fwrapv so lets check if its supported + if "$CC" -v --help 2>/dev/null |grep -- -fwrapv > /dev/null; then + WRAP="-fwrapv" + fi case $ac_cv_prog_cc_g in yes) if test "$Py_DEBUG" = 'true' ; then @@ -4410,7 +4414,7 @@ then # debug builds. OPT="-g -Wall $STRICT_PROTO" else - OPT="-g -O3 -Wall $STRICT_PROTO" + OPT="-g $WRAP -O3 -Wall $STRICT_PROTO" fi ;; *) diff --git a/configure.in b/configure.in index 2e7ebae87f4..c6eabada8d5 100644 --- a/configure.in +++ b/configure.in @@ -732,6 +732,10 @@ then if test "$CC" != 'g++' ; then STRICT_PROTO="-Wstrict-prototypes" fi + # For gcc 4.x we need to use -fwrapv so lets check if its supported + if "$CC" -v --help 2>/dev/null |grep -- -fwrapv > /dev/null; then + WRAP="-fwrapv" + fi case $ac_cv_prog_cc_g in yes) if test "$Py_DEBUG" = 'true' ; then @@ -739,7 +743,7 @@ then # debug builds. OPT="-g -Wall $STRICT_PROTO" else - OPT="-g -O3 -Wall $STRICT_PROTO" + OPT="-g $WRAP -O3 -Wall $STRICT_PROTO" fi ;; *)