Skip to content
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

Add Python #282

Merged
merged 61 commits into from
Jan 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
30d216f
Add initial Python language project
hendrikvanantwerpen Jun 1, 2023
75a3ec5
Add legacy queries and tests for reference
hendrikvanantwerpen Jun 1, 2023
decf584
convert: copy old
hendrikvanantwerpen Jun 1, 2023
edfe903
convert: attr syntax
hendrikvanantwerpen Jun 1, 2023
58c67fd
convert: no_span
hendrikvanantwerpen Jun 1, 2023
a830ef5
convert: more attr syntax
hendrikvanantwerpen Jun 1, 2023
d5a97bd
convert: pop_scoped_symbol
hendrikvanantwerpen Jun 1, 2023
01cf05d
convert: push symbol
hendrikvanantwerpen Jun 1, 2023
3ab39ce
convert: push and pop nodes
hendrikvanantwerpen Jun 1, 2023
a838d6e
convert: push and pop with explicit values
hendrikvanantwerpen Jun 1, 2023
b3179de
convert: more references and definitions
hendrikvanantwerpen Jun 1, 2023
2f2a4cc
convert: edge precedence
hendrikvanantwerpen Jun 1, 2023
90399c7
convert: drop
hendrikvanantwerpen Jun 1, 2023
cfc004a
convert: endpoint
hendrikvanantwerpen Jun 1, 2023
b14aba9
convert: definiens
hendrikvanantwerpen Jun 1, 2023
129aa5d
convert: syntax type
hendrikvanantwerpen Jun 1, 2023
dba45d9
convert: jump
hendrikvanantwerpen Jun 1, 2023
6bb4d57
convert: nodes
hendrikvanantwerpen Jun 1, 2023
da3728c
convert: scoped variables
hendrikvanantwerpen Jun 1, 2023
39c2624
convert: root
hendrikvanantwerpen Jun 1, 2023
8e05b65
convert: captures
hendrikvanantwerpen Jun 1, 2023
10e33f7
convert: module ref and def
hendrikvanantwerpen Jun 2, 2023
ff21d32
convert: global/global_dot
hendrikvanantwerpen Jun 2, 2023
fb9e45c
convert: syntax nodes as graph nodes
hendrikvanantwerpen Jun 2, 2023
e614b60
convert: super scope
hendrikvanantwerpen Jun 2, 2023
cd0255c
convert: duplicate edge
hendrikvanantwerpen Jun 2, 2023
307e03c
convert: duplicate stanza
hendrikvanantwerpen Jun 2, 2023
861fbca
convert: one more syntax node used directly as grap hnode
hendrikvanantwerpen Jun 2, 2023
7aa54c8
convert: toplevel dummy values for inherited variables
hendrikvanantwerpen Jun 2, 2023
1624d70
convert: duplicate attribute
hendrikvanantwerpen Jun 2, 2023
5318655
convert: graph node for argument_list
hendrikvanantwerpen Jun 2, 2023
ec0f61b
convert: function name
hendrikvanantwerpen Jun 2, 2023
3859536
convert: export scope
hendrikvanantwerpen Jun 2, 2023
02f4b5e
convert: function name
hendrikvanantwerpen Jun 2, 2023
6e39e4a
convert: argument lists
hendrikvanantwerpen Jun 2, 2023
ac61586
convert: duplicate edges
hendrikvanantwerpen Jun 2, 2023
a127916
convert: duplicate edges
hendrikvanantwerpen Jun 2, 2023
6407b1d
convert: always create .args
hendrikvanantwerpen Jun 2, 2023
d5d312e
Enable tests
hendrikvanantwerpen Jun 2, 2023
8d8c7e0
convert: comment out syntax_type and definiens_node which are not yet…
hendrikvanantwerpen Jun 2, 2023
e44bad9
Re-enable syntax_type and definiens_node
hendrikvanantwerpen Nov 15, 2023
5a63def
Don't crash visualization on self edges
hendrikvanantwerpen Nov 15, 2023
fe70ba0
Cleanup accidental self loop
hendrikvanantwerpen Nov 15, 2023
dbfb172
Fix module start lines and do not expect definitions at assertion pos…
hendrikvanantwerpen Nov 15, 2023
2d8fd6b
Factor out identifier rules
hendrikvanantwerpen Nov 15, 2023
fd57fbd
Add bug test
hendrikvanantwerpen Nov 15, 2023
2f619fa
Fix Python grammar versions
hendrikvanantwerpen Nov 15, 2023
aae723f
Remove obsolete nodes because of general identifier rules
hendrikvanantwerpen Nov 15, 2023
0b54f6c
Fix rule to make it similar to others
hendrikvanantwerpen Nov 15, 2023
a899983
Reuse general definition for parameters
hendrikvanantwerpen Nov 15, 2023
1668eec
Lower .before_scope and .after_scope
hendrikvanantwerpen Nov 15, 2023
e1a0dcf
Lower .input and .output
hendrikvanantwerpen Nov 15, 2023
94365dc
Lower more nodes
hendrikvanantwerpen Nov 15, 2023
bb0f034
Lower final set of nodes
hendrikvanantwerpen Nov 15, 2023
d15cb9b
Add tests
hendrikvanantwerpen Nov 17, 2023
34eba6e
Update README
hendrikvanantwerpen Jan 18, 2024
c23f7ca
Upgrade Python and reorganize rules according to syntax categories
hendrikvanantwerpen Nov 16, 2023
41c8f32
Reorganize imports
hendrikvanantwerpen Nov 17, 2023
9135ff5
Fix parameter definitions
hendrikvanantwerpen Nov 30, 2023
0f4bf9b
Fixes for pattern identifiers
hendrikvanantwerpen Nov 30, 2023
cd9f3eb
Merge pull request #358 from github/upgrade-python
BekaValentine Jan 29, 2024
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
3 changes: 3 additions & 0 deletions languages/tree-sitter-stack-graphs-python/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*.html
/Cargo.lock
/target
6 changes: 6 additions & 0 deletions languages/tree-sitter-stack-graphs-python/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Changelog for tree-sitter-stack-graphs-python

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
38 changes: 38 additions & 0 deletions languages/tree-sitter-stack-graphs-python/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
[package]
name = "tree-sitter-stack-graphs-python"
version = "0.1.0"
description = "Stack graphs definition for Python using tree-sitter-python"
readme = "README.md"
keywords = ["tree-sitter", "stack-graphs", "python"]
authors = [
"GitHub <[email protected]>",
]
license = "MIT OR Apache-2.0"
edition = "2018"

[[bin]]
name = "tree-sitter-stack-graphs-python"
path = "rust/bin.rs"
required-features = ["cli"]

[lib]
path = "rust/lib.rs"
test = false

[[test]]
name = "test"
path = "rust/test.rs"
harness = false

[features]
cli = ["anyhow", "clap", "tree-sitter-stack-graphs/cli"]

[dependencies]
anyhow = { version = "1.0", optional = true }
clap = { version = "4", optional = true, features = ["derive"] }
tree-sitter-stack-graphs = { version = "0.7", path = "../../tree-sitter-stack-graphs" }
tree-sitter-python = "=0.20.4"

[dev-dependencies]
anyhow = "1.0"
tree-sitter-stack-graphs = { version = "0.7", path = "../../tree-sitter-stack-graphs", features = ["cli"] }
Empty file.
138 changes: 138 additions & 0 deletions languages/tree-sitter-stack-graphs-python/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
# tree-sitter-stack-graphs definition for Python

This project defines tree-sitter-stack-graphs rules for Python using the [tree-sitter-python][] grammar.

[tree-sitter-python]: https://crates.io/crates/tree-sitter-python

- [API documentation](https://docs.rs/tree-sitter-stack-graphs-python/)
- [Release notes](https://github.com/github/stack-graphs/blob/main/languages/tree-sitter-stack-graphs-python/CHANGELOG.md)

## Using the API

To use this library, add the following to your `Cargo.toml`:

```toml
[dependencies]
tree-sitter-stack-graphs-python = "0.1.0"
```

Check out our [documentation](https://docs.rs/tree-sitter-stack-graphs-python/*/) for more details on how to use this library.

## Using the Command-line Program

The command-line program for `tree-sitter-stack-graphs-python` lets you do stack graph based analysis and lookup from the command line.

The CLI can be run as follows:

1. _(Installed)_ Install the CLI using Cargo as follows:

```sh
cargo install --features cli tree-sitter-stack-graphs-python
```

After this, the CLI should be available as `tree-sitter-stack-graphs-python`.

2. _(From source)_ Instead of installing the CLI, it can also be run directly from the crate directory, as a replacement for a `tree-sitter-stack-graphs-python` invocation, as follows:

```sh
cargo run --features cli --
```

The basic CLI workflow for the command-line program is to index source code and issue queries against the resulting database:

1. Index a source folder as follows:

```sh
tree-sitter-stack-graphs-python index SOURCE_DIR
```

_Indexing will skip any files that have already be indexed. To force a re-index, add the `-f` flag._

To check the status if a source folder, run:

```sh
tree-sitter-stack-graphs-python status SOURCE_DIR
```

To clean the database and start with a clean slate, run:

```sh
tree-sitter-stack-graphs-python clean
```

_Pass the `--delete` flag to not just empty the database, but also delete it. This is useful to resolve `unsupported database version` errors that may occur after a version update._

2. Run a query to find the definition(s) for a reference on a given line and column, run:

```sh
tree-sitter-stack-graphs-python query definition SOURCE_PATH:LINE:COLUMN
```

Resulting definitions are printed, including a source line if the source file is available.

Discover all available commands and flags by passing the `-h` flag to the CLI directly, or to any of the subcommands.

## Development

The project is written in Rust, and requires a recent version installed. Rust can be installed and updated using [rustup][].

[rustup]: https://rustup.rs/

The project is organized as follows:

- The stack graph rules are defined in `src/stack-graphs.tsg`.
- Builtins sources and configuration are defined in `src/builtins.it` and `builtins.cfg` respectively.
- Tests are put into the `test` directory.

### Running Tests

Run the tests as follows:

```sh
cargo test
```

The project consists of a library and a CLI. By default, running `cargo` only applies to the library. To run `cargo` commands on the CLI as well, add `--features cli` or `--all-features`.

Run the CLI from source as follows:

```sh
cargo run --features cli -- ARGS
```

Sources are formatted using the standard Rust formatted, which is applied by running:

```sh
cargo fmt
```

### Writing TSG

The stack graph rules are written in [tree-sitter-graph][]. Checkout the [examples][],
which contain self-contained TSG rules for specific language features. A VSCode
[extension][] is available that provides syntax highlighting for TSG files.

[tree-sitter-graph]: https://github.com/tree-sitter/tree-sitter-graph
[examples]: https://github.com/github/stack-graphs/blob/main/tree-sitter-stack-graphs/examples/
[extension]: https://marketplace.visualstudio.com/items?itemName=tree-sitter.tree-sitter-graph

Parse and test a single file by executing the following commands:

```sh
cargo run --features cli -- parse FILES...
cargo run --features cli -- test TESTFILES...
```

Generate a visualization to debug failing tests by passing the `-V` flag:

```sh
cargo run --features cli -- test -V TESTFILES...
```

To generate the visualization regardless of test outcome, execute:

```sh
cargo run --features cli -- test -V --output-mode=always TESTFILES...
```

Go to <https://crates.io/crates/tree-sitter-stack-graphs> for links to examples and documentation.
32 changes: 32 additions & 0 deletions languages/tree-sitter-stack-graphs-python/rust/bin.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// -*- coding: utf-8 -*-
// ------------------------------------------------------------------------------------------------
// Copyright © 2023, stack-graphs authors.
// Licensed under either of Apache License, Version 2.0, or MIT license, at your option.
// Please see the LICENSE-APACHE or LICENSE-MIT files in this distribution for license details.
// ------------------------------------------------------------------------------------------------

use anyhow::anyhow;
use clap::Parser;
use tree_sitter_stack_graphs::cli::database::default_user_database_path_for_crate;
use tree_sitter_stack_graphs::cli::provided_languages::Subcommands;
use tree_sitter_stack_graphs::NoCancellation;

fn main() -> anyhow::Result<()> {
let lc = match tree_sitter_stack_graphs_python::try_language_configuration(&NoCancellation) {
Ok(lc) => lc,
Err(err) => {
eprintln!("{}", err.display_pretty());
return Err(anyhow!("Language configuration error"));
}
};
let cli = Cli::parse();
let default_db_path = default_user_database_path_for_crate(env!("CARGO_PKG_NAME"))?;
cli.subcommand.run(default_db_path, vec![lc])
}

#[derive(Parser)]
#[clap(about, version)]
pub struct Cli {
#[clap(subcommand)]
subcommand: Subcommands,
}
48 changes: 48 additions & 0 deletions languages/tree-sitter-stack-graphs-python/rust/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// -*- coding: utf-8 -*-
// ------------------------------------------------------------------------------------------------
// Copyright © 2023, stack-graphs authors.
// Licensed under either of Apache License, Version 2.0, or MIT license, at your option.
// Please see the LICENSE-APACHE or LICENSE-MIT files in this distribution for license details.
// ------------------------------------------------------------------------------------------------

use tree_sitter_stack_graphs::loader::LanguageConfiguration;
use tree_sitter_stack_graphs::loader::LoadError;
use tree_sitter_stack_graphs::CancellationFlag;

/// The stack graphs tsg source for this language.
pub const STACK_GRAPHS_TSG_PATH: &str = "src/stack-graphs.tsg";
/// The stack graphs tsg source for this language.
pub const STACK_GRAPHS_TSG_SOURCE: &str = include_str!("../src/stack-graphs.tsg");

/// The stack graphs builtins configuration for this language.
pub const STACK_GRAPHS_BUILTINS_CONFIG: &str = include_str!("../src/builtins.cfg");
/// The stack graphs builtins path for this language
pub const STACK_GRAPHS_BUILTINS_PATH: &str = "src/builtins.py";
/// The stack graphs builtins source for this language.
pub const STACK_GRAPHS_BUILTINS_SOURCE: &str = include_str!("../src/builtins.py");

/// The name of the file path global variable.
pub const FILE_PATH_VAR: &str = "FILE_PATH";

pub fn language_configuration(cancellation_flag: &dyn CancellationFlag) -> LanguageConfiguration {
try_language_configuration(cancellation_flag).unwrap_or_else(|err| panic!("{}", err))
}

pub fn try_language_configuration(
cancellation_flag: &dyn CancellationFlag,
) -> Result<LanguageConfiguration, LoadError> {
LanguageConfiguration::from_sources(
tree_sitter_python::language(),
Some(String::from("source.py")),
None,
vec![String::from("py")],
STACK_GRAPHS_TSG_PATH.into(),
STACK_GRAPHS_TSG_SOURCE,
Some((
STACK_GRAPHS_BUILTINS_PATH.into(),
STACK_GRAPHS_BUILTINS_SOURCE,
)),
Some(STACK_GRAPHS_BUILTINS_CONFIG),
cancellation_flag,
)
}
23 changes: 23 additions & 0 deletions languages/tree-sitter-stack-graphs-python/rust/test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// -*- coding: utf-8 -*-
// ------------------------------------------------------------------------------------------------
// Copyright © 2023, stack-graphs authors.
// Licensed under either of Apache License, Version 2.0, or MIT license, at your option.
// Please see the LICENSE-APACHE or LICENSE-MIT files in this distribution for license details.
// ------------------------------------------------------------------------------------------------

use anyhow::anyhow;
use std::path::PathBuf;
use tree_sitter_stack_graphs::ci::Tester;
use tree_sitter_stack_graphs::NoCancellation;

fn main() -> anyhow::Result<()> {
let lc = match tree_sitter_stack_graphs_python::try_language_configuration(&NoCancellation) {
Ok(lc) => lc,
Err(err) => {
eprintln!("{}", err.display_pretty());
return Err(anyhow!("Language configuration error"));
}
};
let test_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("test");
Tester::new(vec![lc], vec![test_path]).run()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[globals]
Empty file.
Loading
Loading