-
Notifications
You must be signed in to change notification settings - Fork 46
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Extract generic decorator into a reusable class (#569)
The only current use of the decorator pattern in colcon-core is the argument parser, but the concept can be applied generically in a variety of scenarios.
- Loading branch information
Showing
4 changed files
with
60 additions
and
38 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
# Copyright 2023 Open Source Robotics Foundation, Inc. | ||
# Licensed under the Apache License, Version 2.0 | ||
|
||
|
||
class GenericDecorator: | ||
"""A generic class decorator.""" | ||
|
||
def __init__(self, decoree, **kwargs): | ||
""" | ||
Create a new decorated class instance. | ||
:param decoree: The instance to decorate | ||
:param **kwargs: The keyword arguments are set as attributes on this | ||
instance | ||
""" | ||
assert '_decoree' not in kwargs | ||
kwargs['_decoree'] = decoree | ||
for k, v in kwargs.items(): | ||
self.__dict__[k] = v | ||
|
||
def __getattr__(self, name): | ||
""" | ||
Get an attribute from this decorator if it exists or the decoree. | ||
:param str name: The name of the attribute | ||
:returns: The attribute value | ||
:raises AttributeError: if the attribute doesn't exist in either of the | ||
two instances | ||
""" | ||
if '_decoree' not in self.__dict__: | ||
raise AttributeError(name) | ||
return getattr(self.__dict__['_decoree'], name) | ||
|
||
def __setattr__(self, name, value): | ||
""" | ||
Set an attribute value on this decorator if it exists or the decoree. | ||
:param str name: The name of the attribute | ||
:param value: The attribute value | ||
""" | ||
assert name != '_decoree' | ||
# overwrite existing attribute | ||
if name in self.__dict__: | ||
self.__dict__[name] = value | ||
return | ||
if '_decoree' not in self.__dict__: | ||
self.__dict__[name] = value | ||
return | ||
# set attribute on decoree | ||
setattr(self.__dict__['_decoree'], name, value) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,5 @@ | ||
addopts | ||
apache | ||
argcomplete | ||
argparse | ||
asyncio | ||
autouse | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters