Skip to content

add typing-extensions requirement #939

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 10 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
continue-on-error: ${{ matrix.python-version == 'pypy3' }}
strategy:
matrix:
python-version: [3.6, 3.7, 3.8, 3.9, "3.10", pypy3]
python-version: [3.7, 3.8, 3.9, "3.10", pypy3]
steps:
- uses: actions/checkout@v2
with:
Expand Down
11 changes: 11 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
Changelog
=========

0.23
----

General information:

New features:

Fixes:

Support for Python 3.6 has been dropped.

0.22
----

Expand Down
28 changes: 14 additions & 14 deletions bpython/autocomplete.py
Original file line number Diff line number Diff line change
Expand Up @@ -343,13 +343,14 @@ def format(self, word: str) -> str:
return after_last_dot(word)


def _safe_glob(pathname: str) -> Iterator[str]:
return glob.iglob(glob.escape(pathname) + "*")


class FilenameCompletion(BaseCompletionType):
def __init__(self, mode: AutocompleteModes = AutocompleteModes.SIMPLE):
super().__init__(False, mode)

def safe_glob(self, pathname: str) -> Iterator[str]:
return glob.iglob(glob.escape(pathname) + "*")

def matches(
self, cursor_offset: int, line: str, **kwargs: Any
) -> Optional[Set]:
Expand All @@ -359,7 +360,7 @@ def matches(
matches = set()
username = cs.word.split(os.path.sep, 1)[0]
user_dir = os.path.expanduser(username)
for filename in self.safe_glob(os.path.expanduser(cs.word)):
for filename in _safe_glob(os.path.expanduser(cs.word)):
if os.path.isdir(filename):
filename += os.path.sep
if cs.word.startswith("~"):
Expand All @@ -371,7 +372,6 @@ def locate(self, cursor_offset: int, line: str) -> Optional[LinePart]:
return lineparts.current_string(cursor_offset, line)

def format(self, filename: str) -> str:
filename.rstrip(os.sep).rsplit(os.sep)[-1]
if os.sep in filename[:-1]:
return filename[filename.rindex(os.sep, 0, -1) + 1 :]
else:
Expand Down Expand Up @@ -570,15 +570,15 @@ def matches(
r = self.locate(cursor_offset, line)
if r is None:
return None
if argspec:
matches = {
f"{name}="
for name in argspec[1][0]
if isinstance(name, str) and name.startswith(r.word)
}
matches.update(
name + "=" for name in argspec[1][4] if name.startswith(r.word)
)

matches = {
f"{name}="
for name in argspec[1][0]
if isinstance(name, str) and name.startswith(r.word)
}
matches.update(
name + "=" for name in argspec[1][4] if name.startswith(r.word)
)
return matches if matches else None

def locate(self, cursor_offset: int, line: str) -> Optional[LinePart]:
Expand Down
2 changes: 1 addition & 1 deletion bpython/curtsiesfrontend/interpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def format(self, tokensource, outfile):
for token, text in tokensource:
while token not in self.f_strings:
token = token.parent
o += "{}\x03{}\x04".format(self.f_strings[token], text)
o += f"{self.f_strings[token]}\x03{text}\x04"
outfile.write(parse(o.rstrip()))


Expand Down
2 changes: 1 addition & 1 deletion bpython/curtsiesfrontend/repl.py
Original file line number Diff line number Diff line change
Expand Up @@ -2067,7 +2067,7 @@ def key_help_text(self):

max_func = max(len(func) for func, key in pairs)
return "\n".join(
"{} : {}".format(func.rjust(max_func), key) for func, key in pairs
f"{func.rjust(max_func)} : {key}" for func, key in pairs
)

def get_session_formatted_for_file(self) -> str:
Expand Down
4 changes: 2 additions & 2 deletions bpython/formatter.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ class BPythonFormatter(Formatter):
def __init__(self, color_scheme, **options):
self.f_strings = {}
for k, v in theme_map.items():
self.f_strings[k] = "\x01{}".format(color_scheme[v])
self.f_strings[k] = f"\x01{color_scheme[v]}"
if k is Parenthesis:
# FIXME: Find a way to make this the inverse of the current
# background colour
Expand All @@ -114,7 +114,7 @@ def format(self, tokensource, outfile):

while token not in self.f_strings:
token = token.parent
o += "{}\x03{}\x04".format(self.f_strings[token], text)
o += f"{self.f_strings[token]}\x03{text}\x04"
outfile.write(o.rstrip())


Expand Down
11 changes: 3 additions & 8 deletions bpython/inspection.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ def getfuncprops(func, f):
return fprops


def is_eval_safe_name(string):
def is_eval_safe_name(string: str) -> bool:
return all(
part.isidentifier() and not keyword.iskeyword(part)
for part in string.split(".")
Expand Down Expand Up @@ -334,7 +334,7 @@ def get_argspec_from_signature(f):
get_encoding_line_re = LazyReCompile(r"^.*coding[:=]\s*([-\w.]+).*$")


def get_encoding(obj):
def get_encoding(obj) -> str:
"""Try to obtain encoding information of the source of an object."""
for line in inspect.findsource(obj)[0][:2]:
m = get_encoding_line_re.search(line)
Expand All @@ -354,7 +354,7 @@ def get_encoding_file(fname: str) -> str:
return "utf8"


def getattr_safe(obj: Any, name: str):
def getattr_safe(obj: Any, name: str) -> Any:
"""side effect free getattr (calls getattr_static)."""
result = inspect.getattr_static(obj, name)
# Slots are a MemberDescriptorType
Expand All @@ -369,8 +369,3 @@ def hasattr_safe(obj: Any, name: str) -> bool:
return True
except AttributeError:
return False


def get_source_unicode(obj):
"""Returns a decoded source of object"""
return inspect.getsource(obj)
2 changes: 1 addition & 1 deletion bpython/repl.py
Original file line number Diff line number Diff line change
Expand Up @@ -649,7 +649,7 @@ def get_source_of_current_name(self):
raise SourceNotFound(_("Nothing to get source of"))
if inspection.is_eval_safe_name(line):
obj = self.get_object(line)
return inspection.get_source_unicode(obj)
return inspect.getsource(obj)
except (AttributeError, NameError) as e:
msg = _("Cannot get source: %s") % (e,)
except OSError as e:
Expand Down
2 changes: 1 addition & 1 deletion bpython/simpleeval.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ def safe_getitem(obj, index):
return obj[index]
except (KeyError, IndexError):
raise EvaluationError(f"can't lookup key {index!r} on {obj!r}")
raise ValueError("unsafe to lookup on object of type {}".format(type(obj)))
raise ValueError(f"unsafe to lookup on object of type {type(obj)}")


def find_attribute_with_name(node, name):
Expand Down
13 changes: 4 additions & 9 deletions bpython/test/test_inspection.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import inspect
import os
import sys
import unittest
Expand Down Expand Up @@ -89,19 +90,13 @@ def test_get_encoding_utf8(self):
self.assertEqual(inspection.get_encoding(encoding_utf8.foo), "utf-8")

def test_get_source_ascii(self):
self.assertEqual(
inspection.get_source_unicode(encoding_ascii.foo), foo_ascii_only
)
self.assertEqual(inspect.getsource(encoding_ascii.foo), foo_ascii_only)

def test_get_source_utf8(self):
self.assertEqual(
inspection.get_source_unicode(encoding_utf8.foo), foo_non_ascii
)
self.assertEqual(inspect.getsource(encoding_utf8.foo), foo_non_ascii)

def test_get_source_latin1(self):
self.assertEqual(
inspection.get_source_unicode(encoding_latin1.foo), foo_non_ascii
)
self.assertEqual(inspect.getsource(encoding_latin1.foo), foo_non_ascii)

def test_get_source_file(self):
path = os.path.join(
Expand Down
2 changes: 1 addition & 1 deletion doc/sphinx/source/contributing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ the time of day.
Getting your development environment set up
-------------------------------------------

bpython supports Python 3.6 and newer. The code is compatible with all
bpython supports Python 3.7 and newer. The code is compatible with all
supported versions.

Using a virtual environment is probably a good idea. Create a virtual
Expand Down
2 changes: 1 addition & 1 deletion doc/sphinx/source/releases.rst
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ A checklist to perform some manual tests before a release:

Check that all of the following work before a release:

* Runs under Python 3.6 - 3.9
* Runs under Python 3.7 - 3.9
* Save
* Rewind
* Pastebin
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ requires = [

[tool.black]
line-length = 80
target_version = ["py36"]
target_version = ["py37"]
include = '\.pyi?$'
exclude = '''
/(
Expand Down
1 change: 0 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ Pygments
backports.cached-property; python_version < "3.8"
curtsies >=0.3.5
cwcwidth
dataclasses; python_version < "3.7"
greenlet
pyxdg
requests
Expand Down
4 changes: 2 additions & 2 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ classifiers =
Programming Language :: Python :: 3

[options]
python_requires = >=3.6
python_requires = >=3.7
packages =
bpython
bpython.curtsiesfrontend
Expand All @@ -22,12 +22,12 @@ packages =
install_requires =
backports.cached-property; python_version < "3.8"
curtsies >=0.3.5
dataclasses; python_version < "3.7"
cwcwidth
greenlet
pygments
pyxdg
requests
typing-extensions

[options.extras_require]
clipboard = pyperclip
Expand Down