-
Notifications
You must be signed in to change notification settings - Fork 36
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
detect instance variables in constructor #7
Comments
To detect instance variables, The class should be instantiated first. For example, from inspect import signature, Parameter
from unittest import mock
def instantiate_class(class_type):
params = []
for p, v in signature(class_type.__init__).parameters.items():
if p == 'self': continue
if v.kind == Parameter.POSITIONAL_ONLY or v.kind == Parameter.POSITIONAL_OR_KEYWORD:
if v.default is not Parameter.empty: # default value exists
if v.default is not None: # and not None
params.append(v.default)
else:
if v.annotation == Parameter.empty: # value type is not specified
spec = None
else:
spec = find_class_type(v.annotation)
params.append(mock.MagicMock(spec=spec))
obj = class_type(*params)
return obj
|
yes it is an approach that can be followed. The one I am following in my current work is to process the AST of the constructor and detect |
Sry but I don't understand what you mean. If I have a class
How can I create the correct UML? |
in this case, the class test has 2 class attributes and no instance attribute. The value of If you want instance attributes, the code should be: class Test:
def __init__(self, string_1: str, string_2: str):
self.string_1 = string_1
self.string_2 = string_2 And if you want instance attributes with default values: class Test:
def __init__(self, string_1: str = 'String 1', string_2: str = 'String 2'):
self.string_1 = string_1
self.string_2 = string_2 When I started this library, it was mainly to create a class diagram of dataclasses. The |
Okay, I understand. But I think this could be a really great tool. |
Followings are the code that gets instance variables from the class definition code. class Address(object):
street: str
zipcode: str
city: str
class Worker:
name: str
# forward refs are skipped for now
colleagues: List['Worker']
def __init__(self):
self.addr: Address
self.address: Address = Address()
self.old_addr = Address()
self.cons = []
self.cons[0] = 0
self.age = self.max_age = 0
flag = 0
self.age += 1
addr = Address()
def func(self, age):
self.your_age = age
return self.age
"""
import ast
import pprint
p=ast.parse(code)
for cls in p.body:
if isinstance(cls, ast.ClassDef):
print(cls.name)
for m in cls.body:
if isinstance(m, ast.FunctionDef):
print(m.name)
for a in m.body:
if isinstance(a, ast.AnnAssign):
if isinstance(a.target, ast.Attribute):
if a.target.value.id == 'self':
print(f'{a.target.value.id}.{a.target.attr}: {a.annotation.id}')
elif isinstance(a, ast.AugAssign):
pass
elif isinstance(a, ast.Assign):
for t in a.targets:
if isinstance(t, ast.Attribute):
if t.value.id == 'self':
print(f'{t.value.id}.{t.attr}') This will generate output:
|
hi @doyou89 😃 Thank you for your suggestion. I am coming up with some similar code, but following the visitor pattern so that:
Thank you for pointing out some cases like |
The current approach detects class variables (which is how dataclass works). But non-dataclass classes should be handled as well.
The text was updated successfully, but these errors were encountered: