Commit graph

776 commits

Author SHA1 Message Date
Zsolt Dollenstein
5f22b6c438
bump version to 0.4.0 2022-01-12 19:51:51 +00:00
Steven Troxler
122627cabc
Codemod for PEP 484 Assign w / type comments -> PEP 526 AnnAssign (#594)
* Codemod for PEP 484 Assign w / type comments -> PEP 526 AnnAssign

Summary:

This codemod is intended to eventually handle all type comments from
PEP 484. This is a partial implementation specifically handling
assignment type comments, which as of PEP 526 are better dealt
with using AnnAssign nodes.

There is more work to do because there are two other kinds of
comments to support: function heading comments and function parameter
inline comments. But the PEP 526 functionality is complete so I feel
like it's worth havign a PR / CI signals / code review at this stage.

Test Plan:

```
python -m unittest libcst.codemod.commands.tests.test_convert_type_comments
```

* Disable on python 3.6, 3.7

The ast module didn't get the `type_comment` information we need
until python 3.8.

It is possible but not a priority right now to enable 3.6 and 3.7
via the typed_ast library, for now I just throw a NotImplementedError
with a nice description. There's a note in the code about where to look
for a typed_ast example in case anyone wants to add support in the
future.

* Fix type errors on the 3.8+ testing fix

* Do a better job of complaining on Python < 3.8

* Updates based on code review

Summary:

Do not strip type comments in the visitor pattern; instead,
reach down from the parent to do it because this makes it
much more reliable that we won't accidentally remove
other comments in a codemod (using visitor state to do this
isn't really feasible once we handle complex statements like
FunctionDef, With, For).

Handle multi-statement statement lines; this works since the
trailing whitespace can only apply to the final statement on
the line. It's not really a critical edge case to handle, but
the code is no more complicated so we might as well.

* Prevent comment stripping for multi-assign

* Note in the docstring that this is a limited WIP

* Reorder checks so the next step will be cleaner
2022-01-12 09:34:01 -08:00
Martin DeMello
31ba5bf583
Remove unused argument to handle_Index (#595) 2022-01-11 16:59:46 -08:00
Martin DeMello
8a7c13ff36
Use precise signature matching when inserting function type annotations (#591)
* Use precise signature matching when inserting function type annotations

* add type annotations

* Add an argument for strict annotation matching.

* don't use Any
2022-01-10 12:41:21 -08:00
Steven Troxler
1937fbf47d
Add a Building subsection to the Developing docs (#593)
* Add a build section to the docs

* Tweaks based on code review
2022-01-09 08:32:13 -08:00
Martin DeMello
8652974d87
Support relative imports in AddImportsVisitor. (#585)
* Support relative imports in AddImportsVisitor.

* Adds an Import dataclass to represent a single imported object
* Refactors AddImportsVisitor to pass around Import objects
* Separates out the main logic in get_absolute_module_for_import so that
  it can be used to resolve relative module names outside of a cst.Import
  node
* Resolves relative module names in AddImportsVisitor if we have a
  current module name set.

Fixes #578
2022-01-08 10:18:10 +00:00
Steven Troxler
1337022770
[WIP] Support Parenthesized With Statements (#584)
On the python side, we can add parentheses from MaybeSentinel.DEFAULT if the whitespace requires it.

On the rust side, we support the new grammar but codegen will only add explicitly included parentheses for now - it should be possible to match python behavior but it's not urgent so I've left a TODO
2022-01-07 12:21:58 -08:00
Luke Petre
9f6ff017f2
Use pyre site-package feature (#589)
* Use pyre site-package feature
* Update readme, remove example
2022-01-07 07:34:50 -05:00
Steven Troxler
2f75246c3a
Fix variable name in lambda (#590) 2022-01-07 09:29:51 +00:00
Luke Petre
6434ca8512
Remove tox references (#588) 2022-01-06 21:09:27 -05:00
Luke Petre
2f7f174daa
Remove setup matrix (#586) 2022-01-06 11:26:12 -05:00
Zsolt Dollenstein
6615ccb0ce
pin to git rev (#587) 2022-01-06 15:56:14 +00:00
Steven Troxler
3578f2fc3d
Add some color to children-vs-codegen error (#583)
It took me some time to track down the root cause of `children`
not matching codegen, having the error message directly hint that
visit and codegen are probably mimatched (my visit was running
out-of-order) will likely help newbies get going faster.
2022-01-05 21:26:51 +00:00
Steven Troxler
601db54880
Add instructions to codegen test failures (#582)
* Add instructions to codegen test failures

* Run ufmt

* Fix lint errors, mention tox -e codegen
2022-01-05 12:24:31 -08:00
Zsolt Dollenstein
d9a1dc8473
Fix all type errors (#579)
* bump pyre version
* make sure CI-pyre uses working copy
* remove unused pyre suppressions
* suppress invalid decorations
* fix undefined attributes
* fix missing return annotations
* fix tuple concatenation issues
* add native stubs
* fix invalid typing of **kwargs in test_apply_type_annotations
* only install pyre on non-windows
* update test fixture to reflect changes in recent pyre versions
* suppress errors related to mismatched positions
2022-01-05 18:13:01 +00:00
Zsolt Dollenstein
73ecdf45c3
only run CI on pushes to main and pull requests (#581) 2022-01-05 17:09:30 +00:00
Zsolt Dollenstein
b939bf2998
run tests with 3.10 too (#577) 2022-01-05 15:43:43 +00:00
Zsolt Dollenstein
86431eea89
Make sure dedents are emitted for inputs without trailing newlines (#573) 2022-01-04 20:04:21 +00:00
Zsolt Dollenstein
cff47b767b
fix python version in pypi upload step (#576) 2022-01-04 20:03:59 +00:00
Zsolt Dollenstein
b5fb9d79c5
Fix pypi upload CI step (#570)
* pass in LIBCST_NO_LOCAL_SCHEME to CIBW

* only build a source tarball on one platform

* factor out upload into a separate job
2022-01-04 17:01:09 +00:00
Zsolt Dollenstein
9932a6d339
Implement PEP-634 - Match statement (#568)
* ParenthesizedNode implementation for Box

* match statement rust CST and grammar

* match statement python CST and docs

* run rust unit tests in release mode for now
2021-12-30 10:00:51 +00:00
Zsolt Dollenstein
67db03915d
implement PEP-654: except* (#571) 2021-12-29 21:23:46 +00:00
Zsolt Dollenstein
c44ff0500b
Fix license headers (#560)
* Facebook -> Meta

* remove year from doc copyright
2021-12-28 11:55:18 +00:00
Zsolt Dollenstein
9c13ca5f9c
pin checkout action to v1 (#569) 2021-12-23 11:51:41 -05:00
Steven Troxler
1d1b7da05f
.gitignore shared-object built artifacts (#567) 2021-12-22 20:56:12 +00:00
John Reese
10c3aa09a7
Upgrade to µsort 1.0.0rc1, and apply formatting changes (#565)
* Upgrade to usort==1.0.0rc1

* Apply sorting changes from usort 1.0.0rc1

* reapply codegen

Co-authored-by: Zsolt Dollenstein <zsol.zsol@gmail.com>
2021-12-21 14:55:04 -08:00
Zsolt Dollenstein
c02de9b718
Implement a Python PEG parser in Rust (#566)
This massive PR implements an alternative Python parser that will allow LibCST to parse Python 3.10's new grammar features. The parser is implemented in Rust, but it's turned off by default through the `LIBCST_PARSER_TYPE` environment variable. Set it to `native` to enable. The PR also enables new CI steps that test just the Rust parser, as well as steps that produce binary wheels for a variety of CPython versions and platforms.

Note: this PR aims to be roughly feature-equivalent to the main branch, so it doesn't include new 3.10 syntax features. That will be addressed as a follow-up PR.

The new parser is implemented in the `native/` directory, and is organized into two rust crates: `libcst_derive` contains some macros to facilitate various features of CST nodes, and `libcst` contains the `parser` itself (including the Python grammar), a `tokenizer` implementation by @bgw, and a very basic representation of CST `nodes`. Parsing is done by
1. **tokenizing** the input utf-8 string (bytes are not supported at the Rust layer, they are converted to utf-8 strings by the python wrapper)
2. running the **PEG parser** on the tokenized input, which also captures certain anchor tokens in the resulting syntax tree
3. using the anchor tokens to **inflate** the syntax tree into a proper CST

Co-authored-by: Benjamin Woodruff <github@benjam.info>
2021-12-21 18:14:39 +00:00
Zsolt Dollenstein
9d611f9733
bump version to 0.3.23 2021-11-23 12:53:42 +00:00
Luke Petre
58b447d8f7
Fixes incorrectly missing annotations (#561)
Co-authored-by: Zsolt Dollenstein <zsol.zsol@gmail.com>
2021-11-23 11:08:23 +00:00
Zsolt Dollenstein
3895925f15
bump version to 0.3.22 2021-11-22 14:06:19 +00:00
Luke Petre
d0f8fa97e2
Remove remnants of circleci (#552) 2021-11-19 15:04:02 +00:00
Giorgi Megreli
c48cc2101a
Move find_qualified_names_for in the Assignment class. (#557)
Move _NameUtil.find_qualified_name_for ... method inside Assignment classes.
2021-11-19 14:58:50 +00:00
Giorgi Megreli
9732f5ec82
Correct and simplify logic of recording assignments (#556) 2021-11-19 07:21:06 -05:00
Giorgi Megreli
ae8d0cda2f
Pin accesses to import alias node (#554)
* Add ImportAssignment class and record it from Scope

* Add overrides for LocalScope and ClassScope

* Clean scope_provider code and use ImportAssignment class in `unusued_imports` codemod

* Add missing types

* Fix fixit errors
2021-11-19 11:20:47 +00:00
Luke Petre
463f15e805
Test overwriting imports w/ global and nonlocal stmts (#553) 2021-11-18 17:08:19 -05:00
Zsolt Dollenstein
2cd43c4b78
disable setuptools local scheme when env var is set (#551) 2021-11-18 15:00:06 +00:00
Luke Petre
5c05001c2d
Publish test packages (#550) 2021-11-18 09:03:27 +00:00
Luke Petre
56386d7add
Stop parsing string annotations when no longer in a typing call (#546)
* Fix ScopeProvider when string type annotation is unparsable

* Handle nested function calls w/in type declarations

* Edit stack in place

* Add unparsed test to test_cast
2021-11-17 16:12:02 -05:00
Luke Petre
7db6ec5384
Swallow parsing errors in string annotations. (#548)
* Swallow parsing errors in string annotations.

This is the same behavior as cPython.

I've also rewritten the test that was relying on this exception to check where type parsing was happening

* Fix pyre error
2021-11-17 15:08:52 -05:00
Luke Petre
3e798726ec
Pass absolute path to codemod test (#549) 2021-11-17 14:37:53 -05:00
Luke Petre
70ff0f2182
Upgrade black to fix errors in 3.9.8 (#547) 2021-11-10 12:15:18 -05:00
Steven Troxler
182586cf5b
Support relative imports in ATAV qualifier handling (#538)
Based on diff review of https://github.com/Instagram/LibCST/pull/536,
I investigated relatvie import handling and realized that with minor
changes we can now handle them correctly.

Relative imports aren't likely in code coming from an automated
tool, but they could happen in hand-written stubs if anyone tries
to use this codemod tool to merge stubs with code.

Added a new test:
```
> python -m unittest libcst.codemod.visitors.tests.test_apply_type_annotations
.............................................
----------------------------------------------------------------------
Ran 45 tests in 2.195s

OK

```
2021-11-10 10:33:57 +00:00
Luke Petre
3dbcf5fed7
Don't gather metadata if the wrapper already contains it (#545)
Make sure that the MetadataWrapper to resolves the requested providers vs the existing metadata results and prevent a single provider from being invoked multiple times.
2021-11-08 15:34:24 -05:00
Steven Troxler
3ccfc4adc8
Fix typing errors on ATAV (#542) 2021-11-02 14:06:45 -05:00
Steven Troxler
a352d56970 Support use_future_annotations in ApplyTypeAnnotationsVisitor
Note: I'm pushing this because it works, but I actually want to
add annotation counting first and then modify the code so that we
only add the import if an annotation was actually included.
2021-10-30 11:57:19 -04:00
Steven Troxler
87625d02b6 Do not add imports if we added no type info in ATAV
In ApplyTypeAnnotationsVisitor, there are edge cases where we
might have changed the module imports even though we never wound
up applying any type annotations.

This will become even more common if we support adding
`from __future__ import annotations`, which I would like to do
soon.

To handle this, we can simply return the original tree from
`transform_module_impl` (discarding any changes from either
`self` or `AddImportsVisitor`) whenever there are no changes
in `self.annotation_counts`.

I updated the no-annotations-changed test to reflect this:
```
> python -m unittest libcst.codemod.visitors.tests.test_apply_type_annotations.TestApplyAnnotationsVisitor
...............................................
----------------------------------------------------------------------
Ran 47 tests in 2.312s

OK
```
2021-10-28 19:11:46 -04:00
Steven Troxler
3743c702dc
Use QualifiedNameProvider to handle stub types (#536)
The existing TypeCollector visitor logic attempted to
fold actual imports from stubs together with the module
we were annotating, and separately do nice things with the
names of types so that we could parse stubs written either
with various sorts of proper imports *or* stubs written
using bare fully-qualified type names (which isn't
actually legal python, but is easy to produce from automated
tools like `pyre infer`).

In this commit I simplify things in principle - meaning the
data flow is simpler, although the code is still similarly
complex - by using `QualifiedNameProvider` plus a fallback
to `get_full_name_for_node` to handle all cases via
fully-qualified names, so that the way a stub chooses to
lay out its imports is no longer relevant to how we will
understand it.

As a result, we can scrap a whole test suite where we
were understanding edge cases in the import handling, and
moreover one of the weird unsupported edge cases is now
well supported.

The tests got simpler because some edge cases no longer
matter (the whole imports test is no longer relevant),
and a couple of weird edge cases were fixed.

I ran tests with
```
python -m unittest libcst.codemod.visitors.tests.test_apply_type_annotations.TestApplyAnnotationsVisitor
```

I tried to make this change minimal in that I preserve the
existing data flow, so that it's easy to review. But it's worth
considering whether to follow up with a diff where we change
the TypeAnnotationCollector into a *transform* rather than a
*visitor*, because that would allow us to scrap quite a bit
of logic - all we would need to know is a couple of bits
of context from higher up in the tree and we could process
Names and Attributes without needing all this recursion.
2021-10-28 13:46:18 -04:00
Steven Troxler
1f169b8b8d
Count the information we add in ApplyTypeAnnotationsVisitor (#537)
Refactor ApplyTypeAnnotationsVisitor so that all annotation
information is added via a smart constructor method starting
with `_apply_annotation_to`. This makes it much easier to
skim the code and understand where annotations are actually
added with a simple forward search.

Then, add an AnnotationCounts dataclass and count up all the
annotations we add inside the transform. This should be helpful
for a few reasons:
- First, it just makes counting the annotations easier. Prior
  to this change, we would have to run some separate command
  to count annotations before and after a codemod, which is
  not as convenient as doing it directly, and would also fail
  to account for cases where we changed an annotation.
- Second, I want to be able to avoid altering the import
  statements in cases where we never actually made any changes.
  Having annotation counts will help us do this - we can just
  return the original tree (without import changes) in that
  situtation.

```
> python -m unittest libcst.codemod.visitors.tests.test_apply_type_annotations.TestApplyAnnotationsVisitor
................................................
----------------------------------------------------------------------
Ran 48 tests in 1.773s

OK
```

(
2021-10-28 12:46:57 -04:00
Steven Troxler
14eff6aaf5
Remove a dead method in ApplyTypeAnnotationsVisitor (#533)
I'm not really sure how the method got there, but it was calling
itself recursively... fortunately, it was also overwritten by
an identically named method so it was actually impossible to access.
2021-10-27 11:08:38 -04:00
Zac Hatfield-Dodds
1e0d4841bf
Fix m.OneOf() docs (#529)
Closes #345.
2021-10-20 22:25:59 -07:00