We have a config.yaml
file like this:
darwin:
installer:
title: "%(product_name)s %(version)s"
filename: "%(brand_name)s-%(version)s"
and a function to format it:
def format_context(config):
return {
"company_name": config['company_name'],
"product_name": config['product_name'],
"brand_name": config['brand_name'],
"title": config['darwin']['installer']['title'],
"filename": config['darwin']['installer']['filename'],
}
The goal here is we can input the value as a formatted string.
Now I need to turn the dictionary return by format_context
into variables.
The first try is use locals()
:
context = format_context(config)
for k, v in context.iteritems():
locals()[k] = str(v) % context
But maybe due to the order, I sometimes got a KeyError
error. And moreover, from the Python doc:
Note The contents of this dictionary should not be modified; changes may not affect the values of local and free variables used by the interpreter.
So, I switched to use exec
:
context = format_context(config)
for k, v in context.iteritems():
exec("%s = '%s'" % (k, str(v) % context))
It works but I'm wondering is this a good way?
Please let me clarify why I'm going to create variables from that dict.
I have a function to parse this config.yaml
:
class BrandConfiguration(object):
"""
A brand configuration (directory)
"""
def __init__(self, directory):
self.dirname = directory
@property
def config(self):
"""
return configuration for a single brand
"""
with open(os.path.join(self.dirname, "config.yaml")) as fh:
return yaml.load(fh)
Then in one class, I defined some variables:
- brand_config = self.brand_config_instance.config
- binary_name = brand_config['binary_name']
- major_version = brand_config['version']['major']
- minor_version = brand_config['version']['minor']
- patch_version = brand_config['version']['patch']
In another class (or another Python file), I need to do the same thing:
- brand_name, binary_name = config['brand_name'], config['binary_name']
- identifiers = [binary_name] + brand_name.split('.')
- identifiers.reverse()
- identifier = '.'.join(identifiers)
- major_version = config['version']['major']
- minor_version = config['version']['minor']
- patch_version = config['version']['patch']
- version = '.'.join(
- (
- str(major_version),
- str(minor_version),
- str(patch_version),
- build_number
- )
- )
Since I don't want to duplicate the code, I'm trying store it all in a dictionary and convert it into variables.
Where/how are you trying to use the values from the dictionary returned by format_context?
Assumming that in config.yaml
, you have something like this:
version:
major: 1
minor: 0
patch: 0
When adding metadata for Windows, instead of creating some variables:
- brand_name, binary_name = config['brand_name'], config['binary_name']
- identifiers = [binary_name] + brand_name.split('.')
- identifiers.reverse()
- identifier = '.'.join(identifiers)
- major_version = config['version']['major']
- minor_version = config['version']['minor']
- patch_version = config['version']['patch']
- version = '.'.join(
- (
- str(major_version),
- str(minor_version),
- str(patch_version),
- build_number
- )
- )
now I can use it directly:
json_data['FixedFileInfo']['FileVersion']['Major'] = major_version
json_data['FixedFileInfo']['FileVersion']['Minor'] = minor_version
json_data['FixedFileInfo']['FileVersion']['Patch'] = patch_version
json_data['FixedFileInfo']['FileVersion']['Build'] = build_number
json_data['FixedFileInfo']['ProductVersion'] = \
json_data['FixedFileInfo']['FileVersion']
json_data['StringFileInfo']['CompanyName'] = company_name
json_data['StringFileInfo']['FileDescription'] = service_description
json_data['StringFileInfo']['LegalCopyright'] = legal_copyright
json_data['StringFileInfo']['ProductName'] = product_name
json_data['StringFileInfo']['ProductVersion'] = '.'.join(
(
str(major_version),
str(minor_version),
str(patch_version),
self.target.build_number
)
)