ARG default value across multiple stages - dockerfile

How can I give a default value to MY_ARG if it is used across multiple stages?
ARG MY_ARG
FROM something as base
# use ARG here
FROM other as final
# use ARG here

Alright. Apparently it is as simple as doing
ARG MY_ARG=some-value
FROM something as base
# use ARG here
FROM other as final
# use ARG here

Related

forcing keyword arguments in python 2.7

I know I can use * to force all keyword arguments to a function/method to be "named".
If I have
def abc(a, *, x=10, z=30):
pass
then the following all work
abc(5)
abc(8, x=12)
abc(9, z=31)
abc(x=17, a=4)
even if I change the function signature to def abc(a, *, x=10, y=20, z=30),
and
abc(7, 13)
throws an error.
This is extremely important because, I can use the logical place, which will help maintenance over time, without being forced to use the end position based on history.
But * is not valid in Python 2.7, and abc(a, *args, x=10, z=30) (which I tried) doesn't work either.
Is there a way to force the use of x=12 in Python 2.7? Or another way of saying: make abc(7, 13) be invalid on Python 2.7.
One way of doing this is by adding a dummy keyword argument that never gets a valid positional value (so don't check for None):
_dummy = object()
def abc(a, dummy_kw=_dummy, x=10, z=30):
if dummy_kw is not _dummy:
raise TypeError("abc() takes 1 positional argument but at least 2 were given")
That will prohibit abc(7, 13) and allow all the others. It works on Python 2 and Python 3, so it is useful when you have code that needs to run on both.
Originally I used:
def _dummy():
pass
but as #mata pointed out _dummy=object() works as well, and cleaner. Essentially any unique memory location that is not used in another way will work.
What about the following:
def abc(a, **kwargs):
# Get arguments from kwargs otherwise use default values
x = kwargs.pop('x', 10)
z = kwargs.pop('z', 30)
if not kwargs: # if kwargs is not empty
print 'extra parameters passed'
pass
This allows to force the use of kwargs and still have default values.
pop removes the key from kwargs, once you use it.
This is potentially very useful as you can check if the user gave extra parameters that do not belong to the function and in this case you can throw an error (for example).

Python: assigning variables from function(*args) using argparse

I'm trying to assign my arguments from argparse to variables. I have two scripts one is the parser and the other is a module. When I try to assign a variable I get a tuple object has no attribute error. Any guidance would be appreciated.
def main():
parser = argparse.ArgumentParser(description='A simple front end script interface')
subparsers = parser.add_subparsers(help='(run various listed scripts..)', dest='mode')
add_pyrr_command_options(subparsers)
args = parser.parse_args()
if args.mode == "pyrr":
pyrr.parse_cmds(args)
else:
parser.print_usage()
pyrr.py
def parse_cmds(*args):
print(args)
pass
(Namespace(mode='pyrr', plugin_name='ntuser', reg_loc='/user/home', rip_loc='/user/some'),)
When I try to assign a variable via researched methods (e.g. arg.plugin_name) I get a AttributeError: 'tuple' object has no attribute 'pyrr'
So args is a Namespace object
Namespace(mode='pyrr', plugin_name='ntuser', reg_loc='/user/home', rip_loc='/user/some')
And as your 1st script shows you can use args.mode.
In (with corrected indent)
def parse_cmds(*args):
print(args)
pass
args is a tuple (because of the *args), e.g. (Namespace(...),). With plain args you could continue to access mode with:
def parse_cmds(args):
args.mode
Another option is to pass a dictionary via **kwargs
def parse_cmds(**vargs):
# vargs is a keyword dictionary
parse_cmds(vars(args)) # converting namespace to dictionary
I think you are on the right track. You just to need to distinguish between namespace object, dictionaries, and tuples.
In your examples 'pyrr' is the string value of args.mode, and also the name of the imported pyrr.py module.

Passing an argument to main that calls a function in python

I'm trying to pass arguments to my python script using argparse and consequently call functions. Any ideas where I might be going wrong?
def parse_args():
parser = argparse.ArgumentParser()
parser.add_argument('-d','--d', dest='action', action='store_const',const=do_comparison,
help="Diff the current and most recent map file memory information)")
options = parser.parse_args()
return options
def do_comparison(parsed_args):
# do things
def main(args):
options = parse_args()
if __name__ == '__main__':
sys.exit(main())
In my comment I missed the fact that you are using store_const and const=do_comparison. So you are trying some sort of callback.
options from parse_args is a argparse.Namespace object. This is a simple object, similar to a dictionary. In fact vars(options) returns a dictionary.
When main is run (with -d), options.action will be set to the const, a function. But remember, in Python, functions are first class objects, and can be set to variables, etc just like numbers and strings. To be used the function has to be 'called'.
options.action()
should end up calling do_comparison. Actually since that function requires an argument, you should use
options.action(options)
or some other way of providing a varible or object to the function.
Of course you'll have to be careful about the case where you don't specify -d. Then options.action will have the default value (e.g. None). If the default isn't a callable, then this call will produce an error.
The argparse documentation illustrates this kind of action in the section dealing with subparsers (subcommands). I vaguely recall a tutorial that set an argument value to functions like add and multiply, creating a simple arithmetic expression evaluator.
Usually the values in the Namespace are strings, or numbers, and to use them you test for string equality. e.g.
if options.action is None:
# default action
elif options.action == 'print':
print(options)
else:
do some other backup or error
A callback kind of action is possible, and may be convenient in some cases, but it isn't the usual arrangement.
You asked about using successfully store a string following the -d, to be used as the function arg with:
parser.add_argument('-d','--d', dest='action', dest='function_input', action='store_const', const=diff_map)
A 'store_const' action does not take an argument (in effect nargs=0). It's more like store_true. In fact store_true is just a store_const with has default=False and const=True.
What you need is another argument, whick could occur either before or after the -d. argparse tries to be order flexible.
Here's a simple script with a callable argument, and flexible positional argument.
import argparse
def action1(*args):
print 'action1',args
def action0(*args):
print 'action0',args
parser = argparse.ArgumentParser()
parser.add_argument('-d', dest='action', action='store_const', const=action1, default=action0)
parser.add_argument('args', nargs='*')
args = parser.parse_args()
args.action(args.args)
resulting runs
1238:~/mypy$ python stack32214076.py
action0 ([],)
1238:~/mypy$ python stack32214076.py one two three
action0 (['one', 'two', 'three'],)
1238:~/mypy$ python stack32214076.py one two three -d
action1 (['one', 'two', 'three'],)
1239:~/mypy$ python stack32214076.py -d one two three
action1 (['one', 'two', 'three'],)
1239:~/mypy$ python stack32214076.py -d
action1 ([],)
TO make -d value perform some action on value, try:
parser.add_argument('-d','--action')
The default action type stores one value (e.g. action='store', nargs=None)
args = parser.parse_args()
if args.action: # or is not None
do_comparison(args.action)
If -d is not given args.action will have default None value, and nothing happens here.
If -d astr is given acts.action will have the string value 'astr'. This if just calls the do_comparison function with this value. It's the present of this (nondefault) value that triggers the function call.
This is a rather straight forward use of a parser and an argument.

Django: what is the difference between using request and context as argument

I am defining a function in my context_processor to pass a value from my settings to use in templates. So what is the right way, and more importantly what is the difference?
def baseurl(request):
return {'BASE_URL': settings.BASE_URL}
or
def baseurl(context):
return {'BASE_URL': settings.BASE_URL}
I have always used the first, but have run into a few examples of the second
From django/template/context.py:
class RequestContext(Context):
"""
This subclass of template.Context automatically populates itself using
the processors defined in TEMPLATE_CONTEXT_PROCESSORS.
Additional processors can be specified as a list of callables
using the "processors" keyword argument.
"""
def __init__(self, request, dict_=None, processors=None, current_app=None,
use_l10n=None, use_tz=None):
Context.__init__(self, dict_, current_app=current_app,
use_l10n=use_l10n, use_tz=use_tz)
if processors is None:
processors = ()
else:
processors = tuple(processors)
for processor in get_standard_processors() + processors:
self.update(processor(request))
The last two lines are the most important. It means that arguments are not named. Thus it doesn't matter how you name your argument.
You are free to call this argument whatever you like but request is the most common or clear. From the Django docs: https://docs.djangoproject.com/en/1.4/ref/templates/api/#writing-your-own-context-processors
A context processor has a very simple interface: It's just a Python function that takes one argument, an HttpRequest object, and returns a dictionary that gets added to the template context.
While there is nothing stopping you from naming this argument context it would be misleading since it is passed an HttpRequest object.

In Django urls. How can we make the link argument as optional .i.e. (\w+)

I want to make the arguments i pass through the urls as optional.
url(r'^dashboard/forms/(\w+)|/create/$','dashboard_message_create'),
url(r'^dashboard/forms/(\w+)/delete/$', 'delete'),
The problem with using "|" is that django cannot distinguish between the above 2 urls.
I am new to django . So any pointers in this direction will be very useful. Thanks in advance
You can try associating both with the same view
url(r'^dashboard/forms/create/$','dashboard_message_create'),
url(r'^dashboard/forms/(\w+)/create/$','dashboard_message_create'),
Then, make sure dashboard_message_create works without the argument
def dashboard_message_create(request, name=None):
# Body
You can do better, using full re-superpowers (well, almost super, no lookahead in urlpatterns...):
url(r'^dashboard/forms/((?P<name>\w+)/)?create/$','dashboard_message_create'),
url(r'^dashboard/forms/(?P<name>\w+)/delete/$', 'delete'),
Add named args to your view and ignore the unnamed ones:
def dashboard_message_create(request, name, *args, **kwargs):
pass
The name arg will be None when the ((?P<name>\w+)/)? token matches the empty string.