Changelog


← Back to all posts

December 21, 2021

Try Sourcery without an account!

You can now use Sourcery straight away on installation, with no need to create an account or enter a token. This gives you access to our Free tier. To try out our Pro features you can create an account to get a 30 day free trial.

New refactorings

Sourcery refactoring id: equality-identity

Description:

Simplify equality comparisons that are always True or False

Before:

if 1 == 1:
    always_do_this()

if 1 != 1:
    never_do_this()

After:

if True:
    always_do_this()

if False:
    never_do_this()

Explanation:

When comparing a value to itself, the outcome will always be True, as long as the equality operator has not been overridden, and this also holds for the opposite comparison and False. It is more readable to use a direct comparison to the boolean value.

Sourcery refactoring id: identity-comprehension

Description

Convert list/set/tuple comprehensions that do not change the input elements into

Before

# List comprehensions
[item for item in coll]
[item for item in friends.names()]

# Dict comprehensions
{k: v for k, v in coll}
{k: v for k, v in coll.items()}  # Only if we know coll is a `dict`

# Unneeded call to `.items()`
dict(coll.items())  # Only if we know coll is a `dict`

# Set comprehensions
{item for item in coll}

After

# List comprehensions
list(iter(coll))
list(iter(friends.names()))

# Dict comprehensions
dict(coll)
dict(coll)

# Unneeded call to `.items()`
dict(coll)

# Set comprehensions
set(coll)

Explanation

All these comprehensions are just creating a copy of the original collection. They can all be simplified by simply constructing a new collection directly. The resulting code is easier to read and shows the intent more clearly.

Sourcery refactoring id: merge-assign-and-aug-assign

Description:

Replaces an assignment and an augmented assignment with a single assignment.

Before:

other_value = 33
number = 42
number += other_value

After:

other_value = 33
number = 42 + other_value

Explanation:

When we mutate a variable multiple times without reading or writing its value in between, it's more readable and more efficient to change its value only once. This way, it's clearer which values this variable can have at various points.

This refactoring works with all 4 augmented assignment operators:

  • +=
  • -=
  • *=
  • /=

Sourcery refactoring id: remove-str-from-print

Description:

Removes unnecessary calls to str() from within print()

Before:

print(str(1))

After:

print(1)

Explanation:

Objects passed into calls to the print() function already have str() called on them, so it is not required to do so yourself.

Sourcery refactoring id: simplify-division

Description:

Use Python's built-in feature for succinct division syntax.

Before:

result = int(42 / 10)

After:

result = 42 // 10

Before:

result = 42 // 10
remainder = 42 % 10

After:

result, remainder = divmod(42, 10)

Explanation:

Python has some great features to simplify division expressions. If you're interested only in the whole number component of the quotient, you can use the // integer division operator. If you want to have the whole number component and the remainder in separate variables, the built-in divmod function comes handy.

Sourcery refactoring id: simplify-substring-search

Description:

Simplify finding if substrings are present in strings by using in

Before:

my_str = "Hello world"
if my_str.find("ello") == -1:
    print("Not Found!")

After:

my_str = "Hello world"
if "ello" not in my_str:
    print("Not Found!")

Before:

my_str = "Hello world"
if my_str.count("ello") > 0:
    print("Found!")

After:

my_str = "Hello world"
if "ello" in my_str:
    print("Found!")

Explanation:

Making use of Python's in operator for detecting if a substring is present in a string is more readable than using the find or count methods, and is also suggested in the documentation. These methods are more suitable for cases where you need more information about the substring's location or the number of times it appears.

Fixed

  • Fix issue where merging nested if conditions with named expresssions could change behaviour due to missing brackets.
  • Fix issue when refactoring strings containing different types of quotes
  • Stop hoist-if-from-if proposal from hoisting ifs that would then be incorrectly entered