Skip to content

Introduction to Sourcery

About this Tutorial

Welcome!

If you are new to Sourcery, you are in the right place - this tutorial is aimed at people just starting out.

If you're familiar with Sourcery already, you may instead want to browse the Reference material, the Guides, or the Further Reading.

In this tutorial, you'll learn:

  • What Sourcery does, and how to use it as your pair programmer
  • How to install Sourcery in VSCode & JetBrains IDEs
  • How to use Sourcery interactively in VS Code & JetBrains IDEs

Non-VSCode/JetBrains users

If you are following this tutorial for the first time, we encourage you to install VSCode and follow along, even if you don't usually use VSCode for programming. This will help you understand what Sourcery can do, so you can make best use of it in your main programming workflow.

Tutorial Setup

Objectives

In this section, you will:

  • Learn how to install Sourcery in your IDE
  • Get the tutorial project

See Also


Requirements

  • Windows, macOS, or Linux operating system (special instructions for M1 machines can be found here)
  • VSCode installed (download at the official website) or a JetBrains IDE installed
  • git installed (installation instructions on the official website)

Installing Sourcery

  1. Open VSCode, and click the icon in the sidebar for "Extensions" Location of VSCode Extensions

or

Open a JetBrains IDE, go to "Settings", and select "Plugins" 2. Search for "Sourcery" (note the "u" in the spelling) and click "Install" to install the extension Location of Install Button

Logging Into Sourcery

Once you've installed Sourcery you'll need to log in to start using it. Click into the Sourcery section of the sidebar (click on our hexagon logo) and you'll see a prompt to log in.

Click the log in button and you'll be taken to our website to connect to your account. If you don't have an account you can easily create one and you'll get a 14 day free trial of Sourcery.

Demo Code

For the rest of this tutorial we'll be taking a look at this demo code:

def read_file(filename):
    with open(filename, 'r') as file:
        content = file.readlines()
    return content


def is_digit(character):
    return character in '0123456789'


def is_alpha(character):
    return 'a' <= character <= 'z' or 'A' <= character <= 'Z'


def is_valid_email_character(character):
    return is_alpha(character) or is_digit(character) or character in ['.', '-', '_']


def find_emails(line):
    emails = []
    i = 0
    while i < len(line):
        if is_valid_email_character(line[i]):
            start = i
            while i < len(line) and line[i] != '@':
                i += 1
            if i < len(line) and line[i] == '@':
                i += 1
                while i < len(line) and line[i] != '.':
                    i += 1
                if i < len(line) and line[i] == '.':
                    end = i
                    while i < len(line) and is_valid_email_character(line[i]):
                        i += 1
                    emails.append(line[start:i])
        i += 1
    return emails


def find_phone_numbers(line):
    phone_numbers = []
    i = 0
    while i < len(line):
        if is_digit(line[i]):
            start = i
            count_digits = 0
            while i < len(line) and (is_digit(line[i]) or line[i] in ['-', ' ', '(', ')']):
                if is_digit(line[i]):
                    count_digits += 1
                i += 1
            if count_digits == 10:
                phone_numbers.append(line[start:i])
        i += 1
    return phone_numbers


def extract_information_from_file(filename):
    lines = read_file(filename)
    all_emails = []
    all_phone_numbers = []
    for line in lines:
        emails = find_emails(line)
        phone_numbers = find_phone_numbers(line)
        all_emails.extend(emails)
        all_phone_numbers.extend(phone_numbers)
    return all_emails, all_phone_numbers


def write_to_file(filename, emails, phone_numbers):
    with open(filename, 'w') as file:
        file.write("Emails:\n")
        for email in emails:
            file.write(email + "\n")
        file.write("\nPhone Numbers:\n")
        for phone_number in phone_numbers:
            file.write(phone_number + "\n")


def main():
    input_filename = "sample.txt"
    output_filename = "output.txt"
    emails, phone_numbers = extract_information_from_file(input_filename)
    write_to_file(output_filename, emails, phone_numbers)


if __name__ == "__main__":
    main()

It's some sample code that reads from a file named sample.txt, extracts email addresses and phone numbers from it, and then writes the results to output.txt. The pattern matching is done manually, and there's definitely room for improvement

Interacting with Sourcery

Chatting with Sourcery

If you open the Sourcery sidebar you can start to ask Sourcery questions. When you select a section of code, Sourcery can then refererence that code in its answer.

Here we can select the sample code and ask it to replace the manual pattern matching with regex.

Sourcery will take a look at the code we've given it and suggest an updated version using regex.

If you hover over the code block in the chat window you will see 2 icons appear - the lefthand icon copies the code to your clipboard and the righthand icon inserts the codeblock at your current cursor location in your editor.

With the initial code still selected in your editor you can click the "insert at cursor" icon and replace the initial code.

Sourcery suggesting code improvements through chat

Generating Docstrings and Tests

Above each function in the file you'll see a few commands - Generate Docstrings, Generate Tests, Ask Sourcery, etc. These are Code Lenses that you can use as quick commands to have Sourcery interact with your code.

Let's start by using one on the extract_information_from_file function. Click Generate Docstring above that function definition and Sourcery will propose a new docstring for that code.

You can add a line below the function definition, select the new line, and click the "insert at cursor" icon to add the docstring directly to the code.

Sourcery writing a docstring

Next you can have Sourcery write tests for the same function by clicking the "Generate Tests" code lens.

In the chat, you'll see a full test file that Sourcery proposes for that code. Click the copy icon in that code block and paste it into a new test file.

You should always review the tests that Sourcery writes and use them as a jumping off point for your tests rather than taking them as the optimal outcome (although we'll keep working to make them better and better!)

Sourcery writing tests

Explaining Code

So far we've used Sourcery to change existing code and write new code - but what if we want to learn more about the code we already have?

The Explain Code recipe tells Sourcery to give us an explanation about a section of code and is particularly useful when we we're working in a new project.

Click the Explain Code code lens above the extract_information_from_file function and Sourcery will give you more info about the function in the sidebar chat.

Sourcery explaining code

More Recipes

Sourcery has two more built in recipes - Optimize Performance and Simplify Code.

Let's try seeing how sourcery can further simplify extract_information_from_file.

Click on the Ask Sourcery code lens above the function and select Simplify Code from the dropdown that appears.

In the sidebar, Sourcery will suggest a simplified version of the code and explain what simplifications it's making. If it looks good to you, replace the current code with the simplified code. If it doesn't, you can ask Sourcery to make changes in the chat.

You can also use any recipe by selecting a section of code, opening the Sourcery sidebar, and clicking the button for the recipe you want to apply.

Simplifying code with Sourcery

Sourcery's Rules Based Suggestions

Sourcery will passively review your code while you work and give you suggestions about how it could be improved based on language-specific rules and best practices. You'll know you have a Sourcery suggestion when you see a squigly underline on your code, such as this one:

Underlined line of code in the editor

Blue lines correspond to Suggestions and Comments, and yellow lines are used for Refactorings.

If you hover over these lines with your cursor, you'll see a pop-up window with some additional detail about the rule.

Important

Sourcery only underlines the first line of the code it thinks should change, to avoid visual spam.

Seeing Rules in The Problems Panel

As well as being shown as a wiggly underline in your code, Sourcery's matched Rules can be found in your IDE's "Problems" panel.

To open the problems panel, click "View" in the main toolbar and then select "Problems":

The problems panel shows a summary of all the Rules that Sourcery has matched in your open documents.

The problems panel, showing matched Rules

You can click on any of these to jump to their location in the document; this is convenient if you have large files and don't want to scroll through looking for refactorings.

Sourcery Rules Based Suggestions

How to Read Rule Details

Using your cursor, hover over the line in the editor which reads

emails = re.findall(pattern,line)

You should see a pop-up with a proposed change to your code.

Here's a bit of detail about what that pop-up means.

A summary line gives you an overview of the change. It may describe the change as "refactored", "making a change", or "identifying an issue" depending on the type of change. It will also try to tell you which function or lines of code will change.

The bullet point list shows a breakdown of each of the individual rules Sourcery has matched to make the change. In this case, only one rule was used, in-line-immediately-returned-variable.

Towards the bottom you'll see a diff of the complete code change sourcery is proposing - it will delete four lines (shown in red) and introduce a new one (shown in green). A couple of unchanged lines are shown in gray for context.

The final lines show all the diagnostics your IDE has identified for this line, including a repeat of the main issue reported by Sourcery. If you have other plugins, there may be more here.

Skipping Sourcery's Rules

Sourcery's rules are opinionated, and you may disagree with them.

Skip a Rule Violation Once

If you don't think a rule is right for your code, you can "skip" it. Sourcery will add a comment to your code that lets it know not to search for that rule in the current function.

Hover over the second underlined line. Click on the lightbulb next to it to bring up a menu. The second menu item says "Sourcery - skip suggested refactoring in this code block". Choose this option.

Skipping a proposed change from the quick-fix hover menu

Two things will happen. First, Sourcery will insert a comment near the start of the function which says

# sourcery skip: in-line-immdiately-returned-variable

Second, the highlighted Refactoring will disappear.

You can make Sourcery search for the in-line-immediately-returned-variable Refactoring again at any time by removing the Python comment.

Running a Code Review

Once we've made a number of changes we can ask Sourcery to review our code - just like you might ask a colleague for a review of a pull request/merge request.

Open the Sourcery sidebar and click on the Reviews tab at the top. (Note: Code Review is currently in a closed beta - if you do not see a Reviews tab and would like to try it out, please email tim@sourcery.ai)

Here you can select what code you would like Sourcery to review - the HEAD of your current branch with your repos default branch or your uncommitted code with the HEAD of your current branch.

For now, select Compare uncommitted changes with HEAD and click Review My Code

Sourcery will then start a code reivew - it will start with a summary of your PR and then give you feedback, starting with general feedback and then moving to line specific feedback.

This review functionality is still under development, so please let us know what feedback you have.

Reviewing Code

Conclusions

Here you've seen how you can use Sourcery to create, change, and review code throughout your project. You can chat with Sourcery to clarify or expand any of Sourcery's responses if you find that the initial results of a recipe aren't what you needed.

Was this page helpful?