Skip to content

Commit dcfdc6e

Browse files
authored
Apply some Pylint fixes, Part 1: Clean up parser (pyccel#1826)
Clean up the `parser/` folder by fixing missing fstrings. As a result docstrings are also improved.
1 parent cd6f30f commit dcfdc6e

File tree

4 files changed

+129
-65
lines changed

4 files changed

+129
-65
lines changed

pyccel/parser/base.py

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,8 @@ def get_filename_from_import(module, input_folder=''):
8989
while filename.startswith('/'):
9090
filename = folder_above + filename[1:]
9191

92-
filename_pyh = '{}.pyh'.format(filename)
93-
filename_py = '{}.py'.format(filename)
92+
filename_pyh = f'{filename}.pyh'
93+
filename_py = f'{filename}.py'
9494

9595
poss_filename_pyh = os.path.join( input_folder, filename_pyh )
9696
poss_filename_py = os.path.join( input_folder, filename_py )
@@ -106,8 +106,8 @@ def get_filename_from_import(module, input_folder=''):
106106

107107
source = """.""".join(i for i in module.split(""".""")[:-1])
108108
_module = module.split(""".""")[-1]
109-
filename_pyh = '{}.pyh'.format(_module)
110-
filename_py = '{}.py'.format(_module)
109+
filename_pyh = f'{_module}.pyh'
110+
filename_py = f'{_module}.py'
111111

112112
try:
113113
package = importlib.import_module(source)
@@ -402,6 +402,8 @@ def exit_loop_scope(self):
402402

403403
def create_new_class_scope(self, name, **kwargs):
404404
"""
405+
Create a new scope for a Python class.
406+
405407
Create a new Scope object for a Python class with the given name,
406408
and attach any decorators' information to the scope. The new scope is
407409
a child of the current one, and can be accessed from the dictionary of
@@ -416,6 +418,13 @@ def create_new_class_scope(self, name, **kwargs):
416418
name : str
417419
Function's name, used as a key to retrieve the new scope.
418420
421+
**kwargs : dict
422+
A dictionary containing any additional arguments of the new scope.
423+
424+
Returns
425+
-------
426+
Scope
427+
The scope for the class.
419428
"""
420429
child = self.scope.new_child_scope(name, **kwargs)
421430
self._scope = child
@@ -431,11 +440,13 @@ def dump(self, filename=None):
431440
"""
432441
Dump the current ast using Pickle.
433442
434-
Parameters
435-
----------
436-
filename: str
437-
output file name. if not given `name.pyccel` will be used and placed
438-
in the Pyccel directory ($HOME/.pyccel)
443+
Dump the current ast using Pickle.
444+
445+
Parameters
446+
----------
447+
filename : str
448+
Output file name. if not given `name.pyccel` will be used and placed
449+
in the Pyccel directory ($HOME/.pyccel).
439450
"""
440451
if self._created_from_pickle:
441452
return
@@ -450,7 +461,7 @@ def dump(self, filename=None):
450461
if ext != '.pyh':
451462
return
452463

453-
name = '{}.pyccel'.format(name)
464+
name = f'{name}.pyccel'
454465
filename = os.path.join(path, name)
455466
# check extension
456467

@@ -460,7 +471,6 @@ def dump(self, filename=None):
460471
import pickle
461472
import hashlib
462473

463-
# print('>>> home = ', os.environ['HOME'])
464474
# ...
465475

466476
# we are only exporting the AST.
@@ -478,13 +488,15 @@ def dump(self, filename=None):
478488
warnings.warn("Can't pickle files on a read-only system. Please run `sudo pyccel-init`")
479489

480490
def load(self, filename=None):
481-
""" Load the current ast using Pickle.
491+
"""
492+
Load the current ast using Pickle.
482493
483-
Parameters
484-
----------
485-
filename: str
486-
output file name. if not given `name.pyccel` will be used and placed
487-
in the Pyccel directory ($HOME/.pyccel)
494+
Load the current ast using Pickle.
495+
496+
Parameters
497+
----------
498+
filename : str, optional
499+
The name of the pickled file. if not given `name.pyccel` will be used.
488500
"""
489501

490502
# ...
@@ -500,7 +512,7 @@ def load(self, filename=None):
500512
if ext != '.pyh':
501513
return
502514

503-
name = '{}.pyccel'.format(name)
515+
name = f'{name}.pyccel'
504516
filename = os.path.join(path, name)
505517

506518
if not filename.split(""".""")[-1] == 'pyccel':

pyccel/parser/parser.py

Lines changed: 42 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,19 @@
1717
# TODO [AR, 18.11.2018] to be modified as a function
1818
# TODO [YG, 28.01.2020] maybe pass filename to the parse method?
1919
class Parser(object):
20+
"""
21+
A wrapper class which handles dependencies between the syntactic and semantic parsers.
22+
23+
A wrapper class which handles dependencies between the syntactic and semantic parsers.
24+
25+
Parameters
26+
----------
27+
filename : str
28+
The name of the file being translated.
29+
30+
**kwargs : dict
31+
Any keyword arguments for BasicParser.
32+
"""
2033

2134
def __init__(self, filename, **kwargs):
2235

@@ -181,24 +194,26 @@ def append_son(self, son):
181194
self._sons.append(son)
182195

183196
def parse_sons(self, d_parsers_by_filename, verbose=False):
184-
"""Recursive algorithm for syntax analysis on a given file and its
197+
"""
198+
Parse the files on which this file is dependent.
199+
200+
Recursive algorithm for syntax analysis on a given file and its
185201
dependencies.
186202
This function always terminates with an dict that contains parsers
187203
for all involved files.
188204
189-
Parameters
190-
----------
191-
d_parsers_by_filename : dict
192-
A dictionary of parsed sons.
205+
Parameters
206+
----------
207+
d_parsers_by_filename : dict
208+
A dictionary of parsed sons.
193209
194-
verbose: bool
195-
Determine the verbosity.
196-
197-
Results
198-
-------
199-
d_parsers: dict
200-
The updated dictionary of parsed sons.
210+
verbose : bool, default=False
211+
Set the verbosity.
201212
213+
Returns
214+
-------
215+
dict
216+
The updated dictionary of parsed sons.
202217
"""
203218

204219
imports = self.imports
@@ -207,7 +222,7 @@ def parse_sons(self, d_parsers_by_filename, verbose=False):
207222
not_treated = [i for i in source_to_filename.values() if i not in treated]
208223
for filename in not_treated:
209224
if verbose:
210-
print ('>>> treating :: {}'.format(filename))
225+
print ('>>> treating :: ', filename)
211226

212227
# get the absolute path corresponding to source
213228
if filename in d_parsers_by_filename:
@@ -228,25 +243,33 @@ def parse_sons(self, d_parsers_by_filename, verbose=False):
228243

229244
return d_parsers
230245

231-
def _annotate_sons(self, **settings):
246+
def _annotate_sons(self, verbose = False):
247+
"""
248+
Annotate any dependencies of the file currently being parsed.
232249
233-
verbose = settings.pop('verbose', False)
250+
Annotate any dependencies of the file currently being parsed.
251+
252+
Parameters
253+
----------
254+
verbose : bool, default=False
255+
Indicates if the treatment should be run in verbose mode.
256+
"""
234257

235258
# we first treat sons that have no imports
236259

237260
for p in self.sons:
238261
if not p.sons:
239262
if verbose:
240-
print ('>>> treating :: {}'.format(p.filename))
241-
p.annotate(**settings)
263+
print ('>>> treating :: ', p.filename)
264+
p.annotate()
242265

243266
# finally we treat the remaining sons recursively
244267

245268
for p in self.sons:
246269
if p.sons:
247270
if verbose:
248-
print ('>>> treating :: {}'.format(p.filename))
249-
p.annotate(**settings)
271+
print ('>>> treating :: ', p.filename)
272+
p.annotate()
250273

251274
#==============================================================================
252275

pyccel/parser/scope.py

Lines changed: 55 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ def new_child_scope(self, name, **kwargs):
127127
"""
128128
ps = kwargs.pop('parent_scope', self)
129129
if ps is not self:
130-
raise ValueError("A child of {} cannot have a parent {}".format(self, ps))
130+
raise ValueError(f"A child of {self} cannot have a parent {ps}")
131131

132132
child = Scope(name=name, **kwargs, parent_scope = self)
133133

@@ -308,21 +308,17 @@ def create_new_loop_scope(self):
308308
return new_scope
309309

310310
def insert_variable(self, var, name = None):
311-
""" Add a variable to the current scope
311+
"""
312+
Add a variable to the current scope.
313+
314+
Add a variable to the current scope.
312315
313316
Parameters
314317
----------
315-
var : Variable
316-
The variable to be inserted into the current scope
317-
name : str
318-
The name of the variable in the python code
319-
Default : var.name
320-
python_scope : bool
321-
If true then we assume that python scoping applies.
322-
In this case variables declared in loops exist beyond
323-
the end of the loop. Otherwise variables may be local
324-
to loops
325-
Default : True
318+
var : Variable
319+
The variable to be inserted into the current scope.
320+
name : str, default=var.name
321+
The name of the variable in the Python code.
326322
"""
327323
if var.name == '_':
328324
raise ValueError("A temporary variable should have a name generated by Scope.get_new_name")
@@ -336,7 +332,7 @@ def insert_variable(self, var, name = None):
336332
self.parent_scope.insert_variable(var, name)
337333
else:
338334
if name in self._locals['variables']:
339-
raise RuntimeError('New variable {} already exists in scope'.format(name))
335+
raise RuntimeError(f'New variable {name} already exists in scope')
340336
if name == '_':
341337
self._temporary_variables.append(var)
342338
else:
@@ -645,17 +641,24 @@ def get_new_name(self, current_name = None):
645641

646642
def get_temporary_variable(self, dtype_or_var, name = None, **kwargs):
647643
"""
648-
Get a temporary variable
644+
Get a temporary variable.
645+
646+
Get a temporary variable.
649647
650648
Parameters
651649
----------
652650
dtype_or_var : str, DataType, Variable
653651
In the case of a string of DataType: The type of the Variable to be created
654-
In the case of a Variable: a Variable which will be cloned to set all the Variable properties
655-
name : str
656-
The requested name for the new variable
657-
kwargs : dict
658-
See Variable keyword arguments
652+
In the case of a Variable: a Variable which will be cloned to set all the Variable properties.
653+
name : str, optional
654+
The requested name for the new variable.
655+
**kwargs : dict
656+
See Variable keyword arguments.
657+
658+
Returns
659+
-------
660+
Variable
661+
The temporary variable.
659662
"""
660663
assert isinstance(name, (str, type(None)))
661664
name = self.get_new_name(name)
@@ -667,8 +670,21 @@ def get_temporary_variable(self, dtype_or_var, name = None, **kwargs):
667670
return var
668671

669672
def get_expected_name(self, start_name):
670-
""" Get a name with no collisions, ideally the provided name.
671-
The provided name should already exist in the symbols
673+
"""
674+
Get a name with no collisions.
675+
676+
Get a name with no collisions, ideally the provided name.
677+
The provided name should already exist in the symbols.
678+
679+
Parameters
680+
----------
681+
start_name : str
682+
The name which was used in the Python code.
683+
684+
Returns
685+
-------
686+
PyccelSymbol
687+
The name which will be used in the generated code.
672688
"""
673689
if start_name == '_':
674690
return self.get_new_name()
@@ -677,7 +693,7 @@ def get_expected_name(self, start_name):
677693
elif self.parent_scope:
678694
return self.parent_scope.get_expected_name(start_name)
679695
else:
680-
raise RuntimeError("{} does not exist in scope".format(start_name))
696+
raise RuntimeError(f"{start_name} does not exist in scope")
681697

682698
def create_product_loop_scope(self, inner_scope, n_loops):
683699
""" Create a n_loops loop scopes such that the innermost loop
@@ -749,15 +765,28 @@ def add_son(self, name, son):
749765
self._sons_scopes[name] = son
750766

751767
def get_python_name(self, name):
752-
""" Get the name used in the original python code from the
753-
name used by the variable
768+
"""
769+
Get the name used in the original Python code.
770+
771+
Get the name used in the original Python code from the name used
772+
by the variable that was created in the parser.
773+
774+
Parameters
775+
----------
776+
name : PyccelSymbol | str
777+
The name of the Variable in the generated code.
778+
779+
Returns
780+
-------
781+
str
782+
The name of the Variable in the original code.
754783
"""
755784
if name in self._original_symbol:
756785
return self._original_symbol[name]
757786
elif self.parent_scope:
758787
return self.parent_scope.get_python_name(name)
759788
else:
760-
raise RuntimeError("Can't find {} in scope".format(name))
789+
raise RuntimeError(f"Can't find {name} in scope")
761790

762791
@property
763792
def python_names(self):

pyccel/parser/syntactic.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -541,7 +541,7 @@ def _visit_Constant(self, stmt):
541541
return LiteralEllipsis()
542542

543543
else:
544-
raise NotImplementedError('Constant type {} not recognised'.format(type(stmt.value)))
544+
raise NotImplementedError(f'Constant type {type(stmt.value)} not recognised')
545545

546546
def _visit_Name(self, stmt):
547547
name = PyccelSymbol(stmt.id)
@@ -1109,7 +1109,7 @@ def _visit_Call(self, stmt):
11091109
func_attr = FunctionCall(func.name[-1], args)
11101110
func = DottedName(*func.name[:-1], func_attr)
11111111
else:
1112-
raise NotImplementedError(' Unknown function type {}'.format(str(type(func))))
1112+
raise NotImplementedError(f' Unknown function type {type(func)}')
11131113

11141114
return func
11151115

0 commit comments

Comments
 (0)