Skip to content

Add PyiWriter to Cython and new Cython directive 'write_stub_file' #5744

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

Closed
wants to merge 0 commits into from

Conversation

Vizonex
Copy link

@Vizonex Vizonex commented Oct 4, 2023

The Demand for such a tool to exist is very high and I wanted to try my very hardest to deliver. Visual Studio Code and some other coding Ides that I may not be aware off suffer from not being able to have immediate type hint access when a compiled python file such as .so or .pyd that are compiled by Cython. My goal was to finish what the author ax487 had started and I have made some optimizations of my own to his compiler as well as added the bonus of type hint completeness to the arguments. I would've added the ability to recover return type hint annotations but we can save that for the future as this PyiWriter object matures a bit as I have tried to resolve missing type hint annotations labeled as object with no success just yet. However as long as you have provided the necessary type hints needed to your modules that shouldn't be a problem or issue and it should not be overwritten as long as the annotations or declarations are written to the .pyx , .py file.

New Directive Argument Was Added

I have added in a new cython directive called cython: write_stub_file to invoke the PyiWriter to write the stubfiles where the pyx file is being compiled. And here is a neat little example to illustrate this.

We will call this file test.pyx

#cython: write_stub_file = True 
cdef class Concept:
    cdef Py_ssize_t size
    def __cinit__(self,Py_ssize_t size):
        self.size = size

Using the new cython: write_stub_file directive I have created and setting it as True will create the output named test.pyi

# Python stub file generated by Cython 3.0.2
class Concept:
    def __init__(self, size:int):...

There maybe a few things missing like an output folder command but I'm pretty sure all of you could help me come up with those missing pieces. I am honored and humbled to be apart of one of the most revolutionary additions ever to Cython as of currently.

Copy link
Contributor

@da-woods da-woods left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've left a few comments based on a very quick skim through, but this obviously needs a detailed look.

It'll also need some testing, although I don't know the best way to do that since I don't really understand the pyi process. Ideally I think we'd just test using some tool that can load pyi files (and which we didn't write...)

if node.directives['write_stub_file']:
result = self.write(node, True)
# TODO See if we should or shouldn't report back about our stubfiles being written off....
print(f"Writing {result}.pyi ...")
Copy link
Contributor

@da-woods da-woods Oct 4, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't assume that Cython runs on a version of Python that supports fstrings yet

annotation = ""
# TODO Maybe have a flag to check if were currently using
# a class inside of here as an extra check?
if arg.name == "self":
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't necessarily think we should base the behaviour on the argument name - self is a convention rather than a rule

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, I just don't know how to implement it yet, but I'll soon figure it out.

@@ -0,0 +1,485 @@
from .Compiler import Version
from .Compiler.Nodes import *
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd avoid import *

return py_name


def translate_annotations(node) -> list[str]:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We also can't assume that we run on a version of Python that supports type annotations




def visit_DefNode(self,node:DefNode):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Further to my comment about not supporting annotations, I'm also not keen on node : DefNode - it's absolutely explicit from the function already so it isn't adding useful information.

Right now it's irrelevant (since we can't have it) but it's definitely the type of annotation I'd be keen to avoid in future

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll be sure to fix all of this then. Thank you for your input

Copy link
Contributor

@scoder scoder left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. Yes, testing is needed here.
There are also a lot of code formatting issues and some spelling mistakes.

Comment on lines 110 to 111
print("writing file %s.pyi ..." % node.full_module_name)
with open_new_file(os.path.join(node.full_module_name + '.pyi')) as w:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't this write files like pkg1.pkg2.module.pyi? They should rather be created in the package folders.

print("writing file %s.pyi ..." % node.full_module_name)
with open_new_file(os.path.join(node.full_module_name + '.pyi')) as w:
w.write("\n".join(result.lines))
print("pyi file written")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems unnecessary. If it didn't fail, it succeeded, obviously.

Suggested change
print("pyi file written")

@Vizonex
Copy link
Author

Vizonex commented Oct 5, 2023

Not sure what else I need to add, except for better translations for Pyrex types to python types and a brand new test suite.

@Vizonex
Copy link
Author

Vizonex commented Oct 6, 2023

I got the PyiWriter to finally work with the rest of the transforms by adding in a function that was missing from the transform. Turns out that visit_StatListNode was missing from the functions so I had to add it in and now everything seems to compile as normal. I will have to turn off the debug argument when it is writing but the only thing we need now is to find a clean way to test it.

I have tested everything using the cythonize command since I am working with the edited version made inside of a virtual environment. I guess the next part of my plan now is to create a test class that uses both __cinit__ and __init__ functions since it may cause problems in the future. Beyond that will be to make a unit test in the Tests folder where the Compiler is located. Not sure how exactly I will be writing it, but I'm currently am trying to make it.

Below is a file that I recently did to be sure the PyiWriter works and that all the other underlying visitors work with it without a problem.

# cython: language_level = 3
# cython: embedsignature = True 
# cython: embedsignature.python = True
# cython: write_stub_file = True

# This function doesn't make sense but I put it here for demonstration purposes only...
def test_data(int a):
    if a == 1:
        return float(a)
    else:
        return str(a)

cdef class RoundRobin:
    cdef Py_ssize_t current , limit
    def __cinit__(self, Py_ssize_t limit):
        self.limit = limit
        self.current = 0
    cpdef Py_ssize_t next(self):
        cdef Py_ssize_t result = self.current
        self.current += 1 
        if self.current >= self.limit:
            self.current = 0
        return result 
    # This should not be added in with the pyi stub because it's C
    cdef Py_ssize_t get_limit(self):
        return self.limit   
# Python stub file generated by Cython 3.0.2

def test_data(a: int): ...
class RoundRobin:
    def __init__(self, limit: int): ...
    def next(self) -> int: ...

@da-woods
Copy link
Contributor

da-woods commented Oct 6, 2023

A good start to the testing would just be to enable the stub generator generally on the Cython test suite (like we do with the annotated html). That wouldn't actually test any of the functionality, but it would confirm that it can process a lot of Cython code without crashing. Changes would probably need to be in runtest.py.

I'd probably put TypeStubGenerator.py through something like black to standardize the formatting. It's a lot better now but not perfect. We don't generally do this for existing files, but it's a good idea for new files I think.

Again, I haven't have a chance to have a detailed look yet so I'm sure there's more comments, but that bit of testing is definitely a good place to start

from .Nodes import CNameDeclaratorNode
from .ExprNodes import CallNode, NameNode, ImportNode, TupleNode, AttributeNode
from ..CodeWriter import DeclarationWriter
from .ParseTreeTransforms import CythonTransform
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CythonTransform is in Visitor

@scoder
Copy link
Contributor

scoder commented Oct 7, 2023 via email

@Vizonex
Copy link
Author

Vizonex commented Oct 7, 2023

We should just run black selectively on all newly added files, as part of the code checks. It has a mode that fails on necessary format changes.

Sounds like a great idea actually. That would be a good way to verify that it works. I'll see what I can come up with.

@Vizonex
Copy link
Author

Vizonex commented Oct 8, 2023

Did not realize that the imports were accidently deleted but I have that fixed now so this should all work as normal now.

@Vizonex Vizonex requested review from scoder and da-woods October 8, 2023 18:55
Copy link
Contributor

@da-woods da-woods left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Partial review... more comments will come when I have time to look further

import os
import sys

cython.declare(PyrexTypes=object, Naming=object, ExprNodes=object, Nodes=object,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably not useful unless you intend this file to be compiled with Cython. I'd think it shouldn't be at this stage - it's not a "core" feature so doesn't really need speeding up. If you do intend it to be compiled then the file needs adding to setup.py.

cython.declare(PyrexTypes=object, Naming=object, ExprNodes=object, Nodes=object,
Options=object, UtilNodes=object, LetNode=object,
LetRefNode=object, TreeFragment=object, EncodedString=object,
error=object, warning=object, copy=object, _unicode=object)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that error and warning aren't even imported, so declaring them as object probably isn't helpful (but again, I don't think you need this line)



# TODO Save this implementation commented out if required....
if sys.version_info >= (3, 9):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't assume that the version of Python that Cython is run in is necessarily the same as the version of Python the generated files are used in. Can this go in the stub files instead? (is this supported by stub files?)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A try-import might work in the stub file.

def translate_pyrex_type(self, ctype):
# TODO implement Pyrex to cython shadow typehints converter...

if isinstance(ctype, PyrexTypes.BuiltinObjectType):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if ctype.is_builtin_type

if isinstance(ctype, PyrexTypes.BuiltinObjectType):
return ctype.py_type_name()

if isinstance(ctype, PyrexTypes.CVoidType):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most of these are defined as global constants in PyrexTypes. This one you can test with

if ctype is c_void_type:

if self.translation_table.get(base.name):
return self.translation_table[base.name]

elif base.name == "object":
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm suspicious of most of these comparisons to base.name - again, it should be possible to identify without checking the name (as above)

else:
typing_module = "typing_extensions"

class PyiWriter(CythonTransform, DeclarationWriter):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you use the directives tracking of CythonTransform. I wonder if this should inherit from TreeVisitor since I don't think it's intended to change the tree - just to go over it. That'd eliminate any possibility of accidentally changing the tree.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also don't know how much of DeclarationWriter you use - possibly just things like write/indent. I wonder if it would be worth factoring those out so you can inherit without bringing in all the visit_ functions?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, DeclarationWriter deals a lot with Cython's cdef declarations, so splitting out a Python compatible thing seems like a good idea. It would probably do a bit more than just indentation, maybe not that much more.

def __init__(self, context):
super(PyiWriter, self).__init__(context=context)
super(DeclarationWriter, self).__init__()
self.context = context
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused probably.

if isinstance(decorator, NameNode):
self.endline("%s" % decorator.name)
else:
assert isinstance(decorator, AttributeNode) , "Decorator was not an attribute node..."
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd be worried how this interacts with https://peps.python.org/pep-0614/. There's definitely cases where decorators aren't attributes or names now.

I'm not quite sure how decorators mix with stub files though.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recursion again, if you want to properly serialise the stub files. But yeah, not sure if that's really intended here.



def annotation_Str(self, annotation):
return annotation.name if hasattr(annotation,"name") and annotation.is_name else annotation.string.unicode_value
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just annotation.is_name - I don't think you need to do hasattr and is_name

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recursion again.

@Vizonex
Copy link
Author

Vizonex commented Oct 14, 2023

are we ok to merge this pull request or do I still need to write in a unittest for it?

elif base.name == "bint":
return "bool"

ctype = PyrexTypes.simple_c_type(base.signed, base.longness, base.name) # type: ignore
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps I'm missing something, but base is already a type, so I don't understand what this line does

):

# Try checking our table first...
if self.translation_table.get(base.name):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if base.name in self.translation_table

Comment on lines 202 to 204
# Optimized original code by having there be one function to take
# the place of two of them I could see what Scoder meant when
# said the original pull request needed to be cleaned up...
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# Optimized original code by having there be one function to take
# the place of two of them I could see what Scoder meant when
# said the original pull request needed to be cleaned up...

Don't think this comment is needed for future understanding of the code

def write_class(self, node, class_name):
self.endline()
self.put("class %s" % class_name)
if getattr(node,"bases",None) and isinstance(node.bases, TupleNode) and node.bases.args:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think node.bases needs a getattr - it's a child of both PyClassDefNode and CClassDefNode

self.put("class %s" % class_name)
if getattr(node,"bases",None) and isinstance(node.bases, TupleNode) and node.bases.args:
self.put("(")
self.put(",".join([name.name for name in node.bases.args]))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not everything in a tuple node will be a name. E.g.:

import module

class MyClass(module.BaseClass):
   pass

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recursion by visiting the args nodes would probably solve this.

self.endline("):")
else:
self.endline(":")
self.class_func_count = 0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Classes can be nested

@da-woods
Copy link
Contributor

are we ok to merge this pull request or do I still need to write in a unittest for it?

My view is that we definitely need some testing before we consider merging it. The testing doesn't have to be comprehensive but right now we have no evidence it works at all.

Like I said before, I think it would be worth enabling the directive for every CythonCompileTestCase in the entire existing test-suite. We don't even have to look at the output, but it'll at least prove that it doesn't crash given existing valid Cython code.

I think setting up proper tests for this may be quite hard, and maybe we shouldn't leave it to you. I'd think we want to either look for specific generated code in the pyi files with a regex search, or we'd want to re-parse the pyi files into Cython and look for specific nodes using something similar to test_assert_path_exists

@da-woods
Copy link
Contributor

The other thing to say with testing: if you have files that you've used to test it manually yourself it might still be useful to add them as part of the review process so we can think about how to automate it

@Vizonex
Copy link
Author

Vizonex commented Oct 20, 2023

The other thing to say with testing: if you have files that you've used to test it manually yourself it might still be useful to add them as part of the review process so we can think about how to automate it

@da-woods Sounds good sorry I didn't get back sooner but sounds like a great plan I will have to figure out a way to start verifying off pyi files since I cannot seem to find any python libraries that specifically check stub files yet but I will keep looking for an implementation that does. I will also find a way to test it as well since I'm currently working on a unittest for it.

Copy link
Contributor

@scoder scoder left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please run black over TypeStubGenerator.py to properly format it.

There are way too many getattr() calls. They usually indicate something being wrong in the logic and nodes turning up in these places that should probably be handled elsewhere.

And much of this can be taken from the AutoDocTransform, specifically its is_format_python mode. We'd probably need to extract most of it into a plain class rather than the existing transform, so that it can be reused in a tree visitor.

@@ -188,6 +188,7 @@ def create_pipeline(context, mode, exclude_classes=()):
_specific_post_parse,
TrackNumpyAttributes(),
InterpretCompilerDirectives(context, context.compiler_directives),
PyiWriter(context),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this done at this early stage and not at the end of the pipeline? Especially after AdjustDefByDirectives and AnalyseExpressionsTransform ?

else:
typing_module = "typing_extensions"

class PyiWriter(CythonTransform, DeclarationWriter):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, DeclarationWriter deals a lot with Cython's cdef declarations, so splitting out a Python compatible thing seems like a good idea. It would probably do a bit more than just indentation, maybe not that much more.

self.visitchildren(node)
self.dedent()

def translate_pyrex_type(self, ctype):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would have expected a difference between argument types and return types regarding the conversion. Are they really always the same?

self.put("class %s" % class_name)
if getattr(node,"bases",None) and isinstance(node.bases, TupleNode) and node.bases.args:
self.put("(")
self.put(",".join([name.name for name in node.bases.args]))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recursion by visiting the args nodes would probably solve this.

if isinstance(decorator, NameNode):
self.endline("%s" % decorator.name)
else:
assert isinstance(decorator, AttributeNode) , "Decorator was not an attribute node..."
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recursion again, if you want to properly serialise the stub files. But yeah, not sure if that's really intended here.



def annotation_Str(self, annotation):
return annotation.name if hasattr(annotation,"name") and annotation.is_name else annotation.string.unicode_value
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recursion again.

Comment on lines 288 to 290
# TODO Change how init is being handled...
if func_name == '__cinit__':
func_name = '__init__'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, yeah, you can have both __cinit__ and __init__ in the same class.

@da-woods
Copy link
Contributor

I cannot seem to find any python libraries that specifically check stub files yet but I will keep looking for an implementation that does

I think a stub file does end up being a valid Python file. So either putting it into Python or Cython itself would at least show that you've written a valid file.

@Vizonex
Copy link
Author

Vizonex commented Oct 29, 2023

Let me make sure I get the file formatted using black real fast...

@leofang
Copy link

leofang commented Nov 2, 2023

cc @dalcinl for vis

@dalcinl
Copy link
Member

dalcinl commented Nov 3, 2023

@Vizonex You should test your work against mpi4py

git clone https://github.com/mpi4py/mpi4py.git
cd mpi4py
python conf/cythonize.py

Your code currently crashes Cython:

Error compiling Cython file:
------------------------------------------------------------
...
    bint      recv_mprobe
    MPI_Count irecv_bufsz
    int       errors

cdef Options options
options.initialize = 1
                     ^
------------------------------------------------------------

src/mpi4py/MPI/atimport.pxi:95:21: Compiler crash in PyiWriter

ModuleNode.body = StatListNode(MPI.pyx:15:0)
StatListNode.stats[1] = StatListNode(MPI.pyx:3:0)
StatListNode.stats[3] = StatListNode(atimport.pxi:3:0)
StatListNode.stats[8] = SingleAssignmentNode(atimport.pxi:95:21)

Compiler crash traceback from this point on:
  File "/tmp/cython/Cython/Compiler/Visitor.py", line 182, in _visit
    return handler_method(obj)
           ^^^^^^^^^^^^^^^^^^^
  File "/tmp/cython/Cython/Compiler/TypeStubGenerator.py", line 387, in visit_SingleAssignmentNode
    name = node.lhs.name
           ^^^^^^^^^^^^^
AttributeError: 'AttributeNode' object has no attribute 'name'

@Vizonex
Copy link
Author

Vizonex commented Nov 4, 2023

@dalcinl I will be sure to use the repository you mentioned for testing. And I also think some of the visitors in my code should use a little more recursion which is what scoder suggested I do a bit earlier. The attributes themselves I think need better attention than what they have currently been given.

@Vizonex
Copy link
Author

Vizonex commented Nov 4, 2023

I had an Idea for writing decorators by making a new class object that could chain attributes together for the decorators but I am not sure how I am going to approach this problem. Here is an example of what the problem is...

@very.long.wrapper
def func():

Oh I see there is an example in the Expression Writer class Nevermind....

@da-woods
Copy link
Contributor

da-woods commented Nov 4, 2023

Decorators:

https://typing.readthedocs.io/en/latest/source/stubs.html#decorators

Type stubs may only use decorators defined in the typing module, plus a fixed set of additional ones:

classmethod

staticmethod

property (including .setter)

abc.abstractmethod

dataclasses.dataclass

asyncio.coroutine (although async should be used instead)

To me that says you can be fairly eager to drop anything unrecognised. I'd probably do something like:

  1. If it's a CallNode, drop the CallNode and just take node.function to step 2.
  2. If it isn't a NameNode or AttributeNode then drop the decorator completely.
  3. Maybe just write out the name/attribute? (I think filtering to the fixed list of names could be hard)

@Vizonex
Copy link
Author

Vizonex commented Nov 4, 2023

Decorators:

https://typing.readthedocs.io/en/latest/source/stubs.html#decorators

Type stubs may only use decorators defined in the typing module, plus a fixed set of additional ones:
classmethod
staticmethod
property (including .setter)
abc.abstractmethod
dataclasses.dataclass
asyncio.coroutine (although async should be used instead)

To me that says you can be fairly eager to drop anything unrecognised. I'd probably do something like:

  1. If it's a CallNode, drop the CallNode and just take node.function to step 2.
  2. If it isn't a NameNode or AttributeNode then drop the decorator completely.
  3. Maybe just write out the name/attribute? (I think filtering to the fixed list of names could be hard)

So should I make the visitor visit call nodes as well because I am also worried about it accidently being mixed with cython directives. But I will figure out if there's already a check inplace for that.

@da-woods
Copy link
Contributor

da-woods commented Nov 4, 2023

So should I make the visitor visit call nodes as well because I am also worried about it accidently being mixed with cython directives. But I will figure out if there's already a check inplace for that.

You should be able to identify cython directives with node.as_cython_attribute(). You should probably ignore any cython directives.

@Vizonex
Copy link
Author

Vizonex commented Nov 4, 2023

So should I make the visitor visit call nodes as well because I am also worried about it accidently being mixed with cython directives. But I will figure out if there's already a check inplace for that.

You should be able to identify cython directives with node.as_cython_attribute(). You should probably ignore any cython directives.

I just looked at it and it seems that there is a better solution. So would something like this be a bit better?

def write_decorator(self, decorator):
    attribte = decorator.as_cython_attribute()
    if attribte:
         self.putline("@%s" % attribte)

@da-woods
Copy link
Contributor

da-woods commented Nov 4, 2023

Probably

    attribte = decorator.as_cython_attribute()
    if not attribte:

(i.e. you don't want to write out Cython directives)

@Vizonex
Copy link
Author

Vizonex commented Nov 4, 2023

I'm gonna be sure I get to fixing visit_SingleAssignmentNode since there seems to be some nodes that do not have a name attribute as seen in the error above. Might need to re-work on that function when I can get to it.

@Vizonex
Copy link
Author

Vizonex commented Mar 25, 2024

I think the reason why I stopped trying was because everything lacked readability (I blame VS code's intellisense/pyright tools for that). I may resume my attempts on this project soon but I think that writing stub files or maybe even programming external tools for writing tree visitors and finding a way for to figure out node variables and their different class members might be helpful. I'll probably close this Pull Request soon and come up with a new one in the future. For those depending on me to program stub file generation into cython please don't worry, I haven't given up on this. I've just been busy with other stuff that I completely forgot about this project.

@Vizonex Vizonex closed this May 11, 2025
vbraun pushed a commit to vbraun/sage that referenced this pull request Aug 1, 2025
sagemathgh-39257: Create pyi stub files for cython modules in arith and algebras
    
Add pyi stub files for some cython modules in `arith` and `algebras` to
add typing support (and IDE autocompletion) for these cython modules.
They are not supposed to be 100% correct but serve at least as a
starting point for further refinements.

At some point they might be autogenerated by cython, but this could
easily still take a few years (see
cython/cython#3150 and
cython/cython#5744 for the current progress)
    
URL: sagemath#39257
Reported by: Tobias Diez
Reviewer(s): Dima Pasechnik
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy