faker
faker copied to clipboard
Tab completion in interactive shell not working since Python version 3.8
Tab autocomplete in python interactive shell unavailable when using Python versions 3.9, 3.10 or 3.11.
Python documents this feature: https://docs.python.org/3.11/tutorial/interactive.html#tab-completion-and-history-editing. (Docs here are the same in all versions of Python)
Setup
- Faker version: 17.3.0
- OS: Debian GNU/Linux 11 (bullseye)
OS versions
PS C:\Users\User> docker run -it --rm python:3.8 cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 11 (bullseye)"
NAME="Debian GNU/Linux"
VERSION_ID="11"
VERSION="11 (bullseye)"
VERSION_CODENAME=bullseye
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
PS C:\Users\User> docker run -it --rm python:3.9 cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 11 (bullseye)"
NAME="Debian GNU/Linux"
VERSION_ID="11"
VERSION="11 (bullseye)"
VERSION_CODENAME=bullseye
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
PS C:\Users\User> docker run -it --rm python:3.10 cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 11 (bullseye)"
NAME="Debian GNU/Linux"
VERSION_ID="11"
VERSION="11 (bullseye)"
VERSION_CODENAME=bullseye
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
PS C:\Users\User> docker run -it --rm python:3.11 cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 11 (bullseye)"
NAME="Debian GNU/Linux"
VERSION_ID="11"
VERSION="11 (bullseye)"
VERSION_CODENAME=bullseye
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
What used to work
# pip install faker=="17.3.0"
# python
>>> import faker
>>> fake = faker.Faker()
>>> fake.
Type [TAB] once or twice and you see this:
Display all 280 possibilities? (y or n)
fake.aba( fake.generator_attrs fake.pyfloat(
fake.add_provider( fake.get_arguments( fake.pyint(
fake.address( fake.get_formatter( fake.pyiterable(
... I've removed a whole bunch for brevity's sake.
fake.free_email( fake.psv( fake.zipcode_in_state(
fake.free_email_domain( fake.pybool( fake.zipcode_plus4(
fake.future_date( fake.pydecimal(
fake.future_datetime( fake.pydict(
>>> fake.
What's broken
In Python 3.9, 3.10, and 3.11:
# pip install faker=="17.3.0"
# python
>>> import faker
>>> fake = faker.Faker()
>>> fake.
Type [TAB] once or twice and nothing happens.
I've noticed that if I start typing a letter or two, autocomplete will start to work:
>>> fake.a
fake.aba() fake.address() fake.am_pm() fake.ascii_company_email() fake.ascii_free_email()
fake.add_provider( fake.administrative_unit() fake.android_platform_token() fake.ascii_email() fake.ascii_safe_email()
>>> fake.b
fake.bank_country() fake.bban() fake.binary( fake.boolean( fake.bothify( fake.bs() fake.building_number()
>>> fake.c
fake.cache_pattern fake.city_prefix() fake.company_email() fake.country_code( fake.credit_card_security_code( fake.currency() fake.current_country_code()
fake.catch_phrase() fake.city_suffix() fake.company_suffix() fake.credit_card_expire( fake.cryptocurrency() fake.currency_code()
fake.century() fake.color( fake.coordinate( fake.credit_card_full( fake.cryptocurrency_code() fake.currency_name()
fake.chrome( fake.color_name() fake.country() fake.credit_card_number( fake.cryptocurrency_name() fake.currency_symbol(
fake.city() fake.company() fake.country_calling_code() fake.credit_card_provider( fake.csv( fake.current_country()
>>> fake.d
fake.date( fake.date_of_birth( fake.date_this_year( fake.date_time_between_dates( fake.date_time_this_year( fake.dga(
fake.date_between( fake.date_this_century( fake.date_time( fake.date_time_this_century( fake.day_of_month() fake.domain_name(
fake.date_between_dates( fake.date_this_decade( fake.date_time_ad( fake.date_time_this_decade( fake.day_of_week() fake.domain_word()
fake.date_object( fake.date_this_month( fake.date_time_between( fake.date_time_this_month( fake.del_arguments( fake.dsv(
>>> fake.e
fake.ean( fake.ean13( fake.ean8( fake.ein() fake.email(
>>> fake.e
So a workaround would be to just start typing a single letter before before hitting TAB, but I just want to see ALL attributes available at once.
Could it possibly be an issue o Python 38 that got fixed in 3.9?
Either way, I'm not sure what we could do to fix this. I'm open to any ideas.
I thought that if an object had too many attributes, that new versions of Python would not show all those attributes when you hit tab. Below I show that an object with ~17k attributes, in new version of Python, will still work as expected when you hit tab.
>>> import string
>>> Foo = type("Foo", (), {f"{a}{b}{c}":0 for a in string.ascii_lowercase for b in string.ascii_lowercase for c in string.ascii_lowercase})
>>> foo = Foo()
>>> len(dir(foo))
17602
>>> foo. <tab> # I'm not going to show the output, but all 17,602 of them appear
So why then, does tab completion not work?
Can anyone else replicate this?
I showed you how to run this in docker, so hopefully it should be easy enough to duplicate. (The issue can be demonstrated outside of docker btw)
In Ubuntu 20.04 I can't replicate it with Python3.9 installed using APT from default repositories, but Python3.10 installed from deadsnakes PPA has this problem.
Summary
-
IntelliCode and Kite-AI Auto-completion not working in VSCode.
Screenshot (Click to expand)
-
Python Docs unavailable both in VSCode IntelliCode and Kite Copilot.
Screenshots (Click to expand)
-
Auto-completion available as it should in IPython, however …
Screenshot
Environments
- Windows 10 Professional 21H2 (19044.1566)
- Miniconda3, installed via
winget.exe
- conda 4.11.0
- virutalenv 20.4.6
- Python 3.9.7
- Faker 13.0.0
- IPython 8.1.0
- Microsoft Visual Studio Code 1.65.0 (system setup)
- Kite Engine 1.2021.610.0
- VSCode Plugin Installed
- Vim Plugin Installed
Steps to reproduce
-
Setup Python 3.9 or later version
winget install Python.Python.3
-
Install the latest version of
Faker
-
Installed the latest version of Microsoft Visual Studio Code
winget install Microsoft.VisualStudioCode
-
Open an empty folder as a VSCode workspace, and create an empty
*.py
file -
Type in the following snippet
from faker import Faker fake = Faker(locale='en_US') fake.
-
Invoke auto-completion (mostly
Ctrl + Space
) after the dot, check if all available methods are listed.
Expected Behavior
- All available methods should be listed, as it's shown in IPython Console.
- Python Docs are automatically fetched from local (or remote) when cursor on any one of
Faker
's class, instance or method.
Actual Behavior
As I mentioned before in "Summary" section.
Notes
Kite Engine and IntelliCode for VSCode are enabled and ready. It's not Kite or VSCode's fault.
Screenshot (Click to expand)
![](https://user-images.githubusercontent.com/49941141/157201798-82aa16b4-41ab-475c-a9be-0a2266013c84.png)
In Ubuntu 20.04 I can't replicate it with Python3.9 installed using APT from default repositories.
I'm using Docker Desktop for Windows with WSL2 backend. I followed the steps as what @CelestialGuru did before. When I type in a few characters it CAN auto-complete for me, but if I left it empty and invoke Tab
just after the dot, nothing pop up.
Console Logs (too long, click to expand)
root@63d26b38d382:/# python
Python 3.9.10 (main, Mar 2 2022, 04:23:34)
[GCC 10.2.1 20210110] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from faker import Faker
>>> from pprint import pprint
>>> faker = Faker(locale="en_US")
>>> pprint(dir(faker))
['__annotations__',
'__class__',
'__deepcopy__',
'__delattr__',
'__dict__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattr__',
'__getattribute__',
'__getitem__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__le__',
'__lt__',
'__module__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__setstate__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__',
'_factories',
'_factory_map',
'_locales',
'_map_provider_method',
'_select_factory',
'_unique_proxy',
'_weights',
'aba',
'add_provider',
'address',
'administrative_unit',
'am_pm',
'android_platform_token',
'ascii_company_email',
'ascii_email',
'ascii_free_email',
'ascii_safe_email',
'bank_country',
'bban',
'binary',
'boolean',
'bothify',
'bs',
'building_number',
'cache_pattern',
'catch_phrase',
'century',
'chrome',
'city',
'city_prefix',
'city_suffix',
'color',
'color_name',
'company',
'company_email',
'company_suffix',
'coordinate',
'country',
'country_calling_code',
'country_code',
'credit_card_expire',
'credit_card_full',
'credit_card_number',
'credit_card_provider',
'credit_card_security_code',
'cryptocurrency',
'cryptocurrency_code',
'cryptocurrency_name',
'csv',
'currency',
'currency_code',
'currency_name',
'currency_symbol',
'current_country',
'current_country_code',
'date',
'date_between',
'date_between_dates',
'date_object',
'date_of_birth',
'date_this_century',
'date_this_decade',
'date_this_month',
'date_this_year',
'date_time',
'date_time_ad',
'date_time_between',
'date_time_between_dates',
'date_time_this_century',
'date_time_this_decade',
'date_time_this_month',
'date_time_this_year',
'day_of_month',
'day_of_week',
'del_arguments',
'dga',
'domain_name',
'domain_word',
'dsv',
'ean',
'ean13',
'ean8',
'ein',
'email',
'factories',
'file_extension',
'file_name',
'file_path',
'firefox',
'first_name',
'first_name_female',
'first_name_male',
'first_name_nonbinary',
'fixed_width',
'format',
'free_email',
'free_email_domain',
'future_date',
'future_datetime',
'generator_attrs',
'get_arguments',
'get_formatter',
'get_providers',
'hex_color',
'hexify',
'hostname',
'http_method',
'iana_id',
'iban',
'image',
'image_url',
'internet_explorer',
'invalid_ssn',
'ios_platform_token',
'ipv4',
'ipv4_network_class',
'ipv4_private',
'ipv4_public',
'ipv6',
'isbn10',
'isbn13',
'iso8601',
'items',
'itin',
'job',
'json',
'language_code',
'language_name',
'last_name',
'last_name_female',
'last_name_male',
'last_name_nonbinary',
'latitude',
'latlng',
'lexify',
'license_plate',
'linux_platform_token',
'linux_processor',
'local_latlng',
'locale',
'locales',
'localized_ean',
'localized_ean13',
'localized_ean8',
'location_on_land',
'longitude',
'mac_address',
'mac_platform_token',
'mac_processor',
'md5',
'military_apo',
'military_dpo',
'military_ship',
'military_state',
'mime_type',
'month',
'month_name',
'msisdn',
'name',
'name_female',
'name_male',
'name_nonbinary',
'nic_handle',
'nic_handles',
'null_boolean',
'numerify',
'opera',
'paragraph',
'paragraphs',
'parse',
'password',
'past_date',
'past_datetime',
'phone_number',
'port_number',
'postalcode',
'postalcode_in_state',
'postalcode_plus4',
'postcode',
'postcode_in_state',
'prefix',
'prefix_female',
'prefix_male',
'prefix_nonbinary',
'pricetag',
'profile',
'provider',
'providers',
'psv',
'pybool',
'pydecimal',
'pydict',
'pyfloat',
'pyint',
'pyiterable',
'pylist',
'pyset',
'pystr',
'pystr_format',
'pystruct',
'pytimezone',
'pytuple',
'random',
'random_choices',
'random_digit',
'random_digit_not_null',
'random_digit_not_null_or_empty',
'random_digit_or_empty',
'random_element',
'random_elements',
'random_int',
'random_letter',
'random_letters',
'random_lowercase_letter',
'random_number',
'random_sample',
'random_uppercase_letter',
'randomize_nb_elements',
'rgb_color',
'rgb_css_color',
'ripe_id',
'safari',
'safe_color_name',
'safe_domain_name',
'safe_email',
'safe_hex_color',
'secondary_address',
'seed',
'seed_instance',
'seed_locale',
'sentence',
'sentences',
'set_arguments',
'set_formatter',
'sha1',
'sha256',
'simple_profile',
'slug',
'ssn',
'state',
'state_abbr',
'street_address',
'street_name',
'street_suffix',
'suffix',
'suffix_female',
'suffix_male',
'suffix_nonbinary',
'swift',
'swift11',
'swift8',
'tar',
'text',
'texts',
'time',
'time_delta',
'time_object',
'time_series',
'timezone',
'tld',
'tsv',
'unique',
'unix_device',
'unix_partition',
'unix_time',
'upc_a',
'upc_e',
'uri',
'uri_extension',
'uri_page',
'uri_path',
'url',
'user_agent',
'user_name',
'uuid4',
'weights',
'windows_platform_token',
'word',
'words',
'year',
'zip',
'zipcode',
'zipcode_in_state',
'zipcode_plus4']
>>> faker.c
faker.cache_pattern faker.company_suffix( faker.cryptocurrency_code(
faker.catch_phrase( faker.coordinate( faker.cryptocurrency_name(
faker.century( faker.country( faker.csv(
faker.chrome( faker.country_calling_code( faker.currency(
faker.city( faker.country_code( faker.currency_code(
faker.city_prefix( faker.credit_card_expire( faker.currency_name(
faker.city_suffix( faker.credit_card_full( faker.currency_symbol(
faker.color( faker.credit_card_number( faker.current_country(
faker.color_name( faker.credit_card_provider( faker.current_country_code(
faker.company( faker.credit_card_security_code(
faker.company_email( faker.cryptocurrency(
>>> faker. # Invoke TAB several times, but nothing happened.
This issue is stale because it has been open for 30 days with no activity.
I see the same problem on Python 3.9 in PyCharm. I wonder if this is just due to the high level of dynamism in Faker? I.e. attributes are added in via __getattribute__
so static type checkers cannot resolve them?
But makes the library a pain to use as not discoverable via IDE.
These are the attributes I see on faker instance.
I just filed a duplicate (missed this one) in #1684
Here's my completions as of faker 13.15.0, example:
from faker import Faker
def test_faker(faker: Faker):
assert isinstance(faker.name(), str)
This example above is based on Pytest Fixture's examples, annotating with faker.Faker
(as is common, see GitHub Search):
This issue is stale because it has been open for 30 days with no activity.
Everybody wants completions for faker
edit: I don't believe anybody specifically doesn't want it 😃
I found that there are plenties of providers in faker.providers
and all of them have functional auto-completion. Is it possible to use these providers on our own instead of using the "Proxy Class" faker.Faker
? How can we use it?
I'm just commenting to say that I'd greatly appreciate this feature as well. I'd imagine it would be trivial to add a mypy stub or similar to declare all of the many provider's attributes as members of the base Faker class. I'm trying to write the stub file myself, I'll try to remember to report back if it works.
Well, it didn't take long for me to find the issue that's causing our autocomplete not to work. Unfortunately it's not as easy to solve as I'd hoped.
def __dir__(self):
attributes = set(super(Faker, self).__dir__())
for factory in self.factories:
attributes |= {attr for attr in dir(factory) if not attr.startswith("_")}
return sorted(attributes)
Because of self.factories
(aka faker.proxy.Faker().factories
) only being known at runtime (it varies with the parameters provided to faker.proxy.Faker.__init__
), the result of faker.proxy.Faker().__dir__()
can't be determined without actually instantiating the Faker class.
I know that MyPy can provide type hints/autocompletion even for generated classes (I can't remember where I've seen it before - I think the AWS API library boto3 is an example). There has to be a way to get dynamic type hints even with the generated factories.
Edit: I had forgotten that boto3's type hints are actually quite cumbersome to use. Due to its heavy use of generated classes (I digress, but why did they choose to make them dynamic???) the mypy type hints have to be imported manually (from the ugly-named mypy_boto3_*
packages) unless you're using an IDE that supports dynamic type hints (such as VSCode with PyLance, PyCharm, IntelliJ with the Mypy plugin, etc).
Because of the ugliness of these type hints, I'd love to see an alternative solution to the dynamic class typing problem.
@KaylaHood You are correct in factories and metaclasses masking completions due to being reliant on runtime.
If you accomplish anything it'd be nice to see where it goes. But it may be too runtime-heavy to get completion and typings for.
@tony well I seem to have made something helpful but objectively not very Pythonic. https://github.com/KaylaHood/faker-stubs
I wrote a little script that makes heavy use of the standard lib inspect
package to generate a stub for Faker's proxy.py file so that auto-completion for faker.Faker()
instances will contain every provider method for every locale.
It works for my use case (Windows 10, Python 3.9), but I didn't spend time testing it for other platforms.
You have to run the stub generator every time you install/upgrade Faker; I can see it getting tedious very quickly.
If you use poetry or some other python package management tool you could write a post-build script that automates the download and execution of my stub generation script.
NOTE: the automated stub generation solution I just described should NEVER be used for a production or client-facing application. You don't know me! I could change my stub generation script to be a data miner! (I wouldn't, but y'know what I mean) If you would like to incorporate it into your product, then consider forking my repo to your own github/artifactory/server/etc and then use your cloned version of my script in your product's build pipeline.
Hopefully you find it useful!
We could integrate @KaylaHood 's script in our CI build and run it before every release, but that would still not cover community providers that users have installed on their own.
On one hand, that'd be better than nothing. On the other, it may set the wrong expectation on users.
@fcurella if y'all do incorporate my script, please feel free to refactor it and optimize it. I did very little optimization, I approached this with more of an "MVP" mindset :-)
I agree with your last point, incorporating my stubs could confuse users who utilize their own providers or who select a specific locale.
The problem of external providers can easily be resolved by extending my stub generator script to have a configurable list of provider packages to scan.
The locale problem is much harder because locales are selected at runtime. To fix the auto-completion for locale-restricted Faker instances, there'd need to be major renovations done to the locale selection mechanism.
@KaylaHood I try your repo and it works great on my device! Thank you!
Environments
- Microsoft Windows 11 Professional 22H2
- Ubuntu 22.04 LTS on WSL2
- Microsoft Visual Studio Code v1.73.1 (system setup)
- Python v3.10.7
- Poetry v1.2.2
- Faker v15.3.1
Screenshots
This is a night and day difference.
Environment
- Ubuntu 22.04 LTS on WSL2
- vim with coc.nvim + coc-pyright
- Python 3.11.0
- Faker version: trunk @ bc56a8f
- https://github.com/KaylaHood/faker-stubs @
77d25e7
Instructions
mkdir -p ~/projects/python; cd ~/projects/python
git clone https://github.com/joke2k/faker
git clone https://github.com/KaylaHood/faker-stubs
cd ~/projects/python/faker
virtualenv .venv
. .venv/bin/activate
pip install -e .
python ../faker-stubs/generate_stub.py
You should now see this with git status
:
❯ git status
On branch master
Your branch is up to date with 'origin/master'.
Untracked files:
(use "git add <file>..." to include in what will be committed)
faker/proxy.pyi
If the faker/proxy.pyi
stub is there, you will be able to see typings if you open any file, e.g. tests/test_proxy.py
Before (via here)
from faker import Faker
def test_faker(faker: Faker):
assert isinstance(faker.name(), str)
With faker-stubs @ 77d25e7
Locale / faker constructor
re: locales
from faker import Faker
fake = Faker(locale="en")
Expected no arguments to "Faker" constructor (Pyright reportGeneralTypeIssues)
If the constructor itself allowed locale
, we'd get around this particular one. Though we wouldn't have locale-specific ones.
@tony
If the constructor itself allowed locale, we'd get around this particular one. Though we wouldn't have locale-specific ones.
Thanks for pointing this out, I made a quick fix for this: https://github.com/KaylaHood/faker-stubs/tree/3e5c7260539564dd60bc71d83b8cd596d5fd6506
I had forgotten to include the mangled methods from the Faker class (__init__
, __deepcopy__
, etc). Now the __init__
method's signature will include the optional locale argument (as well as the other optional args).
Edit: use this version of my faker-stubs script instead: https://github.com/KaylaHood/faker-stubs/tree/d555b36a4deeeaccdecdfb5a90cda134dbb38605
I fixed the docstrings in the stubs so now the docstrings will populate in the auto-completion results.
I also realized certain provider functions have the same name as some member variables (example: country_code
). I added logic that removes those conflicting member variables from the stub in favor of the provider function.
@KaylaHood Follow up to https://github.com/joke2k/faker/issues/1604#issuecomment-1312496383 + https://github.com/joke2k/faker/issues/1604#issuecomment-1312799159
Environment
- Ubuntu 22.04 LTS on WSL2
- vim with coc.nvim + coc-pyright
- Python 3.11.0
- Faker version: trunk @ bc56a8f
- https://github.com/KaylaHood/faker-stubs @
5c7ffc2
...
New docstring completions + locale kwarg
This looks good.
I had forgotten to include the mangled methods from the Faker class (
__init__
,__deepcopy__
, etc). Now the__init__
method's signature will include the optional locale argument (as well as the other optional args).
Got it and this looks good (screenshot 1)
I fixed the docstrings in the stubs so now the docstrings will populate in the auto-completion results.
Roger that, and this looks good (screenshot 1)
Above: Screenshot 1
Provider functions v. member names
I also realized certain provider functions have the same name as some member variables (example:
country_code
). I added logic that removes those conflicting member variables from the stub in favor of the provider function.
Good catch here as well
Before, with faker-stubs @ 77d25e7
With faker-stubs @ d555b36
:
With faker-stubs @ 5161681
:
With faker-stubs @ 5c7ffc2
:
Side note, re: **config: Any
**config: Any
on the faker side permits anything, https://github.com/joke2k/faker/blob/bc56a8f37f4a1aef3b2fc6c4efb69cfcf28606e0/faker/proxy.py#L34
I've never used any **config
kwargs, so I'm not sure what this is used for. If it's something deterministic, there's new PEPs and backported support available:
- PEP 692 "Using TypedDict for more precise **kwargs typing" may be able to help. Backport supported by mypy 0.981
-
PEP 655 "Marking individual TypedDict items as required or potentially-missing", supported in
typing_extensions
since 4.1.0 (thoughTypedDict
must be imported viatyping_extensions
This issue is stale because it has been open for 30 days with no activity.
This issue was closed because it has been inactive for 14 days since being marked as stale.
@joke2k Can we keep this open?
@tony I assume that pinging @fcurella here would make much sense, as he is the active maintainer at the moment.
I would like this issue reopened. It's not working on Python 3.11 either.
What used to work
# pip install faker=="17.3.0"
# python
>>> import faker
>>> fake = faker.Faker()
>>> fake.
Type [TAB] once or twice and you see this:
Display all 280 possibilities? (y or n)
fake.aba( fake.generator_attrs fake.pyfloat(
fake.add_provider( fake.get_arguments( fake.pyint(
fake.address( fake.get_formatter( fake.pyiterable(
... I've removed a whole bunch for brevity's sake.
fake.free_email( fake.psv( fake.zipcode_in_state(
fake.free_email_domain( fake.pybool( fake.zipcode_plus4(
fake.future_date( fake.pydecimal(
fake.future_datetime( fake.pydict(
>>> fake.
What's broken
In Python 3.9, 3.10, and now 3.11:
# pip install faker=="17.3.0"
# python
>>> import faker
>>> fake = faker.Faker()
>>> fake.
Type [TAB] once or twice and nothing happens.
Claim that this feature should work
This is Python saying things like this should work: https://docs.python.org/3.11/tutorial/interactive.html#tab-completion-and-history-editing. (Docs here are the same in all versions of Python)
We know Windows PowerShell and cmd won't play nice with [TAB]s, but in WSL, with python 3.10.1, I was able to replicate the bug too. Same issue. fake.
type [TAB] then nothing. Tab completion works on other things. Type int.
and [TAB] and see things like int.as_integer_ratio( int.bit_length( int.denominator( ...
. The only thing I don't have easy access to is a bare metal machine with Linux installed to see if it won't work there either.
Okay, someone suggested I try the iPython shell. Tab completion does appear to work in there, which is nice, but I still think it's a bug when tab completion isn't working in the default python shell.