Repository: pyccel/pyccel
Pull request #1791 (2024-03-17 10:20:24)

Clean up unnecessary arguments in the codegen stage
The codegen stage contains lots of old code which sometimes refers to parameters which no longer exist. This PR cleans up some of that code and removes commented dead code which refers to it. Specifically the functions `fcode`, `ccode` and `pycode` are removed as well as `Codegen.doprint` and `Codegen.set_printer`. An instance of `Codegen` must now be created with the language passed as argument.

pyccel-bot[bot]: Hello again! Thank you for this new pull request :star_struck:.

Please begin by requesting your checklist using the command `/bot checklist`

EmilyBourne: /bot checklist
EmilyBourne: /bot run docs linux pylint
EmilyBourne: /bot run docs
pyccel-bot[bot]: It seems like you have forgotten to complete your checklist for this pull request. Please check the list [here](https://github.com/pyccel/pyccel/pull/1791#issuecomment-2002396807), fix the missing items and let me know when everything is ticked and fixed with `/bot mark as ready`.

pyccel-bot[bot]: Hey @pyccel/pyccel-dev ! @EmilyBourne has just created this great new pull request! Check it out and let me know what you think!

pyccel-bot[bot]: @EmilyBourne, @yguclu has a few questions/comments about your code. Can you go through and see if you agree with them. If not go ahead and explain why. Once you've adressed all the comments let me know with `/bot mark as ready` and we will see if we can get approval.


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1c1a3cf2..b5aa1a34 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -28,6 +28,8 @@ All notable changes to this project will be documented in this file.
 -   \[INTERNALS\] Moved precision from `ast.basic.TypedAstNode` to an internal property of `ast.datatypes.FixedSizeNumericType` objects.
 -   \[INTERNALS\] Use cached `__add__` method to determine result type of arithmetic operations.
 -   \[INTERNALS\] Use cached `__and__` method to determine result type of bitwise comparison operations.
+-   \[INTERNALS\] Removed unused `fcode`, `ccode`, `cwrappercode`, `luacode`, and `pycode` functions from printers.
+-   \[INTERNALS\] Removed unused arguments from methods in `pyccel.codegen.codegen.Codegen`.
 
 ### Deprecated
 
diff --git a/pyccel/codegen/codegen.py b/pyccel/codegen/codegen.py
index 01303cc3..3da73d1f 100644
--- a/pyccel/codegen/codegen.py
+++ b/pyccel/codegen/codegen.py
@@ -11,7 +11,6 @@ from pyccel.codegen.printing.ccode  import CCodePrinter
 from pyccel.codegen.printing.pycode import PythonCodePrinter
 
 from pyccel.ast.core      import FunctionDef, Interface, ModuleHeader
-from pyccel.errors.errors import Errors
 from pyccel.utilities.stage import PyccelStage
 
 _extension_registry = {'fortran': 'f90', 'c':'c',  'python':'py'}
@@ -24,28 +23,31 @@ printer_registry    = {
 
 pyccel_stage = PyccelStage()
 
-class Codegen(object):
-
-    """Abstract class for code generator."""
-
-    def __init__(self, parser, name):
-        """Constructor for Codegen.
-
-        parser: pyccel parser
-
-
-        name: str
-            name of the generated module or program.
-        """
+class Codegen:
+    """
+    Class which handles the generation of code.
+
+    The class which handles the generation of code. This is done by creating an appropriate
+    class inheriting from `CodePrinter` and using it to create strings describing the code
+    that should be printed. This class then takes care of creating the necessary files.
+
+    Parameters
+    ----------
+    parser : SemanticParser
+        The Pyccel semantic parser for a Python program or module. This contains the
+        annotated AST and additional information about the variables scope.
+    name : str
+        Name of the generated module or program.
+    language : str
+        The language which the printer should print to.
+    """
+    def __init__(self, parser, name, language):
         pyccel_stage.set_stage('codegen')
         self._parser   = parser
         self._ast      = parser.ast
         self._name     = name
         self._printer  = None
-        self._language = None
-
-        #TODO verify module name != function name
-        #it generates a compilation error
+        self._language = language
 
         self._stmts = {}
         _structs = [
@@ -63,11 +65,32 @@ class Codegen(object):
         self._collect_statements()
         self._is_program = self.ast.program is not None
 
+        # instantiate code_printer
+        try:
+            CodePrinterSubclass = printer_registry[language]
+        except KeyError as err:
+            raise ValueError(f'{language} language is not available') from err
+
+        self._printer = CodePrinterSubclass(self.parser.filename)
 
     @property
     def parser(self):
+        """
+        The parser which generated the AST printed by this class.
+
+        The parser which generated the AST printed by this class.
+        """
         return self._parser
 
+    @property
+    def printer(self):
+        """
+        The printer which is used to generate code.
+
+        The printer which is used by this class to generate code in the target language.
+        """
+        return self._printer
+
     @property
     def name(self):
         """Returns the name associated to the source code"""
@@ -134,22 +157,6 @@ class Codegen(object):
 
         return self._language
 
-    def set_printer(self, **settings):
-        """ Set the current codeprinter instance"""
-        # Get language used (default language used is fortran)
-        language = settings.pop('language', 'fortran')
-
-        # Set language
-        if not language in ['fortran', 'c', 'python']:
-            raise ValueError('{} language is not available'.format(language))
-        self._language = language
-
-        # instantiate codePrinter
-        code_printer = printer_registry[language]
-        errors = Errors()
-        # set the code printer
-        self._printer = code_printer(self.parser.filename, **settings)
-
     def get_printer_imports(self):
         """return the imports of the current codeprinter"""
         return self._printer.get_additional_imports()
@@ -176,22 +183,38 @@ class Codegen(object):
         self._stmts['interfaces'] = interfaces
         self._stmts['body']       = self.ast
 
-    def doprint(self, **settings):
-        """Prints the code in the target language."""
-        if not self._printer:
-            self.set_printer(**settings)
-        return self._printer.doprint(self.ast)
 
-
-    def export(self, filename=None, **settings):
-        """Export code in filename"""
-        self.set_printer(**settings)
+    def export(self, filename):
+        """
+        Export code to a file with the requested name.
+
+        Generate the code in the target language from the AST and print this code
+        to file. Between 1 and 3 files are generated depending on the AST and the
+        target language. A source file is always generated. In languages with
+        header files, a header file is also generated. Finally if the AST includes
+        a program and the target language is not Python a program source file is
+        also generated. The source and header files are named by appending the
+        extension to the requested filename. The program source file is named by
+        additionally prepending 'prog_' to the requested filename.
+
+        Parameters
+        ----------
+        filename : str
+            The base (i.e. no extensions) of the filename of the file where the
+            code should be printed to.
+
+        Returns
+        -------
+        filename : str
+            The name of the file where the source code was printed.
+        prog_filename : str
+            The name of the file where the source code for the program was printed.
+        """
         ext = _extension_registry[self._language]
         header_ext = _header_extension_registry[self._language]
 
-        if filename is None: filename = self.name
-        header_filename = '{name}.{ext}'.format(name=filename, ext=header_ext)
-        filename = '{name}.{ext}'.format(name=filename, ext=ext)
+        header_filename = f'{filename}.{header_ext}'
+        filename = f'{filename}.{ext}'
 
         # print module header
         if header_ext is not None:
diff --git a/pyccel/codegen/pipeline.py b/pyccel/codegen/pipeline.py
index 4d4770a4..648e8ca6 100644
--- a/pyccel/codegen/pipeline.py
+++ b/pyccel/codegen/pipeline.py
@@ -260,9 +260,9 @@ def execute_pyccel(fname, *,
     start_codegen = time.time()
     # Generate .f90 file
     try:
-        codegen = Codegen(semantic_parser, module_name)
+        codegen = Codegen(semantic_parser, module_name, language)
         fname = os.path.join(pyccel_dirpath, module_name)
-        fname, prog_name = codegen.export(fname, language=language)
+        fname, prog_name = codegen.export(fname)
     except NotImplementedError as error:
         msg = str(error)
         errors.report(msg+'\n'+PYCCEL_RESTRICTION_TODO,
diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py
index c083dbbb..a92165d4 100644
--- a/pyccel/codegen/printing/ccode.py
+++ b/pyccel/codegen/printing/ccode.py
@@ -2515,27 +2515,3 @@ class CCodePrinter(CodePrinter):
             level += increase[n]
         return pretty
 
-def ccode(expr, filename, assign_to=None, **settings):
-    """Converts an expr to a string of c code
-
-    expr : Expr
-        A pyccel expression to be converted.
-    filename : str
-        The name of the file being translated. Used in error printing
-    assign_to : optional
-        When given, the argument is used as the name of the variable to which
-        the expression is assigned. Can be a string, ``Symbol``,
-        ``MatrixSymbol``, or ``Indexed`` type. This is helpful in case of
-        line-wrapping, or for expressions that generate multi-line statements.
-    user_functions : dict, optional
-        A dictionary where keys are ``FunctionClass`` instances and values are
-        their string representations. Alternatively, the dictionary value can
-        be a list of tuples i.e. [(argument_test, cfunction_string)]. See below
-        for examples.
-    dereference : iterable, optional
-        An iterable of symbols that should be dereferenced in the printed code
-        expression. These would be values passed by address to the function.
-        For example, if ``dereference=[a]``, the resulting code would print
-        ``(*a)`` instead of ``a``.
-    """
-    return CCodePrinter(filename, **settings).doprint(expr, assign_to)
diff --git a/pyccel/codegen/printing/cwrappercode.py b/pyccel/codegen/printing/cwrappercode.py
index 10334e8b..bf2ef68c 100644
--- a/pyccel/codegen/printing/cwrappercode.py
+++ b/pyccel/codegen/printing/cwrappercode.py
@@ -515,31 +515,3 @@ class CWrapperCodePrinter(CCodePrinter):
             return f'{base}{idxs}'
         else:
             return CCodePrinter._print_IndexedElement(self, expr)
-
-def cwrappercode(expr, filename, target_language, assign_to=None, **settings):
-    """Converts an expr to a string of c wrapper code
-
-    expr : Expr
-        A pyccel expression to be converted.
-    filename : str
-        The name of the file being translated. Used in error printing
-    assign_to : optional
-        When given, the argument is used as the name of the variable to which
-        the expression is assigned. Can be a string, ``Symbol``,
-        ``MatrixSymbol``, or ``Indexed`` type. This is helpful in case of
-        line-wrapping, or for expressions that generate multi-line statements.
-    precision : integer, optional
-        The precision for numbers such as pi [default=15].
-    user_functions : dict, optional
-        A dictionary where keys are ``FunctionClass`` instances and values are
-        their string representations. Alternatively, the dictionary value can
-        be a list of tuples i.e. [(argument_test, cfunction_string)]. See below
-        for examples.
-    dereference : iterable, optional
-        An iterable of symbols that should be dereferenced in the printed code
-        expression. These would be values passed by address to the function.
-        For example, if ``dereference=[a]``, the resulting code would print
-        ``(*a)`` instead of ``a``.
-    """
-
-    return CWrapperCodePrinter(filename, target_language, **settings).doprint(expr, assign_to)
diff --git a/pyccel/codegen/printing/fcode.py b/pyccel/codegen/printing/fcode.py
index 121587a1..9a6766d6 100644
--- a/pyccel/codegen/printing/fcode.py
+++ b/pyccel/codegen/printing/fcode.py
@@ -3266,25 +3266,3 @@ class FCodePrinter(CodePrinter):
                  *[a.getter for a in expr.attributes], *[a.setter for a in expr.attributes]]
         sep = f'\n{self._print(SeparatorComment(40))}\n'
         return '', sep.join(self._print(f) for f in funcs)
-
-
-def fcode(expr, filename, assign_to=None, **settings):
-    """Converts an expr to a string of Fortran code
-
-    expr : Expr
-        A pyccel expression to be converted.
-    filename : str
-        The name of the file being translated. Used in error printing
-    assign_to : optional
-        When given, the argument is used as the name of the variable to which
-        the expression is assigned. Can be a string, ``Symbol``,
-        ``MatrixSymbol``, or ``Indexed`` type. This is helpful in case of
-        line-wrapping, or for expressions that generate multi-line statements.
-    user_functions : dict, optional
-        A dictionary where keys are ``FunctionClass`` instances and values are
-        their string representations. Alternatively, the dictionary value can
-        be a list of tuples i.e. [(argument_test, cfunction_string)]. See below
-        for examples.
-    """
-
-    return FCodePrinter(filename, **settings).doprint(expr, assign_to)
diff --git a/pyccel/codegen/printing/luacode.py b/pyccel/codegen/printing/luacode.py
index c3edbdb2..1888226e 100644
--- a/pyccel/codegen/printing/luacode.py
+++ b/pyccel/codegen/printing/luacode.py
@@ -507,118 +507,3 @@ class LuaCodePrinter(CodePrinter):
             level += increase[n]
         return pretty
 
-
-def lua_code(expr, assign_to=None, **settings):
-    """Converts an expr to a string of Lua code
-
-    expr : Expr
-        A sympy expression to be converted.
-    assign_to : optional
-        When given, the argument is used as the name of the variable to which
-        the expression is assigned. Can be a string, ``Symbol``,
-        ``MatrixSymbol``, or ``Indexed`` type. This is helpful in case of
-        line-wrapping, or for expressions that generate multi-line statements.
-    precision : integer, optional
-        The precision for numbers such as pi [default=15].
-    user_functions : dict, optional
-        A dictionary where the keys are string representations of either
-        ``FunctionClass`` or ``UndefinedFunction`` instances and the values
-        are their desired C string representations. Alternatively, the
-        dictionary value can be a list of tuples i.e. [(argument_test,
-        cfunction_string)].  See below for examples.
-    dereference : iterable, optional
-        An iterable of symbols that should be dereferenced in the printed code
-        expression. These would be values passed by address to the function.
-        For example, if ``dereference=[a]``, the resulting code would print
-        ``(*a)`` instead of ``a``.
-    human : bool, optional
-        If True, the result is a single string that may contain some constant
-        declarations for the number symbols. If False, the same information is
-        returned in a tuple of (symbols_to_declare, not_supported_functions,
-        code_text). [default=True].
-    contract: bool, optional
-        If True, ``Indexed`` instances are assumed to obey tensor contraction
-        rules and the corresponding nested loops over indices are generated.
-        Setting contract=False will not generate loops, instead the user is
-        responsible to provide values for the indices in the code.
-        [default=True].
-    locals: dict
-        A dictionary that contains the list of local symbols. these symbols will
-        be preceeded by local for their first assignment.
-
-    Examples
-
-    >>> from sympy import lua_code, symbols, Rational, sin, ceiling, Abs, Function
-    >>> x, tau = symbols("x, tau")
-    >>> lua_code((2*tau)**Rational(7, 2))
-    '8*1.4142135623731*tau.powf(7_f64/2.0)'
-    >>> lua_code(sin(x), assign_to="s")
-    's = x.sin();'
-
-    Simple custom printing can be defined for certain types by passing a
-    dictionary of {"type" : "function"} to the ``user_functions`` kwarg.
-    Alternatively, the dictionary value can be a list of tuples i.e.
-    [(argument_test, cfunction_string)].
-
-    >>> custom_functions = {
-    ...   "ceiling": "CEIL",
-    ...   "Abs": [(lambda x: not x.is_integer, "fabs", 4),
-    ...           (lambda x: x.is_integer, "ABS", 4)],
-    ...   "func": "f"
-    ... }
-    >>> func = Function('func')
-    >>> lua_code(func(Abs(x) + ceiling(x)), user_functions=custom_functions)
-    '(fabs(x) + x.CEIL()).f()'
-
-    ``Piecewise`` expressions are converted into conditionals. If an
-    ``assign_to`` variable is provided an if statement is created, otherwise
-    the ternary operator is used. Note that if the ``Piecewise`` lacks a
-    default term, represented by ``(expr, True)`` then an error will be thrown.
-    This is to prevent generating an expression that may not evaluate to
-    anything.
-
-    >>> from sympy import Piecewise
-    >>> expr = Piecewise((x + 1, x > 0), (x, True))
-    >>> print(lua_code(expr, tau))
-    tau = if (x > 0) {
-        x + 1
-    } else {
-        x
-    };
-
-    Support for loops is provided through ``Indexed`` types. With
-    ``contract=True`` these expressions will be turned into loops, whereas
-    ``contract=False`` will just print the assignment expression that should be
-    looped over:
-
-    >>> from sympy import Eq, IndexedBase, Idx
-    >>> len_y = 5
-    >>> y = IndexedBase('y', shape=(len_y,))
-    >>> t = IndexedBase('t', shape=(len_y,))
-    >>> Dy = IndexedBase('Dy', shape=(len_y-1,))
-    >>> i = Idx('i', len_y-1)
-    >>> e=Eq(Dy[i], (y[i+1]-y[i])/(t[i+1]-t[i]))
-    >>> lua_code(e.rhs, assign_to=e.lhs, contract=False)
-    'Dy[i] = (y[i + 1] - y[i])/(t[i + 1] - t[i]);'
-
-    Matrices are also supported, but a ``MatrixSymbol`` of the same dimensions
-    must be provided to ``assign_to``. Note that any expression that can be
-    generated normally can also exist inside a Matrix:
-
-    >>> from sympy import Matrix, MatrixSymbol
-    >>> mat = Matrix([x**2, Piecewise((x + 1, x > 0), (x, True)), sin(x)])
-    >>> A = MatrixSymbol('A', 3, 1)
-    >>> print(lua_code(mat, A))
-    A = [x.powi(2), if (x > 0) {
-        x + 1
-    } else {
-        x
-    }, x.sin()];
-    """
-
-    return LuaCodePrinter(settings).doprint(expr, assign_to)
-
-
-def print_lua_code(expr, **settings):
-    """Prints Lua representation of the given expression."""
-    print((lua_code(expr, **settings)))
diff --git a/pyccel/codegen/printing/pycode.py b/pyccel/codegen/printing/pycode.py
index dda7cc8d..6ced1aac 100644
--- a/pyccel/codegen/printing/pycode.py
+++ b/pyccel/codegen/printing/pycode.py
@@ -1154,22 +1154,3 @@ class PythonCodePrinter(CodePrinter):
     def _print_TypingFinal(self, expr):
         annotation = self._print(expr.arg)
         return f'const {annotation}'
-
-#==============================================================================
-def pycode(expr, assign_to=None, **settings):
-    """ Converts an expr to a string of Python code
-    Parameters
-    ==========
-    expr : Expr
-        A SymPy expression.
-    fully_qualified_modules : bool
-        Whether or not to write out full module names of functions
-        (``math.sin`` vs. ``sin``). default: ``True``.
-    Examples
-    ========
-    >>> from sympy import tan, Symbol
-    >>> from sympy.printing.pycode import pycode
-    >>> pycode(tan(Symbol('x')) + 1)
-    'math.tan(x) + 1'
-    """
-    return PythonCodePrinter(settings).doprint(expr, assign_to)
diff --git a/pyccel/codegen/python_wrapper.py b/pyccel/codegen/python_wrapper.py
index cc1eef84..3c363e38 100644
--- a/pyccel/codegen/python_wrapper.py
+++ b/pyccel/codegen/python_wrapper.py
@@ -7,19 +7,19 @@
 import os
 import time
 
-from pyccel.ast.core                        import ModuleHeader
-from pyccel.ast.numpy_wrapper               import get_numpy_max_acceptable_version_file
-from pyccel.codegen.printing.fcode          import fcode
-from pyccel.codegen.printing.cwrappercode   import CWrapperCodePrinter
-from pyccel.codegen.wrapper.fortran_to_c_wrapper   import FortranToCWrapper
-from pyccel.codegen.wrapper.c_to_python_wrapper    import CToPythonWrapper
-from pyccel.codegen.utilities      import recompile_object
-from pyccel.codegen.utilities      import copy_internal_library
-from pyccel.codegen.utilities      import internal_libs
-from pyccel.naming                 import name_clash_checkers
-from pyccel.parser.scope           import Scope
-from pyccel.utilities.stage        import PyccelStage
-from .compiling.basic     import CompileObj
+from pyccel.ast.core                             import ModuleHeader
+from pyccel.ast.numpy_wrapper                    import get_numpy_max_acceptable_version_file
+from pyccel.codegen.printing.cwrappercode        import CWrapperCodePrinter
+from pyccel.codegen.printing.fcode               import FCodePrinter
+from pyccel.codegen.wrapper.fortran_to_c_wrapper import FortranToCWrapper
+from pyccel.codegen.wrapper.c_to_python_wrapper  import CToPythonWrapper
+from pyccel.codegen.utilities                    import recompile_object
+from pyccel.codegen.utilities                    import copy_internal_library
+from pyccel.codegen.utilities                    import internal_libs
+from pyccel.naming                               import name_clash_checkers
+from pyccel.parser.scope                         import Scope
+from pyccel.utilities.stage                      import PyccelStage
+from .compiling.basic                            import CompileObj
 
 from pyccel.errors.errors import Errors
 
@@ -126,7 +126,7 @@ def create_shared_library(codegen,
         timings['Bind C wrapping'] = time.time() - start_bind_c_wrapping
 
         start_bind_c_printing = time.time()
-        bind_c_code = fcode(bind_c_mod, bind_c_mod.name)
+        bind_c_code = FCodePrinter(bind_c_mod.name).doprint(bind_c_mod)
         bind_c_filename = f'{bind_c_mod.name}.f90'
 
         with open(bind_c_filename, 'w') as f:
diff --git a/pyccel/commands/console.py b/pyccel/commands/console.py
index aa9c1aad..60eaab0d 100644
--- a/pyccel/commands/console.py
+++ b/pyccel/commands/console.py
@@ -286,50 +286,3 @@ def pyccel(files=None, mpi=None, openmp=None, openacc=None, output_dir=None, com
         sys.exit(1)
     finally:
         os.chdir(base_dirpath)
-
-#==============================================================================
-# NOTE: left here for later reference
-#
-#    group.add_argument('--prefix', type=str, default = '',\
-#                       help='add prefix to the generated file.')
-#    group.add_argument('--prefix-module', type=str, default = '',\
-#                       help='add prefix module name.')
-#    group.add_argument('--language', type=str, help='target language')
-#
-#    ...
-#
-#    prefix = args.prefix
-#    prefix_module = args.prefix_module
-#    language = args.language
-#
-#    output_folder = args.output
-#
-#    if (len(output_folder)>0 and output_folder[-1]!='/'):
-#        output_folder+='/'
-#
-#    ...
-#
-#    elif args.convert_only:
-#        pyccel = Parser(filename)
-#        ast = pyccel.parse()
-#        settings = {}
-#        if args.language:
-#            settings['language'] = args.language
-#        ast = pyccel.annotate(**settings)
-#        name = os.path.basename(filename)
-#        name = os.path.splitext(name)[0]
-#        codegen = Codegen(ast, name)
-#        settings['prefix_module'] = prefix_module
-#        code = codegen.doprint(**settings)
-#        if prefix:
-#            name = '{prefix}{name}'.format(prefix=prefix, name=name)
-#
-#        codegen.export(output_folder+name)
-#
-#        for son in pyccel.sons:
-#            if 'print' in son.metavars.keys():
-#                name = son.filename.split('/')[-1].strip('.py')
-#                name = 'mod_'+name
-#                codegen = Codegen(son.ast, name)
-#                code = codegen.doprint()
-#                codegen.export()


Test patch:
diff --git a/tests/codegen/ccode/test_ccode_codegen.py b/tests/codegen/ccode/test_ccode_codegen.py
index b16e2a54..bd31e56c 100644
--- a/tests/codegen/ccode/test_ccode_codegen.py
+++ b/tests/codegen/ccode/test_ccode_codegen.py
@@ -45,8 +45,8 @@ def test_codegen(f):
     name = os.path.basename(f)
     name = os.path.splitext(name)[0]
 
-    codegen = Codegen(ast, name)
-    codegen.doprint(language='c')
+    codegen = Codegen(ast, name, 'c')
+    codegen.printer.doprint(codegen.ast)
 
     # Assert codegen success
     assert(not errors.has_errors())
diff --git a/tests/codegen/fcode/test_fcode_codegen.py b/tests/codegen/fcode/test_fcode_codegen.py
index 34593e4a..e3f96069 100644
--- a/tests/codegen/fcode/test_fcode_codegen.py
+++ b/tests/codegen/fcode/test_fcode_codegen.py
@@ -44,8 +44,8 @@ def test_codegen(f):
     name = os.path.basename(f)
     name = os.path.splitext(name)[0]
 
-    codegen = Codegen(ast, name)
-    codegen.doprint()
+    codegen = Codegen(ast, name, 'fortran')
+    codegen.printer.doprint(codegen.ast)
 
     # Assert codegen success
     assert(not errors.has_errors())
diff --git a/tests/codegen/pycode/test_pycode_codegen.py b/tests/codegen/pycode/test_pycode_codegen.py
index 02190377..33244e84 100644
--- a/tests/codegen/pycode/test_pycode_codegen.py
+++ b/tests/codegen/pycode/test_pycode_codegen.py
@@ -30,8 +30,8 @@ def test_codegen(f):
     name = os.path.basename(f)
     name = os.path.splitext(name)[0]
 
-    codegen = Codegen(ast, name)
-    codegen.doprint(language='python')
+    codegen = Codegen(ast, name, 'python')
+    codegen.printer.doprint(codegen.ast)
 
     # reset Errors singleton
     errors = Errors()
diff --git a/tests/errors/test_errors.py b/tests/errors/test_errors.py
index ca109ecd..50800b8b 100644
--- a/tests/errors/test_errors.py
+++ b/tests/errors/test_errors.py
@@ -148,9 +148,9 @@ def test_codegen_errors(f):
     name = os.path.basename(f)
     name = os.path.splitext(name)[0]
 
-    codegen = Codegen(ast, name)
+    codegen = Codegen(ast, name, 'fortran')
     with pytest.raises(PyccelCodegenError):
-        codegen.doprint()
+        codegen.printer.doprint(codegen.ast)
 
     assert(errors.has_errors())
 
diff --git a/tests/symbolic/test_symbolic.py b/tests/symbolic/test_symbolic.py
index aecdcfb0..d515e3c1 100644
--- a/tests/symbolic/test_symbolic.py
+++ b/tests/symbolic/test_symbolic.py
@@ -27,8 +27,8 @@ def test_symbolic(f):
     name = os.path.basename(f)
     name = os.path.splitext(name)[0]
 
-    codegen = Codegen(ast, name)
-    codegen.doprint()
+    codegen = Codegen(ast, name, 'fortran')
+    codegen.printer.doprint(codegen.ast)
 
     # reset Errors singleton
     errors = Errors()
diff --git a/tests/warnings/test_warnings.py b/tests/warnings/test_warnings.py
index 795931ad..3b93a9f3 100644
--- a/tests/warnings/test_warnings.py
+++ b/tests/warnings/test_warnings.py
@@ -69,8 +69,8 @@ def test_semantic_warnings(f):
 #    name = os.path.basename(f)
 #    name = os.path.splitext(name)[0]
 #
-#    codegen = Codegen(ast, name)
-#    code = codegen.doprint()
+#    codegen = Codegen(ast, name, 'fortran')
+#    code = codegen.printer.doprint(codegen.ast)
 #
 #    assert(errors.has_warnings())
 #    assert(not errors.has_errors())