Mastering Python Second Edition Release Code
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
Chapter 2, Interactive Python Shells
|
||||
##############################################################################
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
>>> 'Hello world!'
|
||||
'Hello world!'
|
||||
@@ -0,0 +1,27 @@
|
||||
# Adding default imports
|
||||
|
||||
>>> from pprint import pprint as pp
|
||||
>>> from pprint import pformat as pf
|
||||
|
||||
>>> pp(dict(spam=0xA, eggs=0xB))
|
||||
{'eggs': 11, 'spam': 10}
|
||||
>>> pf(dict(spam=0xA, eggs=0xB))
|
||||
"{'eggs': 11, 'spam': 10}"
|
||||
|
||||
|
||||
# Modifying prompt
|
||||
|
||||
>>> if True:
|
||||
... print('Hello!')
|
||||
Hello!
|
||||
|
||||
>>> import sys
|
||||
|
||||
>>> sys.ps1 = '> '
|
||||
>>> sys.ps2 = '. '
|
||||
|
||||
# With modified prompt
|
||||
|
||||
> if True:
|
||||
. print('Hello!')
|
||||
Hello!
|
||||
@@ -0,0 +1,76 @@
|
||||
import __main__
|
||||
import re
|
||||
import atexit
|
||||
import readline
|
||||
import rlcompleter
|
||||
|
||||
|
||||
class Completer(rlcompleter.Completer):
|
||||
|
||||
ITEM_RE = re.compile(r'(?P<expression>.+?)\[(?P<key>[^\[]*)')
|
||||
|
||||
def complete(self, text, state):
|
||||
# Init namespace. From `rlcompleter.Completer.complete`
|
||||
if self.use_main_ns:
|
||||
self.namespace = __main__.__dict__
|
||||
|
||||
# If we find a [, try and return the keys
|
||||
if '[' in text:
|
||||
# At state 0 we need to prefetch the matches, after
|
||||
# that we use the cached results
|
||||
if state == 0:
|
||||
self.matches = list(self.item_matches(text))
|
||||
|
||||
# Try and return the match if it exists
|
||||
try:
|
||||
return self.matches[state]
|
||||
except IndexError:
|
||||
pass
|
||||
else:
|
||||
# Fallback to the normal completion
|
||||
return super().complete(text, state)
|
||||
|
||||
def item_matches(self, text):
|
||||
# Look for the pattern expression[key
|
||||
match = self.ITEM_RE.match(text)
|
||||
if match:
|
||||
search_key = match.group('key').lstrip()
|
||||
expression = match.group('expression')
|
||||
|
||||
# Strip quotes from the key
|
||||
if search_key and search_key[0] in {"'", '"'}:
|
||||
search_key = search_key.strip(search_key[0])
|
||||
|
||||
# Fetch the object from the namespace
|
||||
object_ = eval(expression, self.namespace)
|
||||
|
||||
# Duck typing, check if we have a `keys()` attribute
|
||||
if hasattr(object_, 'keys'):
|
||||
# Fetch the keys by executing the `keys()` method
|
||||
# Can you guess where the bug is?
|
||||
keys = object_.keys()
|
||||
for i, key in enumerate(keys):
|
||||
# Limit to 25 items for safety, could be
|
||||
# infinite
|
||||
if i >= 25:
|
||||
break
|
||||
|
||||
# Only return matching results
|
||||
if key.startswith(search_key):
|
||||
yield f'{expression}[{key!r}]'
|
||||
|
||||
|
||||
# By default readline doesn't call the autocompleter for [ because
|
||||
# it's considered a delimiter. With a little bit of work we can
|
||||
# fix this however :)
|
||||
delims = readline.get_completer_delims()
|
||||
# Remove [, ' and " from the delimiters
|
||||
delims = delims.replace('[', '').replace('"', '').replace("'", '')
|
||||
# Set the delimiters
|
||||
readline.set_completer_delims(delims)
|
||||
|
||||
# Create and set the completer
|
||||
completer = Completer()
|
||||
readline.set_completer(completer.complete)
|
||||
# Add a cleanup call on Python exit
|
||||
atexit.register(lambda: readline.set_completer(None))
|
||||
@@ -0,0 +1,15 @@
|
||||
>>> sandwich = dict(spam=2, eggs=1, sausage=1)
|
||||
>>> sandwich.<TAB> # doctest: +SKIP
|
||||
sandwich.clear( sandwich.fromkeys( sandwich.items( sandwich.pop(
|
||||
sandwich.setdefault( sandwich.values( sandwich.copy( sandwich.get(
|
||||
sandwich.keys( sandwich.popitem( sandwich.update(
|
||||
>>> sandwich[ # doctest: +SKIP
|
||||
|
||||
|
||||
>>> sandwich = dict(spam=2, eggs=1, sausage=1)
|
||||
>>> sandwich['<TAB> # doctest: +SKIP
|
||||
sandwich['eggs'] sandwich['sausage'] sandwich['spam']
|
||||
|
||||
>>> import T_02_modifying_autocompletion
|
||||
|
||||
>>> autocompletion = T_02_modifying_autocompletion
|
||||
@@ -0,0 +1,25 @@
|
||||
Note: missing_ok was added in Python 3.8
|
||||
|
||||
>>> import pathlib
|
||||
|
||||
>>> pathlib.Path('bpython.txt').unlink(missing_ok=True)
|
||||
|
||||
>>> with open('bpython.txt', 'a') as fh:
|
||||
... fh.write('x')
|
||||
...
|
||||
1
|
||||
>>> with open('bpython.txt') as fh:
|
||||
... print(fh.read())
|
||||
...
|
||||
x
|
||||
>>> sandwich = dict(spam=2, eggs=1, sausage=1)
|
||||
|
||||
>>> with open('bpython.txt', 'a') as fh:
|
||||
... fh.write('x')
|
||||
...
|
||||
1
|
||||
>>> with open('bpython.txt') as fh:
|
||||
... print(fh.read())
|
||||
...
|
||||
xx
|
||||
>>>
|
||||
@@ -0,0 +1,4 @@
|
||||
with open('reload.txt', 'a+') as fh:
|
||||
fh.write('x')
|
||||
fh.seek(0)
|
||||
print(fh.read())
|
||||
@@ -0,0 +1,7 @@
|
||||
import sys
|
||||
import pathlib
|
||||
|
||||
# Little hack to add the current directory to sys.path so we can
|
||||
# find the imports
|
||||
path = pathlib.Path(__file__).parent
|
||||
sys.path.append(str(path.resolve()))
|
||||
@@ -0,0 +1 @@
|
||||
xxxxx
|
||||
@@ -0,0 +1,3 @@
|
||||
# coding: utf-8
|
||||
|
||||
sandwich = dict(spam=2, eggs=1, sausage=1)
|
||||
Reference in New Issue
Block a user