Subject: Re: [Ufl] [Branch ~ufl-core/ufl/main] Rev 1021: Initial work on replacement for UFL set_foo functions

From: Martin Sandve Alnæs <[email-masked]>
Date: Mon, 2 May 2011 13:26:58 +0200

Declaring default arguments with mutable object like dicts such as
this line is dangerous in Python.
def compute_form_data(self, object_names={}, common_cell=None,
element_mapping={}):
If object_names or element_mapping is modified, the
modifications change the default object for future calls.

Therefore it's a good habit to use None instead:
def compute_form_data(self, object_names=None, common_cell=None,
element_mapping=None):
    if object_names is None: object_names = {}
    if element_mapping is None: element_mapping = {}
    ...

Martin

On 2 May 2011 10:13,  <[email-masked]> wrote:
> ------------------------------------------------------------
> revno: 1021
> committer: Anders Logg <[email-masked]>
> branch nick: ufl-main
> timestamp: Mon 2011-05-02 10:11:12 +0200
> message:
>  Initial work on replacement for UFL set_foo functions
> modified:
>  ufl/algorithms/preprocess.py
>  ufl/form.py
>
>
> --
> lp:ufl
> https://code.launchpad.net/~ufl-core/ufl/main
>
> Your team UFL Core Team is subscribed to branch lp:ufl.
> To unsubscribe from this branch go to https://code.launchpad.net/~ufl-core/ufl/main/+edit-subscription
>
> === modified file 'ufl/algorithms/preprocess.py'
> --- ufl/algorithms/preprocess.py        2011-04-26 20:03:38 +0000
> +++ ufl/algorithms/preprocess.py        2011-05-02 08:11:12 +0000
> @@ -7,7 +7,7 @@
>  __license__  = "GNU LGPL version 3 or any later version"
>  __date__ = "2009-12-07"
>
> -# Last changed: 2011-04-26
> +# Last changed: 2011-05-02
>
>  from ufl.log import info, debug, warning, error
>  from ufl.assertions import ufl_assert
> @@ -21,7 +21,7 @@
>  from ufl.algorithms.analysis import extract_num_sub_domains, extract_integral_data, unique_tuple
>  from ufl.algorithms.formdata import FormData
>
> -def preprocess(form, object_names={}, common_cell=None):
> +def preprocess(form, object_names={}, common_cell=None, element_mapping={}):
>     """
>     Preprocess raw input form to obtain form metadata, including a
>     modified (preprocessed) form more easily manipulated by form
> @@ -94,24 +94,8 @@
>     form_data.sub_elements        = extract_sub_elements(form_data.elements)
>     form_data.unique_sub_elements = unique_tuple(form_data.sub_elements)
>
> -    # FIXME: Need to look at logic here, FFC does not support the last two cases
> -
> -    # Store cell
> -    if not common_cell is None:
> -        form_data.cell = common_cell
> -    elif form_data.elements:
> -        cells = [element.cell() for element in form_data.elements]
> -        cells = [cell for cell in cells if not cell.domain() is None]
> -        if len(cells) == 0:
> -            error("Unable to extract form data. Reason: Missing cell definition in form.")
> -        form_data.cell = cells[0]
> -    elif form._integrals:
> -        # Special case to allow functionals only depending on geometric variables, with no elements
> -        form_data.cell = form._integrals[0].integrand().cell()
> -    else:
> -        # Special case to allow integral of constants to pass through without crashing
> -        form_data.cell = None
> -        warning("Form is empty, no elements or integrals, cell is undefined.")
> +    # Store common cell
> +    form_data.cell = common_cell
>
>     # Store data related to cell
>     if form_data.cell is None:
>
> === modified file 'ufl/form.py'
> --- ufl/form.py 2011-04-26 20:03:38 +0000
> +++ ufl/form.py 2011-05-02 08:11:12 +0000
> @@ -96,11 +96,11 @@
>         "Return form metadata (None if form has not been preprocessed)"
>         return self._form_data
>
> -    def compute_form_data(self, object_names={}, common_cell=None):
> +    def compute_form_data(self, object_names={}, common_cell=None, element_mapping={}):
>         "Compute and return form metadata"
>         if self._form_data is None:
>             from ufl.algorithms.preprocess import preprocess
> -            self._form_data = preprocess(self, object_names, common_cell)
> +            self._form_data = preprocess(self, object_names, common_cell, element_mapping)
>         return self.form_data()
>
>     def is_preprocessed(self):
>
>
>

---

From: Anders Logg <[email-masked]>
Date: Mon, 2 May 2011 22:55:53 +0200

> modifications change the default object for future calls.

How do you mean modified? You mean the default will change if a value
is passed to the function with element_mapping=<something>?

>     if element_mapping is None: element_mapping = {}

ok.

--
Anders

> _______________________________________________
> Mailing list: https://launchpad.net/~ufl
> Post to     : [email-masked]
> Unsubscribe : https://launchpad.net/~ufl
> More help   : https://help.launchpad.net/ListHelp

---

From: Johan Hake <[email-masked]>
Date: Mon, 2 May 2011 14:02:02 -0700

Run this and see whats happens:

def jada(bada=[]):
    bada.append(5)
    return bada

print jada()
print jada()

Johan

On Monday May 2 2011 13:55:53 Anders Logg wrote:
> > > To unsubscribe from this branch go to
> > > https://code.launchpad.net/~ufl-core/ufl/main/+edit-subscription
> > > 
> > >  from ufl.algorithms.analysis import extract_num_sub_domains,
> > > extract_integral_data, unique_tuple from ufl.algorithms.formdata
> > > import FormData
> > > 
> > > +def preprocess(form, object_names={}, common_cell=None,
> > > element_mapping={}): """
> > >     form_data.sub_elements        =
> > > extract_sub_elements(form_data.elements) form_data.unique_sub_elements
> > > = unique_tuple(form_data.sub_elements)
> > > 
> > > -    # FIXME: Need to look at logic here, FFC does not support the last
> > > two cases -
> > > -    # Store cell
> > > -            error("Unable to extract form data. Reason: Missing cell
> > > definition in form.") -        form_data.cell = cells[0]
> > > -    elif form._integrals:
> > > -        # Special case to allow functionals only depending on
> > > geometric variables, with no elements -        form_data.cell =
> > > form._integrals[0].integrand().cell() -    else:
> > > -        # Special case to allow integral of constants to pass through
> > > without crashing -        form_data.cell = None
> > > -        warning("Form is empty, no elements or integrals, cell is
> > > undefined.") +    # Store common cell
> > > +    def compute_form_data(self, object_names={}, common_cell=None,
> > > element_mapping={}): "Compute and return form metadata"
> > > -            self._form_data = preprocess(self, object_names,
> > > common_cell) +            self._form_data = preprocess(self,
> > > object_names, common_cell, element_mapping) return self.form_data()
> >

---

From: Anders Logg <[email-masked]>
Date: Mon, 2 May 2011 23:37:23 +0200

> Run this and see whats happens:

Cool. I didn't know. Looks like a good feature that could be used to
write some obfuscated Python code. :-)

--
Anders

---

From: Johan Hake <[email-masked]>
Date: Mon, 2 May 2011 14:40:31 -0700

> write some obfuscated Python code. :-)

Hold your horses!

Johan