-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
Code Completion: Adding stub generator utility (and generated stub) #1939
Conversation
Great! A couple things I saw:
This can of course be discussed |
@KaylaHood @Viicos Is it going to happen something with this pr? Missing code completion is a big drawback :( |
Sorry, I totally forgot to revisit this PR after I got the comment from Viicos.
|
Sorry, I meant in the generated stub file.
I can look into that.
Ah in that case it makes sense, I thought at first that only the non locale-specific methods were available. Maybe worth double checking this. Other than that, the script looks good, but feels a bit hacky and could potentially lead to invalid syntax. I think a more robust implementation could be done using ast/cst, but that can be time consuming to implement. If I have time some day, I can come up with an implementation (but for later, sticking with your implementation is fine for now!) |
I removed the attributes from the stub file and I added a recipe for
Yes, this was intended as a quick hack to get the autocomplete working for me while I wrote unit tests. I figured it'd be useful to the others on the issue thread who were having the same frustration. If you'd like to improve it, please be my guest! |
I made sure to include all the available locales in my stub generator (see lines 85-91) |
If the stubs are to be committed to the repo, then I would add We should alse update our contributing docs to mention running the task when submitting new PRs |
…o adding ``make lint`` to the Contributing guide.
Sorry for another delay, I was away on holiday. I've made the changes you suggested, can you check them out? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work! Thank you!
Thank you @KaylaHood! Does it make sense to try to add a unittest which verifies all the expected methods are present in the stub? |
:param state_abbr: A state abbreviation | ||
""" | ||
... | ||
def random_choices(self, elements: Union[Collection[str], Collection[T], collections.OrderedDict[T, float]] = ..., length: Optional[int] = ...) -> Sequence[T]: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Neither Collection
nor collections
appear in the imports
:sample: base='120004', number_system_digit=0, safe_mode=False | ||
""" | ||
... | ||
def color(self, hue: Optional[HueType] = ..., luminosity: Optional[str] = ..., color_format: str = ...) -> str: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
HueType
isn't imported
:sample: size=(16, 16), hue=[90,270], image_format='ico' | ||
""" | ||
... | ||
def json(self, data_columns: Optional[List] = ..., num_rows: int = ..., indent: Optional[int] = ..., cls: Optional[Type[json.encoder.JSONEncoder]] = ...) -> str: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
json
isn't imported
to that method. | ||
""" | ||
... | ||
def credit_card_full(self, card_type: Optional[CardType] = ...) -> str: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CardType
isn't imported
:example: datetime.time(15, 56, 56, 772876) | ||
""" | ||
... | ||
def time_series(self, start_date: Union[datetime.date, datetime.datetime, datetime.timedelta, str, int] = ..., end_date: Union[datetime.date, datetime.datetime, datetime.timedelta, str, int] = ..., precision: Optional[float] = ..., distrib: Optional[Callable[[datetime.datetime], float]] = ..., tzinfo: Optional[datetime.tzinfo] = ...) -> Iterator[Tuple[datetime.datetime, Any]]: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Callable
isn't imported
from faker.generator import Generator | ||
|
||
T = TypeVar("T") | ||
TEnum = TypeVar("TEnum", bound=Enum) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
T
and TEnum
are redeclared after they are imported.
num_rows=10, include_row_ids=True | ||
""" | ||
... | ||
def uuid4(self, cast_to: Union[Callable[[uuid.UUID], str], Callable[[uuid.UUID], bytes], None] = ...) -> Union[bytes, str, uuid.UUID]: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
uuid
isn't imported
MODULES_TO_FULLY_QUALIFY = ["datetime"] | ||
|
||
|
||
imports: Dict[str, Optional[Set[str]]] = defaultdict(lambda: None) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Annotation should use DefaultDict
instead of Dict
In fact, if you change the line to the following,
imports: DefaultDict[str, Set[str]] = defaultdict(set)
it will fix one of the mypy errors: Unsupported right operand type for in ("set[str] | None")
prov_cls, _, _ = Factory._find_provider_class(provider, locale) | ||
classes_and_locales_to_use_for_stub.append((prov_cls, locale)) | ||
|
||
all_members: List[Tuple[UniqueMemberFunctionsAndVariables, str]] = \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be List[Tuple[UniqueMemberFunctionsAndVariables, Optional[str]]]
since the last item in the list has None
in it.
signatures_with_comments.append((f"def {func_name}{sig_str}: ...", None if comment == "" else comment, False)) | ||
|
||
signatures_with_comments_as_str = [] | ||
for sig, comment, is_preceding_comment in signatures_with_comments: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mypy errors because it infers sig
is Signature
from line 110 instead of str
. Easiest solution would be to rename this variable.
new_parm = parm_val.replace(default=...) | ||
if (new_parm.annotation is not inspect.Parameter.empty | ||
and not new_parm.annotation.__module__ in BUILTIN_MODULES_TO_IGNORE): | ||
module, member = get_module_and_member_to_import(new_parm.annotation, locale) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like the reason a bunch of imports are missing is this function doesn't look inside annotations. So whenever Union[x, y]
occurs, it doesn't grab x & y.
... | ||
def __setstate__(self, state: Any) -> None: ... | ||
def items(self) -> List[Tuple[str, Generator]]: ... | ||
def seed(seed: Union[int, float, str, bytes, bytearray, None] = ...) -> None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
signature for this doesn't match. It's supposed to be a classmethod.
I tweaked generate_stub.py to fix the issues with missing imports, staticmethods, and classmethods. I took the liberty of removing the docstrings as they aren't needed in a stub. They can easily be re-enabled by flipping these lines: I'm not 100% it's covering all the methods without a unittest. One final thought; it seems like it could be handy to create a stub for |
I went and made a branch with the changes I suggested above. (personal account vs work account). I even got the black and isort formatting included in the generate_stubs.py. If you'd like I can create a new PR with the updates. |
i've been following this PR, i would really like for it to make into master that's why im leaving this message.. having these stubs would be really helpful |
@KaylaHood do you want to ingrate @bandophahita's changes into your branch? |
@fcurella I think I'd prefer to merge this PR without @bandophahita's changes and then have them make a new PR with their changes, which can be reviewed separately. This way he gets the recognition for his improvements. |
@bandophahita ball's in your court! 🙂 |
@KaylaHood While I appreciate the gesture, I would say if it is easier feel free to integrate. edit: missed that it was already merged. I'll make a PR |
i dont understand what did you say how i can active the type hint showing in vs code any tutorials or articles |
What does this change
The generate_stubs.py script creates a stub file, proxy.pyi, and saves it to the faker package's directory. This stub file contains extracted method declarations and docstrings (pulled from the providers) which are used by IDEs to provide code completion.
What was wrong
Because the provider classes are "dynamically" linked at runtime, IDEs can't get a list of available faker methods to display as code completion suggestions.
How this fixes it
Description of how the changes fix the issue.
Fixes #...
Generate a stub file (proxy.pyi) using the utility script (generate_stubs.py) to help IDEs provide code completion to developers.