Skip to content

Commit

Permalink
Update to Python ≥ 3.9
Browse files Browse the repository at this point in the history
  • Loading branch information
mstimberg committed Jul 26, 2023
1 parent 646fb55 commit 2cb91df
Show file tree
Hide file tree
Showing 10 changed files with 116 additions and 120 deletions.
124 changes: 61 additions & 63 deletions brian2genn/device.py

Large diffs are not rendered by default.

30 changes: 15 additions & 15 deletions brian2genn/genn_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ class GeNNCodeGenerator(CodeGenerator):
_floordiv_support_code + _pow_support_code)

def __init__(self, *args, **kwds):
super(GeNNCodeGenerator, self).__init__(*args, **kwds)
super().__init__(*args, **kwds)
self.c_data_type = c_data_type

@property
Expand All @@ -126,7 +126,7 @@ def get_array_name(var, access_data=True):
return device.get_array_name(var, access_data=False)

def translate_expression(self, expr):
for varname, var in iteritems(self.variables):
for varname, var in self.variables.items():
if isinstance(var, Function):
try:
impl_name = var.implementations[self.codeobj_class].name
Expand Down Expand Up @@ -179,9 +179,9 @@ def translate_to_write_arrays(self, statements):
def translate_one_statement_sequence(self, statements, scalar=False):
if len(statements) and self.template_name=='synapses':
_, _, _, conditional_write_vars = self.arrays_helper(statements)
vars_pre = [k for k, v in iteritems(self.variable_indices) if v=='_presynaptic_idx']
vars_syn = [k for k, v in iteritems(self.variable_indices) if v=='_idx']
vars_post = [k for k, v in iteritems(self.variable_indices) if v=='_postsynaptic_idx']
vars_pre = [k for k, v in self.variable_indices.items() if v=='_presynaptic_idx']
vars_syn = [k for k, v in self.variable_indices.items() if v=='_idx']
vars_post = [k for k, v in self.variable_indices.items() if v=='_postsynaptic_idx']
if '_pre_codeobject' in self.name:
post_write_var, statements = check_pre_code(self, statements,
vars_pre, vars_syn, vars_post,
Expand Down Expand Up @@ -213,7 +213,7 @@ def _add_user_function(self, varname, variable):
funccode = impl.get_code(self.owner)
if isinstance(funccode, str):
# Rename references to any dependencies if necessary
for dep_name, dep in iteritems(impl.dependencies):
for dep_name, dep in impl.dependencies.items():
dep_impl = dep.implementations[self.codeobj_class]
dep_impl_name = dep_impl.name
if dep_impl_name is None:
Expand All @@ -227,26 +227,26 @@ def _add_user_function(self, varname, variable):
# create global variables and assign to them in the main
# code
func_namespace = impl.get_namespace(self.owner) or {}
for ns_key, ns_value in iteritems(func_namespace):
for ns_key, ns_value in func_namespace.items():
if hasattr(ns_value, 'dtype'):
if ns_value.shape == ():
raise NotImplementedError((
raise NotImplementedError(
'Directly replace scalar values in the function '
'instead of providing them via the namespace'))
'instead of providing them via the namespace')
type_str = c_data_type(ns_value.dtype) + '*'
else: # e.g. a function
type_str = 'py::object'
support_code.append('static {0} _namespace{1};'.format(type_str,
support_code.append('static {} _namespace{};'.format(type_str,
ns_key))
pointers.append('_namespace{0} = {1};'.format(ns_key, ns_key))
pointers.append(f'_namespace{ns_key} = {ns_key};')
support_code.append(deindent(funccode.get('support_code', '')))
hash_defines.append(deindent(funccode.get('hashdefine_code', '')))

dep_hash_defines = []
dep_pointers = []
dep_support_code = []
if impl.dependencies is not None:
for dep_name, dep in iteritems(impl.dependencies):
for dep_name, dep in impl.dependencies.items():
if dep_name not in self.variables: # do not add a dependency twice
self.variables[dep_name] = dep
dep_impl = dep.implementations[self.codeobj_class]
Expand Down Expand Up @@ -275,7 +275,7 @@ def determine_keywords(self):
# Again, do the import here to avoid a circular dependency.
from brian2.devices.device import get_device
device = get_device()
for varname, var in iteritems(self.variables):
for varname, var in self.variables.items():
if isinstance(var, ArrayVariable):
# This is the "true" array name, not the restricted pointer.
array_name = device.get_array_name(var)
Expand All @@ -284,7 +284,7 @@ def determine_keywords(self):
continue
if get_var_ndim(var, 1) > 1:
continue # multidimensional (dynamic) arrays have to be treated differently
line = '{0}* {1} {2} = {3};'.format(self.c_data_type(var.dtype),
line = '{}* {} {} = {};'.format(self.c_data_type(var.dtype),
self.restrict,
pointer_name,
array_name)
Expand All @@ -295,7 +295,7 @@ def determine_keywords(self):
user_functions = []
support_code = []
hash_defines = []
for varname, variable in list(iteritems(self.variables)):
for varname, variable in list(self.variables.items()):
if isinstance(variable, Function):
hd, ps, sc, uf = self._add_user_function(varname, variable)
user_functions.extend(uf)
Expand Down
2 changes: 1 addition & 1 deletion brian2genn/insyn.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ def check_pre_code(codegen, stmts, vars_pre, vars_syn, vars_post,
# "write-protect" a variable during refractoriness to match Brian's semantics
if stmt.var in conditional_write_vars:
assert conditional_write_vars[stmt.var] == 'not_refractory'
accumulation_expr = 'int(not_refractory_post) * ({})'.format(accumulation_expr)
accumulation_expr = f'int(not_refractory_post) * ({accumulation_expr})'
else:
# TODO: we could support expressions like v = v + expr, but this requires some additional work
# namely, for an expression like v = expr we need to check if (expr-v) when simplified reduces to
Expand Down
2 changes: 1 addition & 1 deletion brian2genn/preferences.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from brian2.core.preferences import *

class DeprecatedValidator(object):
class DeprecatedValidator:
'''
'Validator' for deprecated preferences
Expand Down
8 changes: 4 additions & 4 deletions brian2genn/sphinxext/briandoc.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ def brianobj_role(role, rawtext, text, lineno, inliner, options={}, content=[]):
'''
if text in prefs:
linktext = text.replace('_', '-').replace('.', '-')
text = '%s <brian-pref-%s>' % (text, linktext)
text = f'{text} <brian-pref-{linktext}>'
# Use sphinx's cross-reference role
xref = XRefRole(warn_dangling=True)
return xref('std:ref', rawtext, text, lineno, inliner, options, content)
Expand Down Expand Up @@ -221,15 +221,15 @@ def setup(app, get_doc_object_=get_doc_object):
from sphinx.domains.c import CDomain
from sphinx.domains.python import PythonDomain

class ManglingDomainBase(object):
class ManglingDomainBase:
directive_mangling_map = {}

def __init__(self, *a, **kw):
super(ManglingDomainBase, self).__init__(*a, **kw)
super().__init__(*a, **kw)
self.wrap_mangling_directives()

def wrap_mangling_directives(self):
for name, objtype in iteritems(self.directive_mangling_map):
for name, objtype in self.directive_mangling_map.items():
self.directives[name] = wrap_mangling_directive(
self.directives[name], objtype)

Expand Down
38 changes: 19 additions & 19 deletions brian2genn/sphinxext/docscrape.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

from sphinx.pycode import ModuleAnalyzer

class Reader(object):
class Reader:
"""A line-based string reader.
"""
Expand Down Expand Up @@ -85,7 +85,7 @@ def is_empty(self):
return not ''.join(self._str).strip()


class NumpyDocString(object):
class NumpyDocString:
def __init__(self, docstring, config={}):
docstring = textwrap.dedent(docstring).split('\n')

Expand Down Expand Up @@ -272,7 +272,7 @@ def _parse_summary(self):

summary = self._doc.read_to_next_empty_line()
summary_str = " ".join([s.strip() for s in summary]).strip()
if re.compile('^([\w., ]+=)?\s*[\w\.]+\(.*\)$').match(summary_str):
if re.compile(r'^([\w., ]+=)?\s*[\w\.]+\(.*\)$').match(summary_str):
self['Signature'] = summary_str
if not self._is_at_section():
self['Summary'] = self._doc.read_to_next_empty_line()
Expand Down Expand Up @@ -312,7 +312,7 @@ def _str_indent(self, doc, indent=4):

def _str_signature(self):
if self['Signature']:
return [self['Signature'].replace('*','\*')] + ['']
return [self['Signature'].replace('*',r'\*')] + ['']
else:
return ['']

Expand All @@ -333,7 +333,7 @@ def _str_param_list(self, name):
if self[name]:
out += self._str_header(name)
for param,param_type,desc in self[name]:
out += ['%s : %s' % (param, param_type)]
out += [f'{param} : {param_type}']
out += self._str_indent(desc)
out += ['']
return out
Expand All @@ -354,9 +354,9 @@ def _str_see_also(self, func_role):
last_had_desc = True
for func, desc, role in self['See Also']:
if role:
link = ':%s:`%s`' % (role, func)
link = f':{role}:`{func}`'
elif func_role:
link = ':%s:`%s`' % (func_role, func)
link = f':{func_role}:`{func}`'
else:
link = "`%s`_" % func
if desc or last_had_desc:
Expand All @@ -376,10 +376,10 @@ def _str_index(self):
idx = self['index']
out = []
out += ['.. index:: %s' % idx.get('default','')]
for section, references in iteritems(idx):
for section, references in idx.items():
if section == 'default':
continue
out += [' :%s: %s' % (section, ', '.join(references))]
out += [' :{}: {}'.format(section, ', '.join(references))]
return out

def __str__(self, func_role=''):
Expand Down Expand Up @@ -432,8 +432,8 @@ def __init__(self, func, role='func', doc=None, config={}):
# try to read signature
argspec = inspect.getargspec(func)
argspec = inspect.formatargspec(*argspec)
argspec = argspec.replace('*','\*')
signature = '%s%s' % (func_name, argspec)
argspec = argspec.replace('*',r'\*')
signature = f'{func_name}{argspec}'
except TypeError:
signature = '%s()' % func_name
self['Signature'] = signature
Expand All @@ -457,10 +457,10 @@ def __str__(self):
if self._role:
if self._role not in roles:
print("Warning: invalid role %s" % self._role)
out += '.. %s:: %s\n \n\n' % (roles.get(self._role,''),
out += '.. {}:: {}\n \n\n'.format(roles.get(self._role,''),
func_name)

out += super(FunctionDoc, self).__str__(func_role=self._role)
out += super().__str__(func_role=self._role)
return out


Expand Down Expand Up @@ -496,7 +496,7 @@ def __init__(self, cls, doc=None, modulename='', func_doc=FunctionDoc,
def methods(self):
if self._cls is None:
return []
methods = [name for name, func in iteritems(getattr(self._cls, '__dict__'))
methods = [name for name, func in getattr(self._cls, '__dict__').items()
if ((not name.startswith('_')
or name in self.extra_public_methods)
and ((callable(func) and not isinstance(func, type)) or
Expand All @@ -508,11 +508,11 @@ def properties(self):
if self._cls is None:
return []
analyzer = ModuleAnalyzer.for_module(self._cls.__module__)
instance_members = set([attr_name for (class_name, attr_name) in
iterkeys(analyzer.find_attr_docs())
if class_name == self._cls.__name__])
class_members = set([name for name, func in iteritems(getattr(self._cls, '__dict__'))
instance_members = {attr_name for (class_name, attr_name) in
analyzer.find_attr_docs().keys()
if class_name == self._cls.__name__}
class_members = {name for name, func in getattr(self._cls, '__dict__').items()
if not name.startswith('_') and (func is None or
inspect.isdatadescriptor(func))])
inspect.isdatadescriptor(func))}

return instance_members | class_members
14 changes: 7 additions & 7 deletions brian2genn/sphinxext/docscrape_sphinx.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def _str_param_list(self, name):
out += self._str_field_list(name)
out += ['']
for param, param_type, desc in self[name]:
out += self._str_indent(['**%s** : %s' % (param.strip(),
out += self._str_indent(['**{}** : {}'.format(param.strip(),
param_type)])
out += ['']
out += self._str_indent(desc, 8)
Expand Down Expand Up @@ -91,7 +91,7 @@ def _str_member_list(self):
doc='\n'.join(desc)))

if len(prefix):
autosum += [" ~%s%s" % (prefix, param)]
autosum += [f" ~{prefix}{param}"]
else:
autosum += [" %s" % param]

Expand All @@ -117,9 +117,9 @@ def _str_member_docs(self, name):

for param, _, _ in self[name]:
if name == 'Methods':
out += ['.. automethod:: %s%s' % (prefix, param)]
out += [f'.. automethod:: {prefix}{param}']
elif name == 'Attributes':
out += ['.. autoattribute:: %s%s' % (prefix, param)]
out += [f'.. autoattribute:: {prefix}{param}']

out += ['']
return out
Expand All @@ -137,7 +137,7 @@ def _str_section(self, name):
def _str_see_also(self, func_role):
out = []
if self['See Also']:
see_also = super(SphinxDocString, self)._str_see_also(func_role)
see_also = super()._str_see_also(func_role)
out = ['.. seealso::', '']
out += self._str_indent(see_also[2:])
return out
Expand Down Expand Up @@ -168,13 +168,13 @@ def _str_index(self):
return out

out += ['.. index:: %s' % idx.get('default','')]
for section, references in iteritems(idx):
for section, references in idx.items():
if section == 'default':
continue
elif section == 'refguide':
out += [' single: %s' % (', '.join(references))]
else:
out += [' %s: %s' % (section, ','.join(references))]
out += [' {}: {}'.format(section, ','.join(references))]
return out

def _str_references(self):
Expand Down
6 changes: 3 additions & 3 deletions brian2genn/sphinxext/examplefinder.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def get_map(environ_var, relrootdir, pattern, the_map, path_exclusions=[]):
shortfnames = [os.path.relpath(fname, rootdir) for fname in fnames]
exnames = [fname.replace('/', '.').replace('\\', '.').replace(pattern, '') for fname in shortfnames]
for fname, shortfname, exname in zip(fnames, shortfnames, exnames):
ex = open(fname, 'r').read()
ex = open(fname).read()
ids = get_identifiers(ex)
for id in ids:
the_map[id].append((shortfname.replace('\\', '/'), exname))
Expand Down Expand Up @@ -60,10 +60,10 @@ def auto_find_examples(obj, headersymbol='='):
txt = txt+'\n'+headersymbol*len(txt)+'\n\n'
for tutname, tutloc in tutorials:
tutname = tutname.replace('.ipynb', '')
txt += '* Tutorial :doc:`%s </resources/tutorials/%s>`\n' % (tutname, tutloc)
txt += f'* Tutorial :doc:`{tutname} </resources/tutorials/{tutloc}>`\n'
for exname, exloc in examples:
exname = exname.replace('.py', '')
txt += '* Example :doc:`%s </examples/%s>`\n' % (exname, exloc)
txt += f'* Example :doc:`{exname} </examples/{exloc}>`\n'
return txt+'\n'


Expand Down
5 changes: 2 additions & 3 deletions brian2genn/sphinxext/generate_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def main(rootpath, destdir):
examplesbasenames.append(filebase)
relativepaths.append(relpath)
outnames.append(exname)
examplescode = [open(fname, 'rU').read() for fname in examplesfnames]
examplescode = [open(fname).read() for fname in examplesfnames]
examplesdocs = []
examplesafterdoccode = []
examplesdocumentablenames = []
Expand Down Expand Up @@ -132,7 +132,7 @@ def insert_category(category, mainpage_text):
mainpage_text += ' :maxdepth: 1\n\n'
curpath = ''
for exname, basename in sorted(categories[category]):
mainpage_text += ' %s <%s>\n' % (basename, exname)
mainpage_text += f' {basename} <{exname}>\n'
return mainpage_text

mainpage_text = insert_category('', mainpage_text)
Expand All @@ -145,4 +145,3 @@ def insert_category(category, mainpage_text):

if __name__=='__main__':
main('../../examples', '../../docs_sphinx/examples')

7 changes: 3 additions & 4 deletions brian2genn/sphinxext/generate_reference.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
"""
Automatically generate Brian's reference documentation.
Expand Down Expand Up @@ -30,7 +29,7 @@ def makename(package, module):

def write_file(name, text, destdir, suffix):
"""Write the output file for module/package <name>."""
fname = path.join(destdir, '%s.%s' % (name, suffix))
fname = path.join(destdir, f'{name}.{suffix}')
print('Creating file %s.' % fname)
f = open(fname, 'w')
try:
Expand All @@ -42,7 +41,7 @@ def write_file(name, text, destdir, suffix):
def format_heading(level, text):
"""Create a heading of <level> [1, 2 or 3 supported]."""
underlining = ['=', '-', '~', ][level-1] * len(text)
return '%s\n%s\n\n' % (text, underlining)
return f'{text}\n{underlining}\n\n'


def format_directive(module, destdir, package=None, basename='brian2genn'):
Expand Down Expand Up @@ -169,7 +168,7 @@ def create_package_file(root, master_package, subroot, py_files, subs,
text += ' :maxdepth: 2\n\n'
for sub in subs:
if not is_excluded(os.path.join(root, sub), excludes):
text += ' %s.%s\n' % (makename(master_package, subroot), sub)
text += f' {makename(master_package, subroot)}.{sub}\n'
text += '\n'

write_file(makename(master_package, subroot), text, destdir, suffix)
Expand Down

0 comments on commit 2cb91df

Please sign in to comment.