Re: Suggestion: a new "nature" field in Trac
On Apr 1, 10:36 am, Russell Keith-Magee wrote: > On Wed, Mar 30, 2011 at 7:42 AM, Russell Keith-Magee > > wrote: > > Barring objection, I'll try to find some time this afternoon to > > introduce the new flags. > > A little later than originally intended... but I've just made these changes. > > Ladies and Gentlemen start your triage! > > Russ %-) Just a quick note, Russell -- The 'Type' isn't showing up in the ticket summary (yellow frame) at the top. The 'Severity' is showing though. Julien -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.
Re: Suggestion: a new "nature" field in Trac
On Fri, Apr 1, 2011 at 3:12 PM, Julien Phalip wrote: > On Apr 1, 10:36 am, Russell Keith-Magee > wrote: >> On Wed, Mar 30, 2011 at 7:42 AM, Russell Keith-Magee >> >> wrote: >> > Barring objection, I'll try to find some time this afternoon to >> > introduce the new flags. >> >> A little later than originally intended... but I've just made these changes. >> >> Ladies and Gentlemen start your triage! >> >> Russ %-) > > Just a quick note, Russell -- The 'Type' isn't showing up in the > ticket summary (yellow frame) at the top. The 'Severity' is showing > though. Your may need to open a ticket for that; I don't have access to the server to make the change. Yours, Russ Magee %-) -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.
Re: Suggestion: a new "nature" field in Trac
On Apr 1, 10:36 am, Russell Keith-Magee wrote: > On Wed, Mar 30, 2011 at 7:42 AM, Russell Keith-Magee > > wrote: > > Barring objection, I'll try to find some time this afternoon to > > introduce the new flags. > > A little later than originally intended... but I've just made these changes. > > Ladies and Gentlemen start your triage! > > Russ %-) Awesome! It only took 36 emails to get there :-) Updating the 1800 open tickets is a big task, and to avoid duplicating work I have set up a spreadsheet to coordinate our efforts: https://spreadsheets.google.com/ccc?key=0AoGUYlz9V54IdFQtbEpyZTctQzhhQTlfMWdmWGt2a3c&hl=en If you'd like to volunteer, please put your name next to the page numbers (18 pages x 100 tickets per page in total). Here's the list of open tickets ordered by ids: http://code.djangoproject.com/query?status=!closed&order=id Maybe I'm over-engineering this, oh well... ;-) Happy triaging! Julien -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.
Re: GSoc : Templates Compilation
Hi, Jonathan I was considering two approaches : template compilation with static inheritance and template compilation with static and dynamic inheritance. The first one approach has simple way of compilation : 1.Reading template in string 2.Tokenizing 3.Parsing — creating NodeList structure 4.Recuirsive NodeList tree compiling. Note: parent templatea already in this tree. And my task is to repeat this structure in python bytecode. E.g. Template ('TextNodePart\n{% block some_block %}BlockNode 'some_block'{% if True %}IfNode{% endif %}{%endblock%}') : from ... import ... def render(context): print "TextNodePart" print "BlockNode 'some_block'" if True : print "IfNode" or, e.g. With static inheritance Template('{% extends 'base.html' %} SomeTextNode{% block some_block %}{% if True %}ifNode{% endif %}{% endblock%}'), where base.html — Template('{% block some_block %}{% endblock %}{% block other_block %}TextNode{% endblock %}') will be looked : from … import … def render(context): if True : print "ifNode" print "TextNode" But template compilation with dynamic inheritance is a bit more complicated. Real template structure isn't known at compilation time of template, because it isn't known what template it will be. At runtime i tried to find template, compile it, or just import already compiled template. Structure of final template will be known also at runtime - thats why I'm collecting blocks output sequence - to output in this sequence. E.g. : child.html : {% extends parent %} {% block first_block %} {% if True %} some_info {% endif %} {% endblock %} {% block second_block %} {% endblock %} parent.html : TextNode {% block first_block %} {% endblock %} In this example child template has 2 block : first_block and second_block, but parent template has only 1 block : first_block. And in this situation I have to print only first_block output... Compiled child template : from ... import ... blocks_output = Template_BlockOutput() blocks_output_sequence = list() def output(): for block_name in blocks_output_sequence : if blocks_output.has_key(block_name) : print blocks_output[block_name] def render(context,no_output=False): blocks_output['first_block'] = '' # entering block tag blocks_sequence_output.append('first_block') if True : blocks_output['first_block'] = blocks_output['first_block'] + "some_info" blocks_output['second_block'] = '' # entering block tag extenal_blocks_output, external_blocks_sequence_output = get_compiled_template_or_create(context.parent,no_output=True) blocks_output.append(external_blocks_output) blocks_sequence_output = external_blocks_sequence_output """ function footer """ if no_output : return blocks_output, blocks_output_sequence else : output() Compiled parent template : from ... import ... blocks_output = Template_BlockOutput() blocks_output_sequence = list() def output(): for block_name in blocks_output_sequence : if blocks_output.has_key(block_name) : print blocks_output[block_name] def render(context,no_output=False): blocks_output['first_block'] = '' # entering block tag blocks_sequence_output.append('first_block') """ function footer """ if no_output : return blocks_output, blocks_output_sequence else : output() This is draft version of compilation, it has number of defects. I'm solving them now. On Apr 1, 12:50 am, Jonathan Slenders wrote: > Another one: > > Instead of: > def has_key(self,key): > for level in xrange(0,len(self._levels)) : > if self._levels[level].has_key(key) : > return True > return False > > do: > def has_key(self,key): > return any((key in l) for l in self._levels) > > Ony one "self" reference, and any-through-iterator is very fast, as > it's native python code (probably implemented in C). And lazy > evaluating. > > It's challenging to understand your code. Maybe it's easier if you > explain in words-only how you want to implement inheritance. > > - > > My approach would be like this > > For a template called 'x', create a dictionary 'x' with maps the block > names for this template to a func with it's matching implementation > code. > Somehow, a method render_block(name) should be made available. So when > a blocks are nested, one block should be able to call > render_block(other_name). The render_block method should do a lookup > in the dictionary for a block with this name, and call it. > > Dynamic inheritance can easily be realized by replacing key/value > pairs in this dict by other implementations. Pass the original > implementation to the new implementation as an additional function > parameter. (As a curry.) > > I guess it's fast, and can be cached in memory. For each rendering, > only a copy of the required template
Re: Suggestion: a new "nature" field in Trac
On 01/04/11 08:04, Julien Phalip wrote: > Updating the 1800 open tickets is a big task, and to avoid duplicating > work I have set up a spreadsheet to coordinate our efforts: > https://spreadsheets.google.com/ccc?key=0AoGUYlz9V54IdFQtbEpyZTctQzhhQTlfMWdmWGt2a3c&hl=en > > If you'd like to volunteer, please put your name next to the page > numbers (18 pages x 100 tickets per page in total). Here's the list of > open tickets ordered by ids: > http://code.djangoproject.com/query?status=!closed&order=id Great, thanks for organising this. I've done one page **Volunteers, use the batch modify plugin at the bottom of the reports page** With this you can avoid sending out e-mails and changing the ticket modified timestamp, and you can do lots at once from the report page. But will need the 'triager' permissions to do this. **Ask one of the core devs for this.** I'm not sure what our exact process for deciding on 'triager' status is, but I've added Julien and Łukasz already, at least for this work. You may be removed again, but with all the great triaging work you've been doing I imagine you ought to stay there. Luke -- "If your parents never had children, the chances are you won't either." Luke Plant || http://lukeplant.me.uk/ -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.
Re: Suggestion: a new "nature" field in Trac
On 1 April 2011 12:03, Luke Plant wrote: > On 01/04/11 08:04, Julien Phalip wrote: > >> Updating the 1800 open tickets is a big task, and to avoid duplicating >> work I have set up a spreadsheet to coordinate our efforts: >> https://spreadsheets.google.com/ccc?key=0AoGUYlz9V54IdFQtbEpyZTctQzhhQTlfMWdmWGt2a3c&hl=en >> >> If you'd like to volunteer, please put your name next to the page >> numbers (18 pages x 100 tickets per page in total). Here's the list of >> open tickets ordered by ids: >> http://code.djangoproject.com/query?status=!closed&order=id > > > Great, thanks for organising this. I've done one page > > **Volunteers, use the batch modify plugin at the bottom of the reports > page** > > With this you can avoid sending out e-mails and changing the ticket > modified timestamp, and you can do lots at once from the report page. > > But will need the 'triager' permissions to do this. **Ask one of the > core devs for this.** > > I'm not sure what our exact process for deciding on 'triager' status is, > but I've added Julien and Łukasz already, at least for this work. You > may be removed again, but with all the great triaging work you've been > doing I imagine you ought to stay there. Thanks. I noticed the email after about 20 tickets, so sorry for all that emails. -- Łukasz Rekucki -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.
[GSoC] Revised form rendering
I suggest reading this proposal online: https://gist.github.com/898375 It's exactly the same as below but formated nicely. GSoC 2011 Proposal - Revised form rendering Hi my name is Gregor Müllegger. I'm a Computer Science student in Germany at the University of Augsburg currently in the fourth year of my studies. I first came to django shortly before 0.96 was released and a lots of awesomeness was introduced with the magic removal branch. I'm also doing some django freelancing work since 2008 to finance my studies and attended DjangoCon EU in 2011. This year I would like to apply to Google Summer of Code helping to improve Django with something that bugs me since quite a while: It's builtin ability to render a form straight away into HTML. Motiviation --- Why would I like to change the current behaviour? There are some reasons for this: 1. It's hard to change the default rendering. It is very easy to use e.g. django's builtin rendering of a ``ul`` based output like ``{{ myform.as_ul }}``. But what if you want to use your own *layout* like ``{{ myform.as_dl }}``? You can create a new method on your existing forms, but that involves writing python code (out of the designers hand) and might not be possible for thirdparty forms. 2. Maybe the ``as_ul`` rendering is fine for me. But maybe I want to skip that unnecessary field that the thirdparty form is providing. The solution would be to write down every single field in your template, reimplementing the ``ul`` layout:: {{ form.field.label_tag }}: {{ form.field }} {{ form.field.help_text }} {{ form.field.errors }} {# skipping field2 here #} {{ form.field3.label_tag }}: {{ form.field3 }} {{ form.field3.help_text }} {{ form.field3.errors }} ... We all love DRY, so this is not acceptable. 3. The designers I worked with are often interested on adding custom css class or an attribute to a form field. Most of the time this is really a pain to do if you don't have control over the python form code. Imagine a reusable app that ships with urls, views, forms. To add a single class you would need to: (a) overwrite the predefined url because you want (b) to specify an additional parameter for the view which is (c) your custom subclass of the thirdparty form:: class ChangedAttributeForm(ThirdPartyForm): field = forms.CharField(max_length=50, widget=TextInput(attrs={'class': 'fancy-text-input'})) btw: This also violates the DRY principle since you have to redefine the used field type, it's attributes (like ``max_length=50``) and the widget. I want to tell the designer how he can do this without my help in the template. Goals I want to accomplish -- After showing some of the problems that I see, are here the higher goals I want to achieve during the summer: 1. All of the rendering formats should be extracted from django's python source into a well defined structure of customizable templates. 2. Make it possible to reorder the use of form fields in the template without needing to write down the complete form. 3. Support for *chrome* that can be added dynamically in the template to a set of fields, changing some aspects of the form output. 4. Ensuring that the DRY principle is applyable to your form templates (in case of reordering/skipping some fields, like shown above) 5. Ensuring total backwards compatibility for ``{{ form.as_p }}`` etc. but deprecating it. 6. Converting the admin to use all of the new goodness. First, to make django eating its own dogfood. Second, to prove that the stuff I have developed is really a step forward and to show up big problems that occur in reallife scenarios, not taken into account in the blueprint. 7. Documenting all the newly introduced templatetags, the builtin chromes, how to write custom chrome, how to create your own form layout etc... Let's get a bit more detailed. How do I want to implement these goals? **1. No HTML in python source** I will push the formating of ``as_table``, ``as_ul`` and ``as_p`` into a specified template structure. A formating (e.g. ``ul``) will be called a layout and will live in the template directory ``forms/layouts//...``. This directory will contain a single file (e.g. for the table layout):: forms/layouts/table/row.html Creating a new layout is as simple as putting a new directory into your template path and adding one file. Why putting the file into a directory? The reason is because we can make the layout even more customizable. You are able in the ``row.html`` to ``{% include %}`` a ``errors.html`` and a ``helptext.html`` that can be overriden by the designer without completely rewriting the whole layout. Ok, but how will this look in the template where I use the form? For this we need a new template tag:: {% form myform using la
Re: [GSoC] Revised form rendering
Hi Gregor, As you've probably seen in past threads, this is an area where I'm quite motivated to see some improvement. I think you've got quite a strong proposal here in general, and you've clearly done your homework, so my comments below dive directly into the details: On 04/01/2011 11:57 AM, Gregor Müllegger wrote: > I suggest reading this proposal online: https://gist.github.com/898375 > It's exactly the same as below but formated nicely. > > > GSoC 2011 Proposal - Revised form rendering > > > Hi my name is Gregor Müllegger. I'm a Computer Science student in Germany at > the University of Augsburg currently in the fourth year of my studies. I first > came to django shortly before 0.96 was released and a lots of awesomeness was > introduced with the magic removal branch. > > I'm also doing some django freelancing work since 2008 to finance my studies > and attended DjangoCon EU in 2011. This year I would like to apply to > Google Summer of Code helping to improve Django with something that bugs me > since quite a while: It's builtin ability to render a form straight away into > HTML. > > Motiviation > --- > > Why would I like to change the current behaviour? There are some reasons for > this: > > 1. It's hard to change the default rendering. > >It is very easy to use e.g. django's builtin rendering of a ``ul`` based >output like ``{{ myform.as_ul }}``. But what if you want to use your own >*layout* like ``{{ myform.as_dl }}``? You can create a new method on your >existing forms, but that involves writing python code (out of the designers >hand) and might not be possible for thirdparty forms. > > 2. Maybe the ``as_ul`` rendering is fine for me. But maybe I want to skip that >unnecessary field that the thirdparty form is providing. The solution would >be to write down every single field in your template, reimplementing the >``ul`` layout:: > > {{ form.field.label_tag }}: {{ form.field }} > {{ form.field.help_text }} {{ form.field.errors }} > {# skipping field2 here #} > {{ form.field3.label_tag }}: {{ form.field3 }} > {{ form.field3.help_text }} {{ form.field3.errors }} > ... > >We all love DRY, so this is not acceptable. > > 3. The designers I worked with are often interested on adding custom css class >or an attribute to a form field. Most of the time this is really a pain to >do if you don't have control over the python form code. Imagine a reusable >app that ships with urls, views, forms. To add a single class you would >need to: (a) overwrite the predefined url because you want (b) to specify >an additional parameter for the view which is (c) your custom subclass of >the thirdparty form:: > >class ChangedAttributeForm(ThirdPartyForm): >field = forms.CharField(max_length=50, >widget=TextInput(attrs={'class': 'fancy-text-input'})) > >btw: This also violates the DRY principle since you have to redefine the >used field type, it's attributes (like ``max_length=50``) and the widget. > >I want to tell the designer how he can do this without my help in the >template. I agree with your Motivations section - in particular this final line, which sums up the core motivation as I see it. > Goals I want to accomplish > -- > > After showing some of the problems that I see, are here the higher goals I > want to achieve during the summer: > > 1. All of the rendering formats should be extracted from django's python > source >into a well defined structure of customizable templates. > 2. Make it possible to reorder the use of form fields in the template without >needing to write down the complete form. > 3. Support for *chrome* that can be added dynamically in the template to a set >of fields, changing some aspects of the form output. > 4. Ensuring that the DRY principle is applyable to your form templates (in >case of reordering/skipping some fields, like shown above) > 5. Ensuring total backwards compatibility for ``{{ form.as_p }}`` etc. but >deprecating it. > 6. Converting the admin to use all of the new goodness. First, to make django >eating its own dogfood. Second, to prove that the stuff I have developed is >really a step forward and to show up big problems that occur in reallife >scenarios, not taken into account in the blueprint. > 7. Documenting all the newly introduced templatetags, the builtin chromes, >how to write custom chrome, how to create your own form layout etc... > > Let's get a bit more detailed. How do I want to implement these goals? > > **1. No HTML in python source** > > I will push the formating of ``as_table``, ``as_ul`` and ``as_p`` into a > specified template structure. A formating (e.g. ``ul``) will be called a > layout and will live in the template directory ``forms/layouts//...``. > This
Re: Revised form rendering
Hi Carl and Gregor, On 2 апр, 01:17, Carl Meyer wrote: > > > 3. The designers I worked with are often interested on adding custom css > > class > > or an attribute to a form field. Most of the time this is really a pain > > to > > do if you don't have control over the python form code. Imagine a > > reusable > > app that ships with urls, views, forms. To add a single class you would > > need to: (a) overwrite the predefined url because you want (b) to specify > > an additional parameter for the view which is (c) your custom subclass of > > the thirdparty form:: > > > class ChangedAttributeForm(ThirdPartyForm): > > field = forms.CharField(max_length=50, > > widget=TextInput(attrs={'class': 'fancy-text-input'})) > > > btw: This also violates the DRY principle since you have to redefine the > > used field type, it's attributes (like ``max_length=50``) and the widget. > > > I want to tell the designer how he can do this without my help in the > > template. > > I agree with your Motivations section - in particular this final line, > which sums up the core motivation as I see it. > This goal can be achieved without changing django, see https://bitbucket.org/kmike/django-widget-tweaks Each widget is instantiated by field in 'as_widget' method now, and the field passes 'attrs' argument to widget with extra attributes. The idea behind django-widget-tweaks is simple: it provides template filters that take field instance and wrap its 'as_widget' bound method so it receives extra attributes (and pass these extra attributes to widget). This way widget attributes (including input types and css classes) can be altered in templates without touching python, e.g.: {{ myform.field|add_class:"fancy-text-input" }} {{ search_form.query|attr:"type:search" }} Implementation: https://bitbucket.org/kmike/django-widget-tweaks/src/0e9bac3c71bd/widget_tweaks/templatetags/widget_tweaks.py -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.
Re: Revised form rendering
Hi Mikhail, On 04/01/2011 05:09 PM, Mikhail Korobov wrote: > Hi Carl and Gregor, > > On 2 апр, 01:17, Carl Meyer wrote: >> >>> 3. The designers I worked with are often interested on adding custom css >>> class >>>or an attribute to a form field. Most of the time this is really a pain >>> to >>>do if you don't have control over the python form code. Imagine a >>> reusable >>>app that ships with urls, views, forms. To add a single class you would >>>need to: (a) overwrite the predefined url because you want (b) to specify >>>an additional parameter for the view which is (c) your custom subclass of >>>the thirdparty form:: >> >>>class ChangedAttributeForm(ThirdPartyForm): >>>field = forms.CharField(max_length=50, >>>widget=TextInput(attrs={'class': 'fancy-text-input'})) >> >>>btw: This also violates the DRY principle since you have to redefine the >>>used field type, it's attributes (like ``max_length=50``) and the widget. >> >>>I want to tell the designer how he can do this without my help in the >>>template. >> >> I agree with your Motivations section - in particular this final line, >> which sums up the core motivation as I see it. >> > > This goal can be achieved without changing django, see > https://bitbucket.org/kmike/django-widget-tweaks > > Each widget is instantiated by field in 'as_widget' method now, and > the field passes 'attrs' argument to widget with extra attributes. > > The idea behind django-widget-tweaks is simple: it provides template > filters that take field instance and wrap its 'as_widget' bound method > so it receives extra attributes (and pass these extra attributes to > widget). This way widget attributes (including input types and css > classes) can be altered in templates without touching python, e.g.: > > {{ myform.field|add_class:"fancy-text-input" }} > {{ search_form.query|attr:"type:search" }} > > Implementation: > https://bitbucket.org/kmike/django-widget-tweaks/src/0e9bac3c71bd/widget_tweaks/templatetags/widget_tweaks.py That's quite a neat app - I have some similar template filters implemented in some of my own projects. It doesn't cover the full range of Gregor's proposal -- but I actually think most of Gregor's proposal would be possible to implement outside Django. Perhaps we should consider whether it would be preferable to start it off that way, or focus the proposal more on where Django itself really needs to change. Personally, I think HTML generation in Python code is a bug, and I'd like to see it eradicated from Django, so I'm pretty open to seeing this stuff make it to trunk. Carl -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.
Re: Proposal: switch to HTML5 for bundled templates
FYI, I've just stumbled on ticket #7452 and this thread: http://groups.google.com/group/django-developers/browse_thread/thread/f346813ab89d4155/ One interesting idea that was suggested is to introduce a setting for controlling the type of HTML. -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.
[GSoC] Composite fields
After this thread: https://groups.google.com/d/topic/django-developers/Y0aAb792cTw/discussion I decided to modify my proposal a bit. (This, however, still doesn't even try to resemble a final proposal, I just need to get a few more things straight.) I propose to implement a CompositeField with the following properties: - will be represented as a namedtuple containing the values of the actual fields it encapsulates - will support retrieval and assignment (assignment sets the values of encapsulated fields) - will be possible to use in __exact QuerySet lookups - support for Field.db_index and Field.unique creating the appropriate indexes and constraints in the database - support for Field.primary_key A few issues come to mind however. - A QuerySet filter for a CompositeField would have the semantics of a Q object (a conjunction of equalities). AFAICS, you can't create Q objects and add them to the tree within get_prep_lookup or get_db_prep_lookup. The only solution I can think of at the moment is having a special case recognized in the constructor of Q but that is ugly. Or maybe I'm wrong and the whole where node should be a single tuple comparison? Is this supported by database backends? Postgres and MySQL seem to work all right, SQLite seems to choke but maybe it's just me doing something wrong. How should it behave when it comes to aggregation? - Would it make sense to support other kinds of lookups? At quick look at the list at http://docs.djangoproject.com/en/dev/ref/models/querysets/#field-lookups the only thing I see possible is __in but that might be overly complicated if we go down the Q-object way. - CompositeField.unique would make the unique_together Meta option unnecessary - Composite fields would be encoded using comma as the delimiter for use in admin URLs as described in the previous thread - The same encoding could be used as a value in ModelChoiceFields to select related objects - Related fields would have to recognize CompositeField references and automatically create the appropriate fields in the referencing model. Naming proposed by Andrew is "fkname_remotecolname", there haven't been any objections to that. The QuerySet issue is the only one I couldn't figure out how to solve for now. Anyway, I'd like to know which one of the three approaches proposed so far would be the one to choose. I, personally, like the CompositeField idea the most but I'd be also willing to implement the CompositeIndex or just plain Meta attribute if the majority chooses so. There have been voices for and against each one of them but no clear champion. Michal Petrucha signature.asc Description: Digital signature