<div dir="ltr"><div class="markdown-here-wrapper" style=""><p style="margin:1.2em 0px!important">On Tue, Feb 21, 2017 at 6:51 PM, G Jones <<a href="mailto:glenn.caltech@gmail.com" target="_blank">glenn.caltech@gmail.com</a>> wrote:</p>
<p style="margin:1.2em 0px!important"></p><div class="markdown-here-exclude"><p></p><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Hi Matthias,<div>Thanks for the reply; I think that makes sense.</div><div>It might also answer my next question too: Suppose I have another application PipelineMonitor and I want to connect PipelineApp to PipelineMonitor via a common socket. The question is how to share that common socket information (i.e. port number) between the applications using the config file. It sounds like the idea would be to do something like</div><div>common_configuration.py:</div><div><font face="monospace, monospace">class GlobalConfiguration(<wbr>configurable):</font></div><div><font face="monospace, monospace">    common_port_number = Int(55555).tag(config=True)</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">pipeline.py:</font></div><div><font face="monospace, monospace">from common_configuration import GlobalConfiguration</font></div><div><font face="monospace, monospace">class PipelineConfiguration(<wbr>GlobalConfiguration):</font></div><div><font face="monospace, monospace">    common_dir = Unicode('').tag(config=True)</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">pipeline_monitor.py:</font></div><div><span style="font-family:monospace,monospace">from common_configuration import GlobalConfiguration</span><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">class PipelineMonitorConfiguration(<wbr>GlobalCOnfiguration):</font></div><div><font face="monospace, monospace">    some_param = Int(34).tag(config=True)</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="arial, helvetica, sans-serif">and then inherit PipelineConfiguration and PipelineMonitorConfiguration in the respective application classes.</font></div></div></blockquote><p></p></div><p style="margin:1.2em 0px!important"></p>
<p style="margin:1.2em 0px!important">Yup, this is a patten that has shown up in a few cases, and works pretty well. </p>
<p style="margin:1.2em 0px!important"></p><div class="markdown-here-exclude"><p></p><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><font face="arial, helvetica, sans-serif"><br></font></div><div><font face="arial, helvetica, sans-serif">Then I should be able to have a global_config.py configuration file with the common_port_number, and then use load_subconfig(global_config.<wbr>py) in each of the application specific config files.</font></div></div></blockquote><p></p></div><p style="margin:1.2em 0px!important"></p>
<p style="margin:1.2em 0px!important">If your different Applications are relatively small and closely related, you can probably get away with using a single configuration file for your whole application. Set <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;display:inline">config_file_name</code> on all your applications to the same value (e.g. <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;display:inline">'myapp_config'</code>.</p>
<p style="margin:1.2em 0px!important">-MinRK</p>
<p style="margin:1.2em 0px!important"></p><div class="markdown-here-exclude"><p></p><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><font face="arial, helvetica, sans-serif"><br></font></div><div><font face="arial, helvetica, sans-serif">Does that sound like the right idea?</font></div><div><font face="arial, helvetica, sans-serif"><br></font></div><div><font face="arial, helvetica, sans-serif">Thank you again,</font></div><div><font face="arial, helvetica, sans-serif">Glenn</font></div><div><font face="monospace, monospace"><br></font></div></div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Feb 21, 2017 at 11:39 AM, Matthias Bussonnier <span dir="ltr"><<a href="mailto:bussonniermatthias@gmail.com" target="_blank">bussonniermatthias@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi Glenn,<br>
<br>
I think the idea is to make a Common dummy subclass:<br>
<br>
class MyConfigurable(configurable):<br>
    # class can be empty, or you can move the<br>
    # common_dir = Unicode('').tag(config=True)<br>
    # in it, up to you.<br>
    pass<br>
<br>
<br>
Then just inherit from it:<br>
<br>
  class Writer(MyConfigurable):<br>
<span>      writer_trait = Int(4).tag(config=True)<br>
      common_dir = Unicode('').tag(config=True)<br>
<br>
</span>  class Acquire(MyConfigurable):<br>
<span>      acquire_trait = Int(55).tag(config=True)<br>
      common_dir = Unicode('').tag(config=True)<br>
<br>
</span>  class Pipeline(MyConfigurable):<br>
<span>      common_dir = Unicode('').tag(config=True)<br>
      def initialize(self):<br>
          self.writer = Writer()<br>
          self.acquire = Acquire()<br>
<br>
  class PipelineApp(Application):<br>
      classes = [Pipeline, Acquire, Writer]<br>
      def initialize(self,argv=None):<br>
          self.pipeline = Pipeline(config=self.config)<br>
          self.pipeline.initialize()<br>
><br>
><br>
> The idea is that the common_dir traits should be all the same. The code works as<br>
> written, but results in three possible lines in the settings file. Since the<br>
> settings file is just python, it's not too bad to do<br>
><br>
> c.Pipeline.common_dir = '/output'<br>
> c.Acquire.common_dir = c.Pipeline.common_dir<br>
> c.Writer.common_dir = c.Pipeline.common_dir<br>
<br>
<br>
</span>Now you just need to configure MyConfigurable for it to affect all classes.<br>
<br>
    c.MyConfigurable.common_dir = '/output'<br>
<br>
You can target one class in particular with what you do above.<br>
<br>
If you add parent=self<br>
<br>
    self.pipeline = Pipeline(config=self.config, parent=self)<br>
<br>
Then you can narrow down configuration by using parent/child selector;<br>
<br>
    c.PipelineApp.MyConfigurable.c<wbr>ommon_dir = '/output'<br>
<br>
It will target only MyConfigurable where `parent=self` is passed and<br>
parent is an<br>
instance of PipelineApp. (This is a rare case use in nbconvert to allow<br>
configuration of each exporter independently)<br>
<br>
Does that answer your questions ?<br>
<br>
--<br>
<br>
Matthias<br>
<div><div class="m_247533649217288709h5"><br>
On Tue, Feb 21, 2017 at 7:01 AM, G Jones <<a href="mailto:glenn.caltech@gmail.com" target="_blank">glenn.caltech@gmail.com</a>> wrote:<br>
> Hello,<br>
><br>
> I am working on using traitlets.config in my project. The application has<br>
> this structure:<br>
><br>
> class Writer(Configurable):<br>
>     writer_trait = Int(4).tag(config=True)<br>
>     common_dir = Unicode('').tag(config=True)<br>
><br>
> class Acquire(Configurable):<br>
>     acquire_trait = Int(55).tag(config=True)<br>
>     common_dir = Unicode('').tag(config=True)<br>
><br>
> class Pipeline(Configurable):<br>
>     common_dir = Unicode('').tag(config=True)<br>
>     def initialize(self):<br>
>         self.writer = Writer()<br>
>         self.acquire = Acquire()<br>
><br>
> class PipelineApp(Application):<br>
>     classes = [Pipeline, Acquire, Writer]<br>
>     def initialize(self,argv=None):<br>
>         self.pipeline = Pipeline(config=self.config)<br>
>         self.pipeline.initialize()<br>
><br>
><br>
> The idea is that the common_dir traits should be all the same. The code<br>
> works as written, but results in three possible lines in the settings file.<br>
> Since the settings file is just python, it's not too bad to do<br>
> c.Pipeline.common_dir = '/output'<br>
> c.Acquire.common_dir = c.Pipeline.common_dir<br>
> c.Writer.common_dir = c.Pipeline.common_dir<br>
><br>
> But it seems like there should be a better way.<br>
><br>
> I see that I could pass in a parent and access it that way:<br>
> self.writer = Writer(parent=self)<br>
><br>
> and then in writer:<br>
> self.parent.common_dir<br>
><br>
> But then if I want to use Writer on its own, I need to do a check if<br>
> self.parent.... or something.<br>
><br>
> Is there a better way? I hope the intent is clear, please let me know if<br>
> not.<br>
><br>
> Thanks,<br>
> Glenn<br>
><br>
</div></div>> ______________________________<wbr>_________________<br>
> IPython-dev mailing list<br>
> <a href="mailto:IPython-dev@scipy.org" target="_blank">IPython-dev@scipy.org</a><br>
> <a href="https://mail.scipy.org/mailman/listinfo/ipython-dev" rel="noreferrer" target="_blank">https://mail.scipy.org/mailman<wbr>/listinfo/ipython-dev</a><br>
><br>
______________________________<wbr>_________________<br>
IPython-dev mailing list<br>
<a href="mailto:IPython-dev@scipy.org" target="_blank">IPython-dev@scipy.org</a><br>
<a href="https://mail.scipy.org/mailman/listinfo/ipython-dev" rel="noreferrer" target="_blank">https://mail.scipy.org/mailman<wbr>/listinfo/ipython-dev</a><br>
</blockquote></div><br></div>
</div></div><br>______________________________<wbr>_________________<br>
IPython-dev mailing list<br>
<a href="mailto:IPython-dev@scipy.org">IPython-dev@scipy.org</a><br>
<a href="https://mail.scipy.org/mailman/listinfo/ipython-dev" rel="noreferrer" target="_blank">https://mail.scipy.org/<wbr>mailman/listinfo/ipython-dev</a><br>
<br></blockquote><p></p></div><p style="margin:1.2em 0px!important"></p>
<div title="MDH:PGJyPjxkaXYgY2xhc3M9ImdtYWlsX2V4dHJhIj48YnI+PGRpdiBjbGFzcz0iZ21haWxfcXVvdGUi
Pk9uIFR1ZSwgRmViIDIxLCAyMDE3IGF0IDY6NTEgUE0sIEcgSm9uZXMgPHNwYW4gZGlyPSJsdHIi
PiZsdDs8YSBocmVmPSJtYWlsdG86Z2xlbm4uY2FsdGVjaEBnbWFpbC5jb20iIHRhcmdldD0iX2Js
YW5rIj5nbGVubi5jYWx0ZWNoQGdtYWlsLmNvbTwvYT4mZ3Q7PC9zcGFuPiB3cm90ZTo8YnI+PGJs
b2NrcXVvdGUgY2xhc3M9ImdtYWlsX3F1b3RlIiBzdHlsZT0ibWFyZ2luOjAgMCAwIC44ZXg7Ym9y
ZGVyLWxlZnQ6MXB4ICNjY2Mgc29saWQ7cGFkZGluZy1sZWZ0OjFleCI+PGRpdiBkaXI9Imx0ciI+
SGkgTWF0dGhpYXMsPGRpdj5UaGFua3MgZm9yIHRoZSByZXBseTsgSSB0aGluayB0aGF0IG1ha2Vz
IHNlbnNlLjwvZGl2PjxkaXY+SXQgbWlnaHQgYWxzbyBhbnN3ZXIgbXkgbmV4dCBxdWVzdGlvbiB0
b286IFN1cHBvc2UgSSBoYXZlIGFub3RoZXIgYXBwbGljYXRpb24gUGlwZWxpbmVNb25pdG9yIGFu
ZCBJIHdhbnQgdG8gY29ubmVjdCBQaXBlbGluZUFwcCB0byBQaXBlbGluZU1vbml0b3IgdmlhIGEg
Y29tbW9uIHNvY2tldC4gVGhlIHF1ZXN0aW9uIGlzIGhvdyB0byBzaGFyZSB0aGF0IGNvbW1vbiBz
b2NrZXQgaW5mb3JtYXRpb24gKGkuZS4gcG9ydCBudW1iZXIpIGJldHdlZW4gdGhlIGFwcGxpY2F0
aW9ucyB1c2luZyB0aGUgY29uZmlnIGZpbGUuIEl0IHNvdW5kcyBsaWtlIHRoZSBpZGVhIHdvdWxk
IGJlIHRvIGRvIHNvbWV0aGluZyBsaWtlPC9kaXY+PGRpdj5jb21tb25fY29uZmlndXJhdGlvbi5w
eTo8L2Rpdj48ZGl2Pjxmb250IGZhY2U9Im1vbm9zcGFjZSwgbW9ub3NwYWNlIj5jbGFzcyBHbG9i
YWxDb25maWd1cmF0aW9uKDx3YnI+Y29uZmlndXJhYmxlKTo8L2ZvbnQ+PC9kaXY+PGRpdj48Zm9u
dCBmYWNlPSJtb25vc3BhY2UsIG1vbm9zcGFjZSI+Jm5ic3A7ICZuYnNwOyBjb21tb25fcG9ydF9u
dW1iZXIgPSBJbnQoNTU1NTUpLnRhZyhjb25maWc9VHJ1ZSk8L2ZvbnQ+PC9kaXY+PGRpdj48Zm9u
dCBmYWNlPSJtb25vc3BhY2UsIG1vbm9zcGFjZSI+PGJyPjwvZm9udD48L2Rpdj48ZGl2Pjxmb250
IGZhY2U9Im1vbm9zcGFjZSwgbW9ub3NwYWNlIj5waXBlbGluZS5weTo8L2ZvbnQ+PC9kaXY+PGRp
dj48Zm9udCBmYWNlPSJtb25vc3BhY2UsIG1vbm9zcGFjZSI+ZnJvbSBjb21tb25fY29uZmlndXJh
dGlvbiBpbXBvcnQgR2xvYmFsQ29uZmlndXJhdGlvbjwvZm9udD48L2Rpdj48ZGl2Pjxmb250IGZh
Y2U9Im1vbm9zcGFjZSwgbW9ub3NwYWNlIj5jbGFzcyBQaXBlbGluZUNvbmZpZ3VyYXRpb24oPHdi
cj5HbG9iYWxDb25maWd1cmF0aW9uKTo8L2ZvbnQ+PC9kaXY+PGRpdj48Zm9udCBmYWNlPSJtb25v
c3BhY2UsIG1vbm9zcGFjZSI+Jm5ic3A7ICZuYnNwOyBjb21tb25fZGlyID0gVW5pY29kZSgnJyku
dGFnKGNvbmZpZz1UcnVlKTwvZm9udD48L2Rpdj48ZGl2Pjxmb250IGZhY2U9Im1vbm9zcGFjZSwg
bW9ub3NwYWNlIj48YnI+PC9mb250PjwvZGl2PjxkaXY+PGZvbnQgZmFjZT0ibW9ub3NwYWNlLCBt
b25vc3BhY2UiPnBpcGVsaW5lX21vbml0b3IucHk6PC9mb250PjwvZGl2PjxkaXY+PHNwYW4gc3R5
bGU9ImZvbnQtZmFtaWx5Om1vbm9zcGFjZSxtb25vc3BhY2UiPmZyb20gY29tbW9uX2NvbmZpZ3Vy
YXRpb24gaW1wb3J0IEdsb2JhbENvbmZpZ3VyYXRpb248L3NwYW4+PGZvbnQgZmFjZT0ibW9ub3Nw
YWNlLCBtb25vc3BhY2UiPjxicj48L2ZvbnQ+PC9kaXY+PGRpdj48Zm9udCBmYWNlPSJtb25vc3Bh
Y2UsIG1vbm9zcGFjZSI+Y2xhc3MgUGlwZWxpbmVNb25pdG9yQ29uZmlndXJhdGlvbig8d2JyPkds
b2JhbENPbmZpZ3VyYXRpb24pOjwvZm9udD48L2Rpdj48ZGl2Pjxmb250IGZhY2U9Im1vbm9zcGFj
ZSwgbW9ub3NwYWNlIj4mbmJzcDsgJm5ic3A7IHNvbWVfcGFyYW0gPSBJbnQoMzQpLnRhZyhjb25m
aWc9VHJ1ZSk8L2ZvbnQ+PC9kaXY+PGRpdj48Zm9udCBmYWNlPSJtb25vc3BhY2UsIG1vbm9zcGFj
ZSI+PGJyPjwvZm9udD48L2Rpdj48ZGl2Pjxmb250IGZhY2U9ImFyaWFsLCBoZWx2ZXRpY2EsIHNh
bnMtc2VyaWYiPmFuZCB0aGVuIGluaGVyaXQgUGlwZWxpbmVDb25maWd1cmF0aW9uIGFuZCBQaXBl
bGluZU1vbml0b3JDb25maWd1cmF0aW9uIGluIHRoZSByZXNwZWN0aXZlIGFwcGxpY2F0aW9uIGNs
YXNzZXMuPC9mb250PjwvZGl2PjwvZGl2PjwvYmxvY2txdW90ZT48ZGl2Pjxicj48L2Rpdj48ZGl2
Pll1cCwgdGhpcyBpcyBhIHBhdHRlbiB0aGF0IGhhcyBzaG93biB1cCBpbiBhIGZldyBjYXNlcywg
YW5kIHdvcmtzIHByZXR0eSB3ZWxsLiZuYnNwOzwvZGl2PjxibG9ja3F1b3RlIGNsYXNzPSJnbWFp
bF9xdW90ZSIgc3R5bGU9Im1hcmdpbjowIDAgMCAuOGV4O2JvcmRlci1sZWZ0OjFweCAjY2NjIHNv
bGlkO3BhZGRpbmctbGVmdDoxZXgiPjxkaXYgZGlyPSJsdHIiPjxkaXY+PGZvbnQgZmFjZT0iYXJp
YWwsIGhlbHZldGljYSwgc2Fucy1zZXJpZiI+PGJyPjwvZm9udD48L2Rpdj48ZGl2Pjxmb250IGZh
Y2U9ImFyaWFsLCBoZWx2ZXRpY2EsIHNhbnMtc2VyaWYiPlRoZW4gSSBzaG91bGQgYmUgYWJsZSB0
byBoYXZlIGEgZ2xvYmFsX2NvbmZpZy5weSBjb25maWd1cmF0aW9uIGZpbGUgd2l0aCB0aGUgY29t
bW9uX3BvcnRfbnVtYmVyLCBhbmQgdGhlbiB1c2UgbG9hZF9zdWJjb25maWcoZ2xvYmFsX2NvbmZp
Zy48d2JyPnB5KSBpbiBlYWNoIG9mIHRoZSBhcHBsaWNhdGlvbiBzcGVjaWZpYyBjb25maWcgZmls
ZXMuPC9mb250PjwvZGl2PjwvZGl2PjwvYmxvY2txdW90ZT48ZGl2Pjxicj48L2Rpdj48ZGl2Pklm
IHlvdXIgZGlmZmVyZW50IEFwcGxpY2F0aW9ucyBhcmUgcmVsYXRpdmVseSBzbWFsbCBhbmQgY2xv
c2VseSByZWxhdGVkLCB5b3UgY2FuIHByb2JhYmx5IGdldCBhd2F5IHdpdGggdXNpbmcgYSBzaW5n
bGUgY29uZmlndXJhdGlvbiBmaWxlIGZvciB5b3VyIHdob2xlIGFwcGxpY2F0aW9uLiBTZXQgYGNv
bmZpZ19maWxlX25hbWVgIG9uIGFsbCB5b3VyIGFwcGxpY2F0aW9ucyB0byB0aGUgc2FtZSB2YWx1
ZSAoZS5nLiBgJ215YXBwX2NvbmZpZydgLjwvZGl2PjxkaXY+PGJyPjwvZGl2PjxkaXY+LU1pblJL
PC9kaXY+PGRpdj4mbmJzcDs8L2Rpdj48YmxvY2txdW90ZSBjbGFzcz0iZ21haWxfcXVvdGUiIHN0
eWxlPSJtYXJnaW46MCAwIDAgLjhleDtib3JkZXItbGVmdDoxcHggI2NjYyBzb2xpZDtwYWRkaW5n
LWxlZnQ6MWV4Ij48ZGl2IGRpcj0ibHRyIj48ZGl2Pjxmb250IGZhY2U9ImFyaWFsLCBoZWx2ZXRp
Y2EsIHNhbnMtc2VyaWYiPjxicj48L2ZvbnQ+PC9kaXY+PGRpdj48Zm9udCBmYWNlPSJhcmlhbCwg
aGVsdmV0aWNhLCBzYW5zLXNlcmlmIj5Eb2VzIHRoYXQgc291bmQgbGlrZSB0aGUgcmlnaHQgaWRl
YT88L2ZvbnQ+PC9kaXY+PGRpdj48Zm9udCBmYWNlPSJhcmlhbCwgaGVsdmV0aWNhLCBzYW5zLXNl
cmlmIj48YnI+PC9mb250PjwvZGl2PjxkaXY+PGZvbnQgZmFjZT0iYXJpYWwsIGhlbHZldGljYSwg
c2Fucy1zZXJpZiI+VGhhbmsgeW91IGFnYWluLDwvZm9udD48L2Rpdj48ZGl2Pjxmb250IGZhY2U9
ImFyaWFsLCBoZWx2ZXRpY2EsIHNhbnMtc2VyaWYiPkdsZW5uPC9mb250PjwvZGl2PjxkaXY+PGZv
bnQgZmFjZT0ibW9ub3NwYWNlLCBtb25vc3BhY2UiPjxicj48L2ZvbnQ+PC9kaXY+PC9kaXY+PGRp
diBjbGFzcz0iSE9FblpiIj48ZGl2IGNsYXNzPSJoNSI+PGRpdiBjbGFzcz0iZ21haWxfZXh0cmEi
Pjxicj48ZGl2IGNsYXNzPSJnbWFpbF9xdW90ZSI+T24gVHVlLCBGZWIgMjEsIDIwMTcgYXQgMTE6
MzkgQU0sIE1hdHRoaWFzIEJ1c3Nvbm5pZXIgPHNwYW4gZGlyPSJsdHIiPiZsdDs8YSBocmVmPSJt
YWlsdG86YnVzc29ubmllcm1hdHRoaWFzQGdtYWlsLmNvbSIgdGFyZ2V0PSJfYmxhbmsiPmJ1c3Nv
bm5pZXJtYXR0aGlhc0BnbWFpbC5jb208L2E+Jmd0Ozwvc3Bhbj4gd3JvdGU6PGJyPjxibG9ja3F1
b3RlIGNsYXNzPSJnbWFpbF9xdW90ZSIgc3R5bGU9Im1hcmdpbjowIDAgMCAuOGV4O2JvcmRlci1s
ZWZ0OjFweCAjY2NjIHNvbGlkO3BhZGRpbmctbGVmdDoxZXgiPkhpIEdsZW5uLDxicj4KPGJyPgpJ
IHRoaW5rIHRoZSBpZGVhIGlzIHRvIG1ha2UgYSBDb21tb24gZHVtbXkgc3ViY2xhc3M6PGJyPgo8
YnI+CmNsYXNzIE15Q29uZmlndXJhYmxlKGNvbmZpZ3VyYWJsZSk6PGJyPgombmJzcDsgJm5ic3A7
ICMgY2xhc3MgY2FuIGJlIGVtcHR5LCBvciB5b3UgY2FuIG1vdmUgdGhlPGJyPgombmJzcDsgJm5i
c3A7ICMgY29tbW9uX2RpciA9IFVuaWNvZGUoJycpLnRhZyhjb25maWc9VHJ1ZSk8YnI+CiZuYnNw
OyAmbmJzcDsgIyBpbiBpdCwgdXAgdG8geW91Ljxicj4KJm5ic3A7ICZuYnNwOyBwYXNzPGJyPgo8
YnI+Cjxicj4KVGhlbiBqdXN0IGluaGVyaXQgZnJvbSBpdDo8YnI+Cjxicj4KJm5ic3A7IGNsYXNz
IFdyaXRlcihNeUNvbmZpZ3VyYWJsZSk6PGJyPgo8c3Bhbj4mbmJzcDsgJm5ic3A7ICZuYnNwOyB3
cml0ZXJfdHJhaXQgPSBJbnQoNCkudGFnKGNvbmZpZz1UcnVlKTxicj4KJm5ic3A7ICZuYnNwOyAm
bmJzcDsgY29tbW9uX2RpciA9IFVuaWNvZGUoJycpLnRhZyhjb25maWc9VHJ1ZSk8YnI+Cjxicj4K
PC9zcGFuPiZuYnNwOyBjbGFzcyBBY3F1aXJlKE15Q29uZmlndXJhYmxlKTo8YnI+CjxzcGFuPiZu
YnNwOyAmbmJzcDsgJm5ic3A7IGFjcXVpcmVfdHJhaXQgPSBJbnQoNTUpLnRhZyhjb25maWc9VHJ1
ZSk8YnI+CiZuYnNwOyAmbmJzcDsgJm5ic3A7IGNvbW1vbl9kaXIgPSBVbmljb2RlKCcnKS50YWco
Y29uZmlnPVRydWUpPGJyPgo8YnI+Cjwvc3Bhbj4mbmJzcDsgY2xhc3MgUGlwZWxpbmUoTXlDb25m
aWd1cmFibGUpOjxicj4KPHNwYW4+Jm5ic3A7ICZuYnNwOyAmbmJzcDsgY29tbW9uX2RpciA9IFVu
aWNvZGUoJycpLnRhZyhjb25maWc9VHJ1ZSk8YnI+CiZuYnNwOyAmbmJzcDsgJm5ic3A7IGRlZiBp
bml0aWFsaXplKHNlbGYpOjxicj4KJm5ic3A7ICZuYnNwOyAmbmJzcDsgJm5ic3A7ICZuYnNwOyBz
ZWxmLndyaXRlciA9IFdyaXRlcigpPGJyPgombmJzcDsgJm5ic3A7ICZuYnNwOyAmbmJzcDsgJm5i
c3A7IHNlbGYuYWNxdWlyZSA9IEFjcXVpcmUoKTxicj4KPGJyPgombmJzcDsgY2xhc3MgUGlwZWxp
bmVBcHAoQXBwbGljYXRpb24pOjxicj4KJm5ic3A7ICZuYnNwOyAmbmJzcDsgY2xhc3NlcyA9IFtQ
aXBlbGluZSwgQWNxdWlyZSwgV3JpdGVyXTxicj4KJm5ic3A7ICZuYnNwOyAmbmJzcDsgZGVmIGlu
aXRpYWxpemUoc2VsZixhcmd2PU5vbmUpOjxicj4KJm5ic3A7ICZuYnNwOyAmbmJzcDsgJm5ic3A7
ICZuYnNwOyBzZWxmLnBpcGVsaW5lID0gUGlwZWxpbmUoY29uZmlnPXNlbGYuY29uZmlnKTxicj4K
Jm5ic3A7ICZuYnNwOyAmbmJzcDsgJm5ic3A7ICZuYnNwOyBzZWxmLnBpcGVsaW5lLmluaXRpYWxp
emUoKTxicj4KJmd0Ozxicj4KJmd0Ozxicj4KJmd0OyBUaGUgaWRlYSBpcyB0aGF0IHRoZSBjb21t
b25fZGlyIHRyYWl0cyBzaG91bGQgYmUgYWxsIHRoZSBzYW1lLiBUaGUgY29kZSB3b3JrcyBhczxi
cj4KJmd0OyB3cml0dGVuLCBidXQgcmVzdWx0cyBpbiB0aHJlZSBwb3NzaWJsZSBsaW5lcyBpbiB0
aGUgc2V0dGluZ3MgZmlsZS4gU2luY2UgdGhlPGJyPgomZ3Q7IHNldHRpbmdzIGZpbGUgaXMganVz
dCBweXRob24sIGl0J3Mgbm90IHRvbyBiYWQgdG8gZG88YnI+CiZndDs8YnI+CiZndDsgYy5QaXBl
bGluZS5jb21tb25fZGlyID0gJy9vdXRwdXQnPGJyPgomZ3Q7IGMuQWNxdWlyZS5jb21tb25fZGly
ID0gYy5QaXBlbGluZS5jb21tb25fZGlyPGJyPgomZ3Q7IGMuV3JpdGVyLmNvbW1vbl9kaXIgPSBj
LlBpcGVsaW5lLmNvbW1vbl9kaXI8YnI+Cjxicj4KPGJyPgo8L3NwYW4+Tm93IHlvdSBqdXN0IG5l
ZWQgdG8gY29uZmlndXJlIE15Q29uZmlndXJhYmxlIGZvciBpdCB0byBhZmZlY3QgYWxsIGNsYXNz
ZXMuPGJyPgo8YnI+CiZuYnNwOyAmbmJzcDsgYy5NeUNvbmZpZ3VyYWJsZS5jb21tb25fZGlyID0g
Jy9vdXRwdXQnPGJyPgo8YnI+CllvdSBjYW4gdGFyZ2V0IG9uZSBjbGFzcyBpbiBwYXJ0aWN1bGFy
IHdpdGggd2hhdCB5b3UgZG8gYWJvdmUuPGJyPgo8YnI+CklmIHlvdSBhZGQgcGFyZW50PXNlbGY8
YnI+Cjxicj4KJm5ic3A7ICZuYnNwOyBzZWxmLnBpcGVsaW5lID0gUGlwZWxpbmUoY29uZmlnPXNl
bGYuY29uZmlnLCBwYXJlbnQ9c2VsZik8YnI+Cjxicj4KVGhlbiB5b3UgY2FuIG5hcnJvdyBkb3du
IGNvbmZpZ3VyYXRpb24gYnkgdXNpbmcgcGFyZW50L2NoaWxkIHNlbGVjdG9yOzxicj4KPGJyPgom
bmJzcDsgJm5ic3A7IGMuUGlwZWxpbmVBcHAuTXlDb25maWd1cmFibGUuYzx3YnI+b21tb25fZGly
ID0gJy9vdXRwdXQnPGJyPgo8YnI+Ckl0IHdpbGwgdGFyZ2V0IG9ubHkgTXlDb25maWd1cmFibGUg
d2hlcmUgYHBhcmVudD1zZWxmYCBpcyBwYXNzZWQgYW5kPGJyPgpwYXJlbnQgaXMgYW48YnI+Cmlu
c3RhbmNlIG9mIFBpcGVsaW5lQXBwLiAoVGhpcyBpcyBhIHJhcmUgY2FzZSB1c2UgaW4gbmJjb252
ZXJ0IHRvIGFsbG93PGJyPgpjb25maWd1cmF0aW9uIG9mIGVhY2ggZXhwb3J0ZXIgaW5kZXBlbmRl
bnRseSk8YnI+Cjxicj4KRG9lcyB0aGF0IGFuc3dlciB5b3VyIHF1ZXN0aW9ucyA/PGJyPgo8YnI+
Ci0tPGJyPgo8YnI+Ck1hdHRoaWFzPGJyPgo8ZGl2PjxkaXYgY2xhc3M9Im1fMjQ3NTMzNjQ5MjE3
Mjg4NzA5aDUiPjxicj4KT24gVHVlLCBGZWIgMjEsIDIwMTcgYXQgNzowMSBBTSwgRyBKb25lcyAm
bHQ7PGEgaHJlZj0ibWFpbHRvOmdsZW5uLmNhbHRlY2hAZ21haWwuY29tIiB0YXJnZXQ9Il9ibGFu
ayI+Z2xlbm4uY2FsdGVjaEBnbWFpbC5jb208L2E+Jmd0OyB3cm90ZTo8YnI+CiZndDsgSGVsbG8s
PGJyPgomZ3Q7PGJyPgomZ3Q7IEkgYW0gd29ya2luZyBvbiB1c2luZyB0cmFpdGxldHMuY29uZmln
IGluIG15IHByb2plY3QuIFRoZSBhcHBsaWNhdGlvbiBoYXM8YnI+CiZndDsgdGhpcyBzdHJ1Y3R1
cmU6PGJyPgomZ3Q7PGJyPgomZ3Q7IGNsYXNzIFdyaXRlcihDb25maWd1cmFibGUpOjxicj4KJmd0
OyZuYnNwOyAmbmJzcDsgJm5ic3A7d3JpdGVyX3RyYWl0ID0gSW50KDQpLnRhZyhjb25maWc9VHJ1
ZSk8YnI+CiZndDsmbmJzcDsgJm5ic3A7ICZuYnNwO2NvbW1vbl9kaXIgPSBVbmljb2RlKCcnKS50
YWcoY29uZmlnPVRydWUpPGJyPgomZ3Q7PGJyPgomZ3Q7IGNsYXNzIEFjcXVpcmUoQ29uZmlndXJh
YmxlKTo8YnI+CiZndDsmbmJzcDsgJm5ic3A7ICZuYnNwO2FjcXVpcmVfdHJhaXQgPSBJbnQoNTUp
LnRhZyhjb25maWc9VHJ1ZSk8YnI+CiZndDsmbmJzcDsgJm5ic3A7ICZuYnNwO2NvbW1vbl9kaXIg
PSBVbmljb2RlKCcnKS50YWcoY29uZmlnPVRydWUpPGJyPgomZ3Q7PGJyPgomZ3Q7IGNsYXNzIFBp
cGVsaW5lKENvbmZpZ3VyYWJsZSk6PGJyPgomZ3Q7Jm5ic3A7ICZuYnNwOyAmbmJzcDtjb21tb25f
ZGlyID0gVW5pY29kZSgnJykudGFnKGNvbmZpZz1UcnVlKTxicj4KJmd0OyZuYnNwOyAmbmJzcDsg
Jm5ic3A7ZGVmIGluaXRpYWxpemUoc2VsZik6PGJyPgomZ3Q7Jm5ic3A7ICZuYnNwOyAmbmJzcDsg
Jm5ic3A7ICZuYnNwO3NlbGYud3JpdGVyID0gV3JpdGVyKCk8YnI+CiZndDsmbmJzcDsgJm5ic3A7
ICZuYnNwOyAmbmJzcDsgJm5ic3A7c2VsZi5hY3F1aXJlID0gQWNxdWlyZSgpPGJyPgomZ3Q7PGJy
PgomZ3Q7IGNsYXNzIFBpcGVsaW5lQXBwKEFwcGxpY2F0aW9uKTo8YnI+CiZndDsmbmJzcDsgJm5i
c3A7ICZuYnNwO2NsYXNzZXMgPSBbUGlwZWxpbmUsIEFjcXVpcmUsIFdyaXRlcl08YnI+CiZndDsm
bmJzcDsgJm5ic3A7ICZuYnNwO2RlZiBpbml0aWFsaXplKHNlbGYsYXJndj1Ob25lKTo8YnI+CiZn
dDsmbmJzcDsgJm5ic3A7ICZuYnNwOyAmbmJzcDsgJm5ic3A7c2VsZi5waXBlbGluZSA9IFBpcGVs
aW5lKGNvbmZpZz1zZWxmLmNvbmZpZyk8YnI+CiZndDsmbmJzcDsgJm5ic3A7ICZuYnNwOyAmbmJz
cDsgJm5ic3A7c2VsZi5waXBlbGluZS5pbml0aWFsaXplKCk8YnI+CiZndDs8YnI+CiZndDs8YnI+
CiZndDsgVGhlIGlkZWEgaXMgdGhhdCB0aGUgY29tbW9uX2RpciB0cmFpdHMgc2hvdWxkIGJlIGFs
bCB0aGUgc2FtZS4gVGhlIGNvZGU8YnI+CiZndDsgd29ya3MgYXMgd3JpdHRlbiwgYnV0IHJlc3Vs
dHMgaW4gdGhyZWUgcG9zc2libGUgbGluZXMgaW4gdGhlIHNldHRpbmdzIGZpbGUuPGJyPgomZ3Q7
IFNpbmNlIHRoZSBzZXR0aW5ncyBmaWxlIGlzIGp1c3QgcHl0aG9uLCBpdCdzIG5vdCB0b28gYmFk
IHRvIGRvPGJyPgomZ3Q7IGMuUGlwZWxpbmUuY29tbW9uX2RpciA9ICcvb3V0cHV0Jzxicj4KJmd0
OyBjLkFjcXVpcmUuY29tbW9uX2RpciA9IGMuUGlwZWxpbmUuY29tbW9uX2Rpcjxicj4KJmd0OyBj
LldyaXRlci5jb21tb25fZGlyID0gYy5QaXBlbGluZS5jb21tb25fZGlyPGJyPgomZ3Q7PGJyPgom
Z3Q7IEJ1dCBpdCBzZWVtcyBsaWtlIHRoZXJlIHNob3VsZCBiZSBhIGJldHRlciB3YXkuPGJyPgom
Z3Q7PGJyPgomZ3Q7IEkgc2VlIHRoYXQgSSBjb3VsZCBwYXNzIGluIGEgcGFyZW50IGFuZCBhY2Nl
c3MgaXQgdGhhdCB3YXk6PGJyPgomZ3Q7IHNlbGYud3JpdGVyID0gV3JpdGVyKHBhcmVudD1zZWxm
KTxicj4KJmd0Ozxicj4KJmd0OyBhbmQgdGhlbiBpbiB3cml0ZXI6PGJyPgomZ3Q7IHNlbGYucGFy
ZW50LmNvbW1vbl9kaXI8YnI+CiZndDs8YnI+CiZndDsgQnV0IHRoZW4gaWYgSSB3YW50IHRvIHVz
ZSBXcml0ZXIgb24gaXRzIG93biwgSSBuZWVkIHRvIGRvIGEgY2hlY2sgaWY8YnI+CiZndDsgc2Vs
Zi5wYXJlbnQuLi4uIG9yIHNvbWV0aGluZy48YnI+CiZndDs8YnI+CiZndDsgSXMgdGhlcmUgYSBi
ZXR0ZXIgd2F5PyBJIGhvcGUgdGhlIGludGVudCBpcyBjbGVhciwgcGxlYXNlIGxldCBtZSBrbm93
IGlmPGJyPgomZ3Q7IG5vdC48YnI+CiZndDs8YnI+CiZndDsgVGhhbmtzLDxicj4KJmd0OyBHbGVu
bjxicj4KJmd0Ozxicj4KPC9kaXY+PC9kaXY+Jmd0OyBfX19fX19fX19fX19fX19fX19fX19fX19f
X19fX188d2JyPl9fX19fX19fX19fX19fX19fPGJyPgomZ3Q7IElQeXRob24tZGV2IG1haWxpbmcg
bGlzdDxicj4KJmd0OyA8YSBocmVmPSJtYWlsdG86SVB5dGhvbi1kZXZAc2NpcHkub3JnIiB0YXJn
ZXQ9Il9ibGFuayI+SVB5dGhvbi1kZXZAc2NpcHkub3JnPC9hPjxicj4KJmd0OyA8YSBocmVmPSJo
dHRwczovL21haWwuc2NpcHkub3JnL21haWxtYW4vbGlzdGluZm8vaXB5dGhvbi1kZXYiIHJlbD0i
bm9yZWZlcnJlciIgdGFyZ2V0PSJfYmxhbmsiIGRhdGEtc2FmZXJlZGlyZWN0dXJsPSJodHRwczov
L3d3dy5nb29nbGUuY29tL3VybD9obD1lbiZhbXA7cT1odHRwczovL21haWwuc2NpcHkub3JnL21h
aWxtYW4vbGlzdGluZm8vaXB5dGhvbi1kZXYmYW1wO3NvdXJjZT1nbWFpbCZhbXA7dXN0PTE0ODgy
NzAwNjc5ODcwMDAmYW1wO3VzZz1BRlFqQ05IajEtZFlTSXJHeldpNjhILXoxU05Yekw5TVJ3Ij5o
dHRwczovL21haWwuc2NpcHkub3JnL21haWxtYW48d2JyPi9saXN0aW5mby9pcHl0aG9uLWRldjwv
YT48YnI+CiZndDs8YnI+Cl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fXzx3YnI+X19fX19f
X19fX19fX19fX188YnI+CklQeXRob24tZGV2IG1haWxpbmcgbGlzdDxicj4KPGEgaHJlZj0ibWFp
bHRvOklQeXRob24tZGV2QHNjaXB5Lm9yZyIgdGFyZ2V0PSJfYmxhbmsiPklQeXRob24tZGV2QHNj
aXB5Lm9yZzwvYT48YnI+CjxhIGhyZWY9Imh0dHBzOi8vbWFpbC5zY2lweS5vcmcvbWFpbG1hbi9s
aXN0aW5mby9pcHl0aG9uLWRldiIgcmVsPSJub3JlZmVycmVyIiB0YXJnZXQ9Il9ibGFuayIgZGF0
YS1zYWZlcmVkaXJlY3R1cmw9Imh0dHBzOi8vd3d3Lmdvb2dsZS5jb20vdXJsP2hsPWVuJmFtcDtx
PWh0dHBzOi8vbWFpbC5zY2lweS5vcmcvbWFpbG1hbi9saXN0aW5mby9pcHl0aG9uLWRldiZhbXA7
c291cmNlPWdtYWlsJmFtcDt1c3Q9MTQ4ODI3MDA2Nzk4NzAwMCZhbXA7dXNnPUFGUWpDTkhqMS1k
WVNJckd6V2k2OEgtejFTTlh6TDlNUnciPmh0dHBzOi8vbWFpbC5zY2lweS5vcmcvbWFpbG1hbjx3
YnI+L2xpc3RpbmZvL2lweXRob24tZGV2PC9hPjxicj4KPC9ibG9ja3F1b3RlPjwvZGl2Pjxicj48
L2Rpdj4KPC9kaXY+PC9kaXY+PGJyPl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fXzx3YnI+
X19fX19fX19fX19fX19fX188YnI+CklQeXRob24tZGV2IG1haWxpbmcgbGlzdDxicj4KPGEgaHJl
Zj0ibWFpbHRvOklQeXRob24tZGV2QHNjaXB5Lm9yZyI+SVB5dGhvbi1kZXZAc2NpcHkub3JnPC9h
Pjxicj4KPGEgaHJlZj0iaHR0cHM6Ly9tYWlsLnNjaXB5Lm9yZy9tYWlsbWFuL2xpc3RpbmZvL2lw
eXRob24tZGV2IiBkYXRhLXNhZmVyZWRpcmVjdHVybD0iaHR0cHM6Ly93d3cuZ29vZ2xlLmNvbS91
cmw/aGw9ZW4mYW1wO3E9aHR0cHM6Ly9tYWlsLnNjaXB5Lm9yZy9tYWlsbWFuL2xpc3RpbmZvL2lw
eXRob24tZGV2JmFtcDtzb3VyY2U9Z21haWwmYW1wO3VzdD0xNDg4MjcwMDY3OTk5MDAwJmFtcDt1
c2c9QUZRakNORTJVVkJJVTdaMXpGS2lmYnk5NzUtNS1fdHhDQSIgcmVsPSJub3JlZmVycmVyIiB0
YXJnZXQ9Il9ibGFuayI+aHR0cHM6Ly9tYWlsLnNjaXB5Lm9yZy88d2JyPm1haWxtYW4vbGlzdGlu
Zm8vaXB5dGhvbi1kZXY8L2E+PGJyPgo8YnI+PC9ibG9ja3F1b3RlPjwvZGl2Pjxicj48L2Rpdj4=" style="height:0;width:0;max-height:0;max-width:0;overflow:hidden;font-size:0em;padding:0;margin:0">​</div></div></div>