Unsorted Notes

Great Flamingo



sudo dnf install -y hub

Download a pull request:

git checkout -b pr104
git am -3 https://github.com/python/cpython/pull/104


  • Add ?w=1 in a pull request to ignore whitespace changes

Debug methodolody

The first step is to debug is to find a reliable or highly reliable scenario to reproduce the bug. In the worst case, it can take several days to get such reliable scenario :-/

Code bisection

If a bug occurred recently and it didn’t exist in previous versions, it’s called a regression and it should be easier to debug. If the code is tracked by a Version Control System (VCS like Git or Mercurial), you can “bisect” the source code history to find the changeset introducing the bug. Git and Mercurial have a builtin bisect command:

The best is to have a reliable script reproducing the bug which returns 0 on success (test succeeded, no bug) or non-zero exit code (test failed, bug). Example of shell script:

make || exit 125
./python -m test -v test_sys

make || exit 125 fails with the exit code 125 if the compilation fails. It’s useful to skip a revision if the project cannot be compiled at this revision. hg bisect and git bisect skip a revision if the command exit code is 125.

The idea is similar to dichotomy: reduce the quantity of code that have to be read to find a bug.


Dichotomy or “divide to conquer” ;-)

The idea of the “dichotomy” methodology is to reduce the quantity of executed code before the bug is triggered. To reduce the quantity of code, you can:

  • comment function calls
  • disable most features: turn off logging, turn off audio and/or video playback, etc.
  • comment large partion of code

The goal is not the reduce the code to a single line of code reproducing the bug. The goal is the reduce the quantity of code that should be read manually to find the bug.

The debug method can sometimes take several hours, so it’s nice to have “milestones”: backup points where the bug can still be reproduced. If you use a Version Control System (VCS like Git or Mercurial), you can use local commits (ex: create a local branch in git). Don’t worry of the change content or the commit message, plop is a great commit message for such changes :-) These milestones are important to be able to go backward if the bug cannot be reproduced anymore when you disabled too much code and features.

Add printf

Debuggers are great, convenient and powerful. But. Sometimes, a bug cannot be reproduce in the debugger for an unknown reason, or the control flow is too complex to run the application in a debugger. For example, it’s hard to debug an event based application where a single logical “function” (or coroutine) is splitted into several small callbacks.

In such case, an easy method is to add “print” calls (ex: printf() in C or print in Python) in the code to “dump” the control flow, to try to bisect manually the code. Example of a Python function body:

return func3(c)

Add print calls to see where the bug is triggered:

res = func3(c)
return res

The last instruction was splitted into two instructions to see if the bug occurs before the call to func3() or after.

If you see func1 and func2 but not func3, the bug occurred after the line print("func2") and before print("func3"), so the bug occurred on the func2() call.

You can now remove the print("func1") line (to have a less verbose output), and continue to add print calls inside the func2() function. Iterate until you have a few functions to read to find the bug. It’s common to get the failing line in less than 5 iterations, the technic looks very basic, but it’s fast if the scenario to reproduce the bug is reliable.

Debugging can be painful, so don’t hesitate to make it more funny by using less boring messages than func1 or func3 :-) I’m using:

  • LA (here in french)
  • 1
  • 1b
  • pouet
  • @@@@@@@@@@@
  • etc.


If the source code is not tracked by a Version Control System (VCS like Git or Mercurial), don’t forget to create backup of files to easily remove these print calls when the bug is identified.

vim for developer

In these examples, I’m using Mercurial with the command “hg”. To use git, just replace “hg” with “git”. I prefer the graphical editor gvim. To use the console version, replace “gvim” with “vim”.

View differences:

hg diff | gvim -


  • a/asyncio/events.py: to open the file, delete a\, put the cursor on the file type, type vs for a vertial split, and type gf (goto file) to open the file
  • %bd: close all buffers


Search a package without updating yum cache:

yum search -C pattern

Which package provides the program route?

$ rpm -qf $(which route)

Or if the package is not installed:

$ yum whatprovides route
net-tools-2.0-0.15.20131119git.fc20.x86_64 : Basic networking tools
Nom de fichier: /usr/sbin/route

Listing the files in a package:

rpm -ql mongodb-server

Install dependencies to build the package digikam:

yum-builddep digikam

Rebuild a package: Fedora Source RPM.

Unpack RPM

Unpack file.rpm in a new dir/ subdirectory:

mkdir dir
cp file.rpm dir/
cd dir
rpm2cpio file.rpm | cpio -idmv



  • obj.__iter__()
  • obj.__getitem__()


  • obj.__nonzero__()
  • obj.__len__() != 0

item in obj:

  • obj.__contains__()
  • list-like: obj.__getitem__(0), obj.__getitem__(1) until obj.__getitem__(int) returns item!



I’m not convinced that it’s possible to give libdbus well-designed multi-threading without a redesign and API break, at which point you might as well use GDBus instead.


Remove latest commit

git reset --hard HEAD~1

List tags containing a specific commit

nova$ git tag --contains 94a3b83f9f1fd52a78b9d49b32ddfae40182f852

Remote branches

  • List remote branches: git branch -r

  • Create a new branch fix_1369426_icehouse tracking the remote branch origin/stable/icehouse:

    git branch --track fix_1369426_icehouse origin/stable/icehouse
  • (Track and) Pull a remote branch:

    git branch --track NAME_REMOTE_BRANCH
    git fetch --all   # or: git pull --all

Send email

First install git send-email. On Fedora:

yum install -y git-email

Generate a .patch file for a single commit:

git format-patch origin/master

Generate a patch serie for multiple commits:

git format-patch origin/master --cover-letter

Now modify 0000-cover-letter.patch: replace *** BLURB HERE ***. By default, patches create a thread on a mailing list: [PATCH 0/n] is the top message, [PATCH 1/n], [PATCH 2/n], etc. are replied to the top message. See Message-Id and In-Reply-To headers in emails.

To generate a version 2 of a patch (use [PATCH v2] subject prefix instead of [PATCH]):

git format-patch origin/master --subject-prefix 'PATCH v2'

Send patches:

git send-email --to=EMAIL --suppress-cc=all *.patch

For your first try, just send emails to yourself ;-)

Shell script

  • bash8: A pep8 equivalent for bash scripts
  • checkbashisms: static analysis tool for shell scripts. It looks for particular patterns which indicate a script might be relying on /bin/sh being bash.
  • shellcheck: static analysis and linting tool for sh/bash scripts

Python zero copy


offset = 0
view = memoryview(large_data)
while True:
    chunk = view[offset:offset + 4096]
    offset += file.write(chunk)

This copy creates views on large_data without copying bytes, no bytes is copied in memory.


MySQL client:

SELECT * FROM instances WHERE uuid='f12dca29-c51e-4f94-be5a-8aba5dd3c952' \G


bisect with a command

Shell script cmd.sh:

set -e -x
./python script.py

where script.py is the script to reproduce the bug.

Cleanup everything:

hg bisect --reset
hg update -C

We know that the most recent version is bad (./cmd fails):

# cmd.sh failed
hg bisect -b

Find a good revision using a date:

hg up -r "branch(default) and date('May 2015')"
# it's still failing, take an older date
hg up -r "branch(default) and date('Jan 2015')"
# iterate until the test pass
hg bisect -g

Ok, we have a good and a bad revision, and a script to automate the bisection:

hg bisect --command ./cmd.sh
# enjoy watching your computer working for you

cannot edit immutable changeset: xxx

You can force the phase of a changeset back to draft like so:

hg phase -d -f <changeset_id>

Only do that for private changes!

Find tags containing a specific changeset

Let’s say that you want to check which versions contains the _FUTURE_CLASSES variable:

$ grep '_FUTURE_CLASSES =' trollius/*.py
trollius/futures.py:    _FUTURE_CLASSES = (Future, events.asyncio.Future)
trollius/futures.py:    _FUTURE_CLASSES = Future

$ hg blame trollius/futures.py|grep '_FUTURE_CLASSES ='
1712:     _FUTURE_CLASSES = (Future, events.asyncio.Future)
1688:     _FUTURE_CLASSES = Future

$ hg log -r 1688 --template '{date|isodate}\n'
2014-07-25 10:05 +0200

Ok, so the _FUTURE_CLASSES was added by the changeset 1688 which was made the 2014-07-25. We pick the oldest changeset, 1712 was probably a fix.

Find the tags which contains the changeset 1688:

$ hg log -r "reverse(descendants(1688)) and tag()" --template "{tags}\t{rev}:{node|short}\n"
trollius-1.0.2  1767:41ac07cd2d03
trollius-1.0.1  1738:83e574a42e16

$ hg log -r trollius-1.0.1 --template '{date|isodate}\n'
2014-07-30 17:45 +0200
$ hg log -r trollius-1.0.2 --template '{date|isodate}\n'
2014-10-02 16:47 +0200

The _FUTURE_CLASSES was introduced in trollius-1.0.1 which was released the 2014-07-30. The following release trollius-1.0.2 (2014-10-02) also contains it, which is expected since trollius-1.0.2 is based on trollius-1.0.1.

Check versions:

$ hg up trollius-1.0.1
$ grep '_FUTURE_CLASSES =' trollius/*.py
trollius/futures.py:    _FUTURE_CLASSES = (Future, events.asyncio.Future)
trollius/futures.py:    _FUTURE_CLASSES = Future

$ hg up trollius-1.0
$ grep '_FUTURE_CLASSES =' trollius/*.py
trollius/tasks.py:    _FUTURE_CLASSES = (futures.Future, asyncio.Future)
trollius/tasks.py:    _FUTURE_CLASSES = futures.Future

Ok, so in fact the variable was moved from the Python module trollius.tasks to the modle trollius.futures between versions 1.0 and 1.0.1.

abort: can’t rebase public changeset fb6b735060b5


abort: can't rebase public changeset fb6b735060b5
(see "hg help phases" for details)

Share files files from Linux to OSX

I tried NFS: issues with non-ASCII characters, issue with Unicode NFC normalization on OS X. Since OS X 10.9, the only way is to use the command line to pass the option -o nfc to mount -t nfs ....

I tried Samba: well, it’s not easy. Let’s say that the directory to share is /data.

Prepare permissions, readable by everybody, UNIX and SELinux permissions:

sudo find  /data -type f -print0|xargs -0 chmod 644
sudo find -type d -print0|xargs -0 chmod 755
sudo semanage fcontext -a -t samba_share_t "/data(/.*)?"
sudo restorecon -R -v data/

Install Samba:

sudo yum install samba samba-common samba-client cups-lib system-config-samba

Use system-config-samba to share /data:

  • run sudo system-config-samba
  • add /data directory as public and make it readable for everybody
  • add a Windows user which is binded to your user (Preference, Samba users)

Start Samba server and run it at boot:

sudo systemctl start smb.service
sudo systemctl start nmb.service
sudo systemctl enable smb.service
sudo systemctl enable nmb.service

Mac OS X:

  • Finder, Go, Access server: use smb:// URL
  • Type the user and password
  • Enjoy!

Very good tutorial for Fedora 20: How to enable samba share for a specific directory - Fedora 20.


Install bash:

$ su -
# export PKG_PATH=ftp://ftp.openbsd.org/pub/OpenBSD/5.6/packages/amd64/
# pkg_add -r bash
$ chsh -s /usr/local/bin/bash


  • libuv has a good support of IOCP
  • Twisted 14 has an IOCP reactor (twisted.internet.iocpreactor). Since 2008, it supports SSL. (reactor is “nearly complete”?)
  • libevent 2.0.21 suports IOCP:
    • AcceptEx
    • ConnectEx
    • GetAcceptExSockaddrs
  • libev 4.19 does not support IOCP. The source code has some mentions of IOCP, but no implementation: “It’s vestigates of an old experiment to see if it could be done in a different way.” (State of IOCP work)

Windows ACP: Asynchronous Procedure Calls.

UnicodeDecodeError and pip

If you get a UnicodeDecodeError when installing a package with pip:

  • The first workaround is to ensure that your locale encoding is UTF-8, not ASCII (don’t use LANG=C)
  • Use a recent version of pip (6.0, or at least 1.5.x)

asynchronous file system I/O?

No. Each operating system provides its own set of functions, with limitations and not well supported.

P2P clients usually run file system I/O in threads.


list servers

Find the name of the systemd unit for MariaDB or RabbitMQ server.

List all installed services, including disabled services, and search for “maria”:

systemctl list-unit-files --type=service | grep maria

Alternative if you know the package:

$ rpm -ql mariadb-server|grep service

List enabled services:

systemctl list-units

Note: it looks like “list-units” doesn’t show mariadb.service, probably because it is disabled (not started at boot).

system logs (syslogs), journald

  • Show syslog from the most recent to the oldest logs: journalctl --reverse
  • Show all logs since the last boot: journalctl -b 0
  • List boots: journalctl --list-boots
  • tail -f /var/log/syslog: journalctl -f
  • tail -f /var/log/syslog but only for apache: journalctl -u apache.service -f


Install PostgreSQL server on Fedora 21. Type as root:

yum install postgresql-server
postgresql-setup initdb

Modify /var/lib/pgsql/data/postgresql.conf to accept connections from network, replace:

#listen_addresses = 'localhost'         # what IP address(es) to listen on;
max_connections = 100                  # (change requires restart)


listen_addresses = '*'
max_connections = 1000                  # (change requires restart)

Modify /var/lib/pgsql/data/pg_hba.conf to allow login using a password from network, replace:

host    all             all               ident


host    all             all             md5

Start PostgreSQL:

systemctl start postgresql

Switch to the postgres user (sudo -u postgres -H -s), open the psql client (psql) and type:

CREATE USER bigdata;


Install dependencies:

sudo yum install mariadb-devel mongodb-server rabbitmq-server

Start MongoDB server:

sudo systemctl start mongod
sudo systemctl start rabbitmq-server

Copy Ceilometer config:

tox -e genconfig
sudo mkdir /etc/ceilometer
sudo cp -R etc/ceilometer/ /etc/ceilometer/

Configure Ceilometer database:

connection = mongodb://

Create the DB:


Run collector in debug:

ceilometer-collector -d

Send a sample:

ceilometer-send-sample --sample-name name --sample-resource resource

Show meters in MongoDB:

$ mongo
> use ceilometer
> db.meter.find()

Note: If you get the error “mongo: symbol lookup error: mongo: undefined symbol: _ZN2v86LockerC1EPNS_7IsolateE” when running the “mongo” command, see the bug mongo client lookup error. The bug occurs if you installed the package “v8” from the Chromium repository.

Rebuild a Fedora package

If you get a .src.rpm package, you can rebuild it with:

rpmbuild --rebuild wrk-3.1.0-1.fc21.src.rpm

Operating systems

Mac OS X versions:

Mac OS X Name Darwin Version Release Year
Mac OS X 10.11 El Capitan 15.x 2015
Mac OS X 10.10 Yosemite 14.x 2014
Mac OS X 10.9 Mavericks 13.x 2013
Mac OS X 10.8 Mountain Lion 12.x 2012
Mac OS X 10.7 Lion 11.x 2010
Mac OS X 10.6 Snow Leopard 10.x 2008
Mac OS X 10.5 Leopard 9.x 2006
Mac OS X 10.4 Tiger 8.x 2004
  • Microsoft Windows versions:
    • Windows 10: (under development)
    • Windows 8.1: 2013
    • Windows 8: 2012
    • Windows 7: 2009
    • Windows Vista: 2007
    • Windows XP: 2001
  • Linux kernel versions:
    • 4.0: 2015 (under development)
    • 3.0: 2011
    • 2.6: 2003
    • 2.4: 2001
  • Ubuntu releases:
    • 16.10: Yakkety Yak (not released yet, scheduled for 2016-10-20)
    • 16.04 LTS: Xenial Xerus, 2016-04-21
    • 15.10: Wily Werewolf, 2015-10-22
    • 15.04: Vivid, 2015-04
    • 14.10: Utopic, 2014-10
    • 14.04 LTS: Trusty, 2014-04
    • 12.04 LTS: Precise, 2012-04
  • Fedora releases:
    • Fedora 24: 2016-06-21
    • Fedora 23: 2015-11-03
    • Fedora 22: 2015-05-26
    • Fedora 21: 2014-12
    • Fedora 20: 2013-12, Heisenbug
    • Fedora 19: 2013-07, Schrödinger’s Cat
  • FreeBSD releases:
    • FreeBSD 10: 2014-01
    • FreeBSD 9: 2012-01
    • FreeBSD 8.1: 2010-07
    • FreeBSD 7: 2008-02
    • FreeBSD 6.2: 2007-01



  • Write a scenario to reproduce the memory leak. The ideal is a scenario taking only a few minutes
  • Enable tracemalloc and replay the scenario
  • Take regulary tracemalloc snapshots
  • Compare snapshots
  • Enjoy!

If your application only uses Python memory allocators, tracemalloc must show your the exact memory usage counting every single bytes.

If a C extensions uses other memory allocators like malloc(), tracemalloc is unable to trace these allocations.

If the application allocates a lot of memory to process some data (memory peak) and then releases almost all memory, except a few small objects, the memory may become fragmented. For example, the application only uses 20 MB whereas the operating system see 24 or 30 MB.

See also:

Programming advices

  • Coding style: 80 columns, PEP 7 for C, PEP 8 for Python
  • Avoid variable globals
  • Signal handlers: only use signal-safe functions

Python environment markers


pip supports environment markers in requirements since pip 6.0, example of requirement:

futures; python_version < '3.2'

pip uses ”;” (colon) separator but requires ”; ” (colon, space) if the requirement uses an URL. A space is added for readability (spaces are ignored).

Environment markers in extra requirements of setup.cfg:

test =
    futures :python_version < '3.2'

The separator is the ”:” (colon), space is only used for readability (spaces are ignored).

Environment markers in extra requirements of setup.py:

expected_requirements = {
    "test:python_version < '3.2'": ['futures'],
    "test": ['six']

pip issues

  • Upgrading pip3 replaces /usr/bin/pip with the Python 3 pip
  • Once, I got two dist-info directories for pip (ls /usr/lib*/python3.4/site-packages/pip-*.dist-info -d) which broke python3 -m venv: ensurepip was unable to find the system pip and Fedora doesn’t include bundled wheel packages of ensurepip in the python3-libs package
  • With pip 7.0 and newer, pip3 install Routes; pip2 install Routes installs the Python 3 version of Routes on Python 2. pip3 creates a wheel package using 2to3 but Routes 2.1 announces universal wheel support which is wrong.
  • Wheel caching doesn’t work on pip 7.0, 7.0.1 and 7.0.2. It was fixed in pip 7.0.3.

pbr issues

If running tox -e py27 fails the following error, replace 2014.1.4 with 2014.1.5 in setup.cfg:

ValueError: git history requires a target version of
pbr.version.SemanticVersion(2014.1.5), but target version is
pbr.version.SemanticVersion(2014.1.4) error in setup command: Error parsing
/home/haypo/prog/redhat/openstack-nova/setup.cfg: ValueError: git history
requires a target version of pbr.version.SemanticVersion(2014.1.5), but
target version is pbr.version.SemanticVersion(2014.1.4)


Local copy with progress bar and handle sparse files:

rsync -Sav --progress /mnt/vm/images/ /var/lib/libvirt/images/


Checking for new messages in other folders - Thunderbird.

Set mail.server.default.check_all_folders_for_new=true in advanced settings (Edit > Preference > Advanced > General tab > Config editor).


Configure Gnome-Terminal to select a full URL double-click:

dconf write /org/gnome/terminal/legacy/profiles:/:${Profile_ID}/word-char-exceptions '@ms "-,.;/?%&#_=+@~·:"'

Replace ${Profile_ID} with the profile identifier. To get it:

$ gsettings get org.gnome.Terminal.ProfilesList list


dconf write /org/gnome/terminal/legacy/profiles:/:b1dcc9dd-5262-4d8d-a863-c897e6d979b9/word-char-exceptions '@ms "-,.;/?%&#_=+@~·:"'

It looks like you don’t have to restart Gnome-Terminal.



Samsung S2, delete logs on internal storage:

  • dial *#9900#
  • click on: “Delete dumpstate/logcat”

Free space on the 16 GB SD card:

  • install CCleaner
  • Free space using CCleaner

Python platforms

Platform sys.platform os.name
AIX aix3, aix4 posix
Cygwin cygwin ?
FreeBSD freebsd5, freebsd6, ... posix
Java java (with a suffix?) ?
Linux linux on Python 3, linux2 on Python 2 (*) posix
Mac OS X darwin posix
NetBSD netbsd (with a suffix?) posix
OpenBSD openbsd5 posix
Solaris sunos5 posix
Windows win32 nt

sys.platform comes from the MACHDEP variable which is built by the configure script using:

  • uname -s command output converted to lowercase, with some special rules (ex: linux3 is replaced with linux on Python 3)
  • uname -r command output (or uname -v on AIX, UnixWare or OpenUNIX)
  • $host variable (./configure --host=xxx parameter) when cross-compiling

(*) sys.platform was also linux3 on old versions of Python 2.6 and Python 2.7 with Linux kernel 3.x.

Write a core dump in disk

Fedora catchs fatal errors like segmentation faults with its application ABRT. To develop, sometimes it helps to get a core dump. It’s possible to write a core dump on disk with:

ulimit -c unlimited
sudo bash -c "echo '%e-%p.core' > /proc/sys/kernel/core_pattern"


$ python3
>>> import faulthandler; faulthandler._sigsegv()
Erreur de segmentation (core dumped)
$ ls *core*


Put a breakpoint:

  • hit ‘m’, search ‘test_api’ to open glance.tests.unit.test_api

Gtk windows border (Gnome 3)

Add a light border around windows to see borders of terminal. Edit ~/.config/gtk-3.0/gtk.css:

.window-frame {
    border: 3px grey;

To disable shadow, add box-shadow: none;.



dnf install -y rabbitmq-server
vim /etc/rabbitmq/rabbitmq.config
# in "{rabbit," uncomment:
#    {loopback_users, []}
# (no trailing comma ",")
sudo systemctl restart rabbitmq-server
sudo systemctl status rabbitmq-server
sudo rabbitmqctl change_password guest password


To install Fedora:

Linux perf


perf stat command


perf record -o trace.data -g command
# -g to record call graph: you may recompile your code with -fno-omit-frame-pointer


perf report -i trace.data





PYTHONHASHSEED=0 taskset -c 7 valgrind --dsymutil=yes --tool=callgrind --callgrind-out-file=callgrind.out.slow2.25 --dump-instr=yes --collect-jumps=yes ./slow ../benchmarks/performance/bm_call_simple.py -n 50 --timer perf_counter
  • Record at instruction level (not function level)
  • Record conditional jumps

Open with Kcachegrind:

kcachegrind callgrind.out.slow.25.


callgrind_annotate callgrind.out.slow.25


Record traces:

PYTHONHASHSEED=0 time taskset -c 2 valgrind --dsymutil=yes --tool=cachegrind --cachegrind-out-file=cachegrind.out.fast.25 ./fast ../benchmarks/performance/bm_call_simple.py -n 25 --timer perf_counter

OpenStack openstack_citest

For MySQL you can use the following commands:

mysql -u root
mysql> CREATE USER 'openstack_citest'@'localhost' IDENTIFIED BY
mysql> GRANT ALL PRIVILEGES ON * . * TO 'openstack_citest'@'localhost';




List operators of channel:

/msg ChanServ access #python-fr list

Give operator permission to someone:

/msg ChanServ flags #python-fr skyice +Aeiortv

x86_64 assembler, gdb


Stack aligned on 16 bytes boundary.

Calling convention:

  • arg1: RDI
  • arg2: RSI
  • arg3: RDX
  • arg4: RCX
  • arg5: R8
  • arg6: R9


  • TUI:

  • Stop on PyType_Ready() but only if type->tp_name is the string “_ModuleLock”:

    (gdb) b PyType_Ready
    Breakpoint 2 at 0x4faa9c: file Objects/typeobject.c, line 4980.
    (gdb) run
    Breakpoint 2, PyType_Ready (type=0x953ba0 <PyBaseObject_Type>) at Objects/typeobject.c:4980
    4980            if (type->tp_flags & Py_TPFLAGS_READY) {
    (gdb) condition 2 strcmp(type->tp_name, "_ModuleLock")==0
    (gdb) cont
    Breakpoint 2, PyType_Ready (type=0x9ecf78) at Objects/typeobject.c:4980
    4980            if (type->tp_flags & Py_TPFLAGS_READY) {
    (gdb) p type->tp_name
    $6 = 0x7ffff7f83080 "_ModuleLock"
  • Breakpoint on a value:

    (gdb) watch type->tp_init
    Hardware watchpoint 4: type->tp_init
    Hardware watchpoint 4: type->tp_init
    Old value = (initproc) 0x0
    New value = (initproc) 0x4f3e6e <object_init>
    inherit_slots (type=0x9ecf78, base=0x953ba0 <PyBaseObject_Type>) at Objects/typeobject.c:4944
  • Run until line 4988:

    (gdb) u     4899
    inherit_slots (type=0x9ecf78, base=0x953ba0 <PyBaseObject_Type>) at Objects/typeobject.c:4899