We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Coverity - forward null
Event null_check: Comparing "f" to a null-like value implies that "f" might be null-like.
https://github.com/ros/ros_comm/blob/29053c4832229efa7160fb944c05e3bc82e11540/tools/rosgraph/src/rosgraph/roslogging.py#L61-L62

Event property_access: | Accessing a property of null-like value "f".
https://github.com/ros/ros_comm/blob/29053c4832229efa7160fb944c05e3bc82e11540/tools/rosgraph/src/rosgraph/roslogging.py#L76

There is a path for a null-valued variable to be dereferenced. But "f" might still be None

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `tools/rosgraph/src/rosgraph/roslogging.py`
Content:
```
1 # Software License Agreement (BSD License)
2 #
3 # Copyright (c) 2008, Willow Garage, Inc.
4 # All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
8 # are met:
9 #
10 #  * Redistributions of source code must retain the above copyright
11 #    notice, this list of conditions and the following disclaimer.
12 #  * Redistributions in binary form must reproduce the above
13 #    copyright notice, this list of conditions and the following
14 #    disclaimer in the documentation and/or other materials provided
15 #    with the distribution.
16 #  * Neither the name of Willow Garage, Inc. nor the names of its
17 #    contributors may be used to endorse or promote products derived
18 #    from this software without specific prior written permission.
19 #
20 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 # POSSIBILITY OF SUCH DAMAGE.
32 
33 """
34 Library for configuring python logging to standard ROS locations (e.g. ROS_LOG_DIR).
35 """
36 
37 import os
38 import sys
39 import time
40 import logging
41 import logging.config
42 import inspect
43 
44 import yaml
45 
46 import rospkg
47 from rospkg.environment import ROS_LOG_DIR
48 
49 class LoggingException(Exception): pass
50 
51 class RospyLogger(logging.getLoggerClass()):
52     def findCaller(self, stack_info=False):
53         """
54         Find the stack frame of the caller so that we can note the source
55         file name, line number, and function name with class name if possible.
56         """
57         file_name, lineno, func_name = super(RospyLogger, self).findCaller()[:3]
58         file_name = os.path.normcase(file_name)
59 
60         f = inspect.currentframe()
61         if f is not None:
62             f = f.f_back
63         while hasattr(f, "f_code"):
64             # Search for the right frame using the data already found by parent class.
65             co = f.f_code
66             filename = os.path.normcase(co.co_filename)
67             if filename == file_name and f.f_lineno == lineno and co.co_name == func_name:
68                 break
69             f = f.f_back
70 
71         # Jump up two more frames, as the logger methods have been double wrapped.
72         if f.f_back and f.f_code and f.f_code.co_name == '_base_logger':
73             f = f.f_back
74             if f.f_back:
75                 f = f.f_back
76         co = f.f_code
77         func_name = co.co_name
78 
79         # Now extend the function name with class name, if available.
80         try:
81             class_name = f.f_locals['self'].__class__.__name__
82             func_name = '%s.%s' % (class_name, func_name)
83         except KeyError:  # if the function is unbound, there is no self.
84             pass
85 
86         if sys.version_info > (3, 2):
87             # Dummy last argument to match Python3 return type
88             return co.co_filename, f.f_lineno, func_name, None
89         else:
90             return co.co_filename, f.f_lineno, func_name
91 
92 logging.setLoggerClass(RospyLogger)
93 
94 def renew_latest_logdir(logfile_dir):
95     log_dir = os.path.dirname(logfile_dir)
96     latest_dir = os.path.join(log_dir, 'latest')
97     if os.path.lexists(latest_dir):
98         if not os.path.islink(latest_dir):
99             return False
100         os.remove(latest_dir)
101     os.symlink(logfile_dir, latest_dir)
102     return True
103 
104 def configure_logging(logname, level=logging.INFO, filename=None, env=None):
105     """
106     Configure Python logging package to send log files to ROS-specific log directory
107     :param logname str: name of logger, ``str``
108     :param filename: filename to log to. If not set, a log filename
109         will be generated using logname, ``str``
110     :param env: override os.environ dictionary, ``dict``
111     :returns: log file name, ``str``
112     :raises: :exc:`LoggingException` If logging cannot be configured as specified
113     """
114     if env is None:
115         env = os.environ
116 
117     logname = logname or 'unknown'
118     log_dir = rospkg.get_log_dir(env=env)
119     
120     # if filename is not explicitly provided, generate one using logname
121     if not filename:
122         log_filename = os.path.join(log_dir, '%s-%s.log'%(logname, os.getpid()))
123     else:
124         log_filename = os.path.join(log_dir, filename)
125 
126     logfile_dir = os.path.dirname(log_filename)
127     if not os.path.exists(logfile_dir):
128         try:
129             makedirs_with_parent_perms(logfile_dir)
130         except OSError:
131             # cannot print to screen because command-line tools with output use this
132             if os.path.exists(logfile_dir):
133                 # We successfully created the logging folder, but could not change
134                 # permissions of the new folder to the same as the parent folder
135                 sys.stderr.write("WARNING: Could not change permissions for folder [%s], make sure that the parent folder has correct permissions.\n"%logfile_dir)
136             else:
137                 # Could not create folder
138                 sys.stderr.write("WARNING: cannot create log directory [%s]. Please set %s to a writable location.\n"%(logfile_dir, ROS_LOG_DIR))
139             return None
140     elif os.path.isfile(logfile_dir):
141         raise LoggingException("Cannot save log files: file [%s] is in the way"%logfile_dir)
142 
143     # the log dir itself should not be symlinked as latest
144     if logfile_dir != log_dir:
145         if sys.platform not in ['win32']:
146             try:
147                 success = renew_latest_logdir(logfile_dir)
148                 if not success:
149                     sys.stderr.write("INFO: cannot create a symlink to latest log directory\n")
150             except OSError as e:
151                 sys.stderr.write("INFO: cannot create a symlink to latest log directory: %s\n" % e)
152 
153     config_file = os.environ.get('ROS_PYTHON_LOG_CONFIG_FILE')
154     if not config_file:
155         # search for logging config file in ROS_HOME, ROS_ETC_DIR or relative
156         # to the rosgraph package directory.
157         rosgraph_d = rospkg.RosPack().get_path('rosgraph')
158         for config_dir in [os.path.join(rospkg.get_ros_home(), 'config'),
159                            rospkg.get_etc_ros_dir(),
160                            os.path.join(rosgraph_d, 'conf')]:
161             for extension in ('conf', 'yaml'):
162                 f = os.path.join(config_dir,
163                                  'python_logging{}{}'.format(os.path.extsep,
164                                                              extension))
165                 if os.path.isfile(f):
166                     config_file = f
167                     break
168             if config_file is not None:
169                 break
170 
171     if config_file is None or not os.path.isfile(config_file):
172         # logging is considered soft-fail
173         sys.stderr.write("WARNING: cannot load logging configuration file, logging is disabled\n")
174         logging.getLogger(logname).setLevel(logging.CRITICAL)
175         return log_filename
176     
177     # pass in log_filename as argument to pylogging.conf
178     os.environ['ROS_LOG_FILENAME'] = log_filename
179     if config_file.endswith(('.yaml', '.yml')):
180         with open(config_file) as f:
181             dict_conf = yaml.safe_load(f)
182         dict_conf.setdefault('version', 1)
183         logging.config.dictConfig(dict_conf)
184     else:
185         # #3625: disabling_existing_loggers=False
186         logging.config.fileConfig(config_file, disable_existing_loggers=False)
187 
188     return log_filename
189 
190 
191 def makedirs_with_parent_perms(p):
192     """
193     Create the directory using the permissions of the nearest
194     (existing) parent directory. This is useful for logging, where a
195     root process sometimes has to log in the user's space.
196     :param p: directory to create, ``str``
197     """    
198     p = os.path.abspath(p)
199     parent = os.path.dirname(p)
200     # recurse upwards, checking to make sure we haven't reached the
201     # top
202     if not os.path.exists(p) and p and parent != p:
203         makedirs_with_parent_perms(parent)
204         s = os.stat(parent)
205         os.mkdir(p)
206 
207         # if perms of new dir don't match, set anew
208         s2 = os.stat(p)
209         if s.st_uid != s2.st_uid or s.st_gid != s2.st_gid:
210             os.chown(p, s.st_uid, s.st_gid)
211         if s.st_mode != s2.st_mode:
212             os.chmod(p, s.st_mode)    
213 
214 _logging_to_rospy_names = {
215     'DEBUG': ('DEBUG', '\033[32m'),
216     'INFO': ('INFO', None),
217     'WARNING': ('WARN', '\033[33m'),
218     'ERROR': ('ERROR', '\033[31m'),
219     'CRITICAL': ('FATAL', '\033[31m')
220 }
221 _color_reset = '\033[0m'
222 _defaultFormatter = logging.Formatter()
223 
224 class RosStreamHandler(logging.Handler):
225     def __init__(self, colorize=True, stdout=None, stderr=None):
226         super(RosStreamHandler, self).__init__()
227         self._stdout = stdout or sys.stdout
228         self._stderr = stderr or sys.stderr
229         self._colorize = colorize
230         try:
231             from rospy.rostime import get_time, is_wallclock
232             self._get_time = get_time
233             self._is_wallclock = is_wallclock
234         except ImportError:
235             self._get_time = None
236             self._is_wallclock = None
237 
238     def emit(self, record):
239         level, color = _logging_to_rospy_names[record.levelname]
240         record_message = _defaultFormatter.format(record)
241         msg = os.environ.get(
242             'ROSCONSOLE_FORMAT', '[${severity}] [${time}]: ${message}')
243         msg = msg.replace('${severity}', level)
244         msg = msg.replace('${message}', str(record_message))
245         msg = msg.replace('${walltime}', '%f' % time.time())
246         msg = msg.replace('${thread}', str(record.thread))
247         msg = msg.replace('${logger}', str(record.name))
248         msg = msg.replace('${file}', str(record.pathname))
249         msg = msg.replace('${line}', str(record.lineno))
250         msg = msg.replace('${function}', str(record.funcName))
251         try:
252             from rospy import get_name
253             node_name = get_name()
254         except ImportError:
255             node_name = '<unknown_node_name>'
256         msg = msg.replace('${node}', node_name)
257         time_str = '%f' % time.time()
258         if self._get_time is not None and not self._is_wallclock():
259             time_str += ', %f' % self._get_time()
260         msg = msg.replace('${time}', time_str)
261         msg += '\n'
262         if record.levelno < logging.WARNING:
263             self._write(self._stdout, msg, color)
264         else:
265             self._write(self._stderr, msg, color)
266 
267     def _write(self, fd, msg, color):
268         if self._colorize and color and hasattr(fd, 'isatty') and fd.isatty():
269             msg = color + msg + _color_reset
270         fd.write(msg)
271
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/tools/rosgraph/src/rosgraph/roslogging.py b/tools/rosgraph/src/rosgraph/roslogging.py
--- a/tools/rosgraph/src/rosgraph/roslogging.py
+++ b/tools/rosgraph/src/rosgraph/roslogging.py
@@ -66,10 +66,11 @@
             filename = os.path.normcase(co.co_filename)
             if filename == file_name and f.f_lineno == lineno and co.co_name == func_name:
                 break
-            f = f.f_back
+            if f.f_back:
+                f = f.f_back
 
         # Jump up two more frames, as the logger methods have been double wrapped.
-        if f.f_back and f.f_code and f.f_code.co_name == '_base_logger':
+        if f is not None and f.f_back and f.f_code and f.f_code.co_name == '_base_logger':
             f = f.f_back
             if f.f_back:
                 f = f.f_back

{"golden_diff": "diff --git a/tools/rosgraph/src/rosgraph/roslogging.py b/tools/rosgraph/src/rosgraph/roslogging.py\n--- a/tools/rosgraph/src/rosgraph/roslogging.py\n+++ b/tools/rosgraph/src/rosgraph/roslogging.py\n@@ -66,10 +66,11 @@\n             filename = os.path.normcase(co.co_filename)\n             if filename == file_name and f.f_lineno == lineno and co.co_name == func_name:\n                 break\n-            f = f.f_back\n+            if f.f_back:\n+                f = f.f_back\n \n         # Jump up two more frames, as the logger methods have been double wrapped.\n-        if f.f_back and f.f_code and f.f_code.co_name == '_base_logger':\n+        if f is not None and f.f_back and f.f_code and f.f_code.co_name == '_base_logger':\n             f = f.f_back\n             if f.f_back:\n                 f = f.f_back\n", "issue": "Coverity - forward null\nEvent null_check: Comparing \"f\" to a null-like value implies that \"f\" might be null-like.\r\nhttps://github.com/ros/ros_comm/blob/29053c4832229efa7160fb944c05e3bc82e11540/tools/rosgraph/src/rosgraph/roslogging.py#L61-L62\r\n\r\nEvent property_access: | Accessing a property of null-like value \"f\".\r\nhttps://github.com/ros/ros_comm/blob/29053c4832229efa7160fb944c05e3bc82e11540/tools/rosgraph/src/rosgraph/roslogging.py#L76\r\n\r\nThere is a path for a null-valued variable to be dereferenced. But \"f\" might still be None\n", "before_files": [{"content": "# Software License Agreement (BSD License)\n#\n# Copyright (c) 2008, Willow Garage, Inc.\n# All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#\n#  * Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n#  * Redistributions in binary form must reproduce the above\n#    copyright notice, this list of conditions and the following\n#    disclaimer in the documentation and/or other materials provided\n#    with the distribution.\n#  * Neither the name of Willow Garage, Inc. nor the names of its\n#    contributors may be used to endorse or promote products derived\n#    from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n# \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS\n# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\n# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\n# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\n# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\n# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n# POSSIBILITY OF SUCH DAMAGE.\n\n\"\"\"\nLibrary for configuring python logging to standard ROS locations (e.g. ROS_LOG_DIR).\n\"\"\"\n\nimport os\nimport sys\nimport time\nimport logging\nimport logging.config\nimport inspect\n\nimport yaml\n\nimport rospkg\nfrom rospkg.environment import ROS_LOG_DIR\n\nclass LoggingException(Exception): pass\n\nclass RospyLogger(logging.getLoggerClass()):\n    def findCaller(self, stack_info=False):\n        \"\"\"\n        Find the stack frame of the caller so that we can note the source\n        file name, line number, and function name with class name if possible.\n        \"\"\"\n        file_name, lineno, func_name = super(RospyLogger, self).findCaller()[:3]\n        file_name = os.path.normcase(file_name)\n\n        f = inspect.currentframe()\n        if f is not None:\n            f = f.f_back\n        while hasattr(f, \"f_code\"):\n            # Search for the right frame using the data already found by parent class.\n            co = f.f_code\n            filename = os.path.normcase(co.co_filename)\n            if filename == file_name and f.f_lineno == lineno and co.co_name == func_name:\n                break\n            f = f.f_back\n\n        # Jump up two more frames, as the logger methods have been double wrapped.\n        if f.f_back and f.f_code and f.f_code.co_name == '_base_logger':\n            f = f.f_back\n            if f.f_back:\n                f = f.f_back\n        co = f.f_code\n        func_name = co.co_name\n\n        # Now extend the function name with class name, if available.\n        try:\n            class_name = f.f_locals['self'].__class__.__name__\n            func_name = '%s.%s' % (class_name, func_name)\n        except KeyError:  # if the function is unbound, there is no self.\n            pass\n\n        if sys.version_info > (3, 2):\n            # Dummy last argument to match Python3 return type\n            return co.co_filename, f.f_lineno, func_name, None\n        else:\n            return co.co_filename, f.f_lineno, func_name\n\nlogging.setLoggerClass(RospyLogger)\n\ndef renew_latest_logdir(logfile_dir):\n    log_dir = os.path.dirname(logfile_dir)\n    latest_dir = os.path.join(log_dir, 'latest')\n    if os.path.lexists(latest_dir):\n        if not os.path.islink(latest_dir):\n            return False\n        os.remove(latest_dir)\n    os.symlink(logfile_dir, latest_dir)\n    return True\n\ndef configure_logging(logname, level=logging.INFO, filename=None, env=None):\n    \"\"\"\n    Configure Python logging package to send log files to ROS-specific log directory\n    :param logname str: name of logger, ``str``\n    :param filename: filename to log to. If not set, a log filename\n        will be generated using logname, ``str``\n    :param env: override os.environ dictionary, ``dict``\n    :returns: log file name, ``str``\n    :raises: :exc:`LoggingException` If logging cannot be configured as specified\n    \"\"\"\n    if env is None:\n        env = os.environ\n\n    logname = logname or 'unknown'\n    log_dir = rospkg.get_log_dir(env=env)\n    \n    # if filename is not explicitly provided, generate one using logname\n    if not filename:\n        log_filename = os.path.join(log_dir, '%s-%s.log'%(logname, os.getpid()))\n    else:\n        log_filename = os.path.join(log_dir, filename)\n\n    logfile_dir = os.path.dirname(log_filename)\n    if not os.path.exists(logfile_dir):\n        try:\n            makedirs_with_parent_perms(logfile_dir)\n        except OSError:\n            # cannot print to screen because command-line tools with output use this\n            if os.path.exists(logfile_dir):\n                # We successfully created the logging folder, but could not change\n                # permissions of the new folder to the same as the parent folder\n                sys.stderr.write(\"WARNING: Could not change permissions for folder [%s], make sure that the parent folder has correct permissions.\\n\"%logfile_dir)\n            else:\n                # Could not create folder\n                sys.stderr.write(\"WARNING: cannot create log directory [%s]. Please set %s to a writable location.\\n\"%(logfile_dir, ROS_LOG_DIR))\n            return None\n    elif os.path.isfile(logfile_dir):\n        raise LoggingException(\"Cannot save log files: file [%s] is in the way\"%logfile_dir)\n\n    # the log dir itself should not be symlinked as latest\n    if logfile_dir != log_dir:\n        if sys.platform not in ['win32']:\n            try:\n                success = renew_latest_logdir(logfile_dir)\n                if not success:\n                    sys.stderr.write(\"INFO: cannot create a symlink to latest log directory\\n\")\n            except OSError as e:\n                sys.stderr.write(\"INFO: cannot create a symlink to latest log directory: %s\\n\" % e)\n\n    config_file = os.environ.get('ROS_PYTHON_LOG_CONFIG_FILE')\n    if not config_file:\n        # search for logging config file in ROS_HOME, ROS_ETC_DIR or relative\n        # to the rosgraph package directory.\n        rosgraph_d = rospkg.RosPack().get_path('rosgraph')\n        for config_dir in [os.path.join(rospkg.get_ros_home(), 'config'),\n                           rospkg.get_etc_ros_dir(),\n                           os.path.join(rosgraph_d, 'conf')]:\n            for extension in ('conf', 'yaml'):\n                f = os.path.join(config_dir,\n                                 'python_logging{}{}'.format(os.path.extsep,\n                                                             extension))\n                if os.path.isfile(f):\n                    config_file = f\n                    break\n            if config_file is not None:\n                break\n\n    if config_file is None or not os.path.isfile(config_file):\n        # logging is considered soft-fail\n        sys.stderr.write(\"WARNING: cannot load logging configuration file, logging is disabled\\n\")\n        logging.getLogger(logname).setLevel(logging.CRITICAL)\n        return log_filename\n    \n    # pass in log_filename as argument to pylogging.conf\n    os.environ['ROS_LOG_FILENAME'] = log_filename\n    if config_file.endswith(('.yaml', '.yml')):\n        with open(config_file) as f:\n            dict_conf = yaml.safe_load(f)\n        dict_conf.setdefault('version', 1)\n        logging.config.dictConfig(dict_conf)\n    else:\n        # #3625: disabling_existing_loggers=False\n        logging.config.fileConfig(config_file, disable_existing_loggers=False)\n\n    return log_filename\n\n\ndef makedirs_with_parent_perms(p):\n    \"\"\"\n    Create the directory using the permissions of the nearest\n    (existing) parent directory. This is useful for logging, where a\n    root process sometimes has to log in the user's space.\n    :param p: directory to create, ``str``\n    \"\"\"    \n    p = os.path.abspath(p)\n    parent = os.path.dirname(p)\n    # recurse upwards, checking to make sure we haven't reached the\n    # top\n    if not os.path.exists(p) and p and parent != p:\n        makedirs_with_parent_perms(parent)\n        s = os.stat(parent)\n        os.mkdir(p)\n\n        # if perms of new dir don't match, set anew\n        s2 = os.stat(p)\n        if s.st_uid != s2.st_uid or s.st_gid != s2.st_gid:\n            os.chown(p, s.st_uid, s.st_gid)\n        if s.st_mode != s2.st_mode:\n            os.chmod(p, s.st_mode)    \n\n_logging_to_rospy_names = {\n    'DEBUG': ('DEBUG', '\\033[32m'),\n    'INFO': ('INFO', None),\n    'WARNING': ('WARN', '\\033[33m'),\n    'ERROR': ('ERROR', '\\033[31m'),\n    'CRITICAL': ('FATAL', '\\033[31m')\n}\n_color_reset = '\\033[0m'\n_defaultFormatter = logging.Formatter()\n\nclass RosStreamHandler(logging.Handler):\n    def __init__(self, colorize=True, stdout=None, stderr=None):\n        super(RosStreamHandler, self).__init__()\n        self._stdout = stdout or sys.stdout\n        self._stderr = stderr or sys.stderr\n        self._colorize = colorize\n        try:\n            from rospy.rostime import get_time, is_wallclock\n            self._get_time = get_time\n            self._is_wallclock = is_wallclock\n        except ImportError:\n            self._get_time = None\n            self._is_wallclock = None\n\n    def emit(self, record):\n        level, color = _logging_to_rospy_names[record.levelname]\n        record_message = _defaultFormatter.format(record)\n        msg = os.environ.get(\n            'ROSCONSOLE_FORMAT', '[${severity}] [${time}]: ${message}')\n        msg = msg.replace('${severity}', level)\n        msg = msg.replace('${message}', str(record_message))\n        msg = msg.replace('${walltime}', '%f' % time.time())\n        msg = msg.replace('${thread}', str(record.thread))\n        msg = msg.replace('${logger}', str(record.name))\n        msg = msg.replace('${file}', str(record.pathname))\n        msg = msg.replace('${line}', str(record.lineno))\n        msg = msg.replace('${function}', str(record.funcName))\n        try:\n            from rospy import get_name\n            node_name = get_name()\n        except ImportError:\n            node_name = '<unknown_node_name>'\n        msg = msg.replace('${node}', node_name)\n        time_str = '%f' % time.time()\n        if self._get_time is not None and not self._is_wallclock():\n            time_str += ', %f' % self._get_time()\n        msg = msg.replace('${time}', time_str)\n        msg += '\\n'\n        if record.levelno < logging.WARNING:\n            self._write(self._stdout, msg, color)\n        else:\n            self._write(self._stderr, msg, color)\n\n    def _write(self, fd, msg, color):\n        if self._colorize and color and hasattr(fd, 'isatty') and fd.isatty():\n            msg = color + msg + _color_reset\n        fd.write(msg)\n", "path": "tools/rosgraph/src/rosgraph/roslogging.py"}], "after_files": [{"content": "# Software License Agreement (BSD License)\n#\n# Copyright (c) 2008, Willow Garage, Inc.\n# All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#\n#  * Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n#  * Redistributions in binary form must reproduce the above\n#    copyright notice, this list of conditions and the following\n#    disclaimer in the documentation and/or other materials provided\n#    with the distribution.\n#  * Neither the name of Willow Garage, Inc. nor the names of its\n#    contributors may be used to endorse or promote products derived\n#    from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n# \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS\n# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\n# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\n# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\n# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\n# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n# POSSIBILITY OF SUCH DAMAGE.\n\n\"\"\"\nLibrary for configuring python logging to standard ROS locations (e.g. ROS_LOG_DIR).\n\"\"\"\n\nimport os\nimport sys\nimport time\nimport logging\nimport logging.config\nimport inspect\n\nimport yaml\n\nimport rospkg\nfrom rospkg.environment import ROS_LOG_DIR\n\nclass LoggingException(Exception): pass\n\nclass RospyLogger(logging.getLoggerClass()):\n    def findCaller(self, dummy=False): # Dummy second arg to match Python3 function declaration\n        \"\"\"\n        Find the stack frame of the caller so that we can note the source\n        file name, line number, and function name with class name if possible.\n        \"\"\"\n        file_name, lineno, func_name = super(RospyLogger, self).findCaller()[:3]\n        file_name = os.path.normcase(file_name)\n\n        f = inspect.currentframe()\n        if f is not None:\n            f = f.f_back\n        while hasattr(f, \"f_code\"):\n            # Search for the right frame using the data already found by parent class.\n            co = f.f_code\n            filename = os.path.normcase(co.co_filename)\n            if filename == file_name and f.f_lineno == lineno and co.co_name == func_name:\n                break\n            if f.f_back:\n                f = f.f_back\n\n        # Jump up two more frames, as the logger methods have been double wrapped.\n        if f is not None and f.f_back and f.f_code and f.f_code.co_name == '_base_logger':\n            f = f.f_back\n            if f.f_back:\n                f = f.f_back\n        co = f.f_code\n        func_name = co.co_name\n\n        # Now extend the function name with class name, if available.\n        try:\n            class_name = f.f_locals['self'].__class__.__name__\n            func_name = '%s.%s' % (class_name, func_name)\n        except KeyError:  # if the function is unbound, there is no self.\n            pass\n\n        if sys.version_info > (3, 2):\n            # Dummy last argument to match Python3 return type\n            return co.co_filename, f.f_lineno, func_name, None\n        else:\n            return co.co_filename, f.f_lineno, func_name\n\nlogging.setLoggerClass(RospyLogger)\n\ndef renew_latest_logdir(logfile_dir):\n    log_dir = os.path.dirname(logfile_dir)\n    latest_dir = os.path.join(log_dir, 'latest')\n    if os.path.lexists(latest_dir):\n        if not os.path.islink(latest_dir):\n            return False\n        os.remove(latest_dir)\n    os.symlink(logfile_dir, latest_dir)\n    return True\n\ndef configure_logging(logname, level=logging.INFO, filename=None, env=None):\n    \"\"\"\n    Configure Python logging package to send log files to ROS-specific log directory\n    :param logname str: name of logger, ``str``\n    :param filename: filename to log to. If not set, a log filename\n        will be generated using logname, ``str``\n    :param env: override os.environ dictionary, ``dict``\n    :returns: log file name, ``str``\n    :raises: :exc:`LoggingException` If logging cannot be configured as specified\n    \"\"\"\n    if env is None:\n        env = os.environ\n\n    logname = logname or 'unknown'\n    log_dir = rospkg.get_log_dir(env=env)\n    \n    # if filename is not explicitly provided, generate one using logname\n    if not filename:\n        log_filename = os.path.join(log_dir, '%s-%s.log'%(logname, os.getpid()))\n    else:\n        log_filename = os.path.join(log_dir, filename)\n\n    logfile_dir = os.path.dirname(log_filename)\n    if not os.path.exists(logfile_dir):\n        try:\n            makedirs_with_parent_perms(logfile_dir)\n        except OSError:\n            # cannot print to screen because command-line tools with output use this\n            if os.path.exists(logfile_dir):\n                # We successfully created the logging folder, but could not change\n                # permissions of the new folder to the same as the parent folder\n                sys.stderr.write(\"WARNING: Could not change permissions for folder [%s], make sure that the parent folder has correct permissions.\\n\"%logfile_dir)\n            else:\n                # Could not create folder\n                sys.stderr.write(\"WARNING: cannot create log directory [%s]. Please set %s to a writable location.\\n\"%(logfile_dir, ROS_LOG_DIR))\n            return None\n    elif os.path.isfile(logfile_dir):\n        raise LoggingException(\"Cannot save log files: file [%s] is in the way\"%logfile_dir)\n\n    # the log dir itself should not be symlinked as latest\n    if logfile_dir != log_dir:\n        if sys.platform not in ['win32']:\n            try:\n                success = renew_latest_logdir(logfile_dir)\n                if not success:\n                    sys.stderr.write(\"INFO: cannot create a symlink to latest log directory\\n\")\n            except OSError as e:\n                sys.stderr.write(\"INFO: cannot create a symlink to latest log directory: %s\\n\" % e)\n\n    config_file = os.environ.get('ROS_PYTHON_LOG_CONFIG_FILE')\n    if not config_file:\n        # search for logging config file in ROS_HOME, ROS_ETC_DIR or relative\n        # to the rosgraph package directory.\n        rosgraph_d = rospkg.RosPack().get_path('rosgraph')\n        for config_dir in [os.path.join(rospkg.get_ros_home(), 'config'),\n                           rospkg.get_etc_ros_dir(),\n                           os.path.join(rosgraph_d, 'conf')]:\n            for extension in ('conf', 'yaml'):\n                f = os.path.join(config_dir,\n                                 'python_logging{}{}'.format(os.path.extsep,\n                                                             extension))\n                if os.path.isfile(f):\n                    config_file = f\n                    break\n            if config_file is not None:\n                break\n\n    if config_file is None or not os.path.isfile(config_file):\n        # logging is considered soft-fail\n        sys.stderr.write(\"WARNING: cannot load logging configuration file, logging is disabled\\n\")\n        logging.getLogger(logname).setLevel(logging.CRITICAL)\n        return log_filename\n    \n    # pass in log_filename as argument to pylogging.conf\n    os.environ['ROS_LOG_FILENAME'] = log_filename\n    if config_file.endswith(('.yaml', '.yml')):\n        with open(config_file) as f:\n            dict_conf = yaml.safe_load(f)\n        dict_conf.setdefault('version', 1)\n        logging.config.dictConfig(dict_conf)\n    else:\n        # #3625: disabling_existing_loggers=False\n        logging.config.fileConfig(config_file, disable_existing_loggers=False)\n\n    return log_filename\n\n\ndef makedirs_with_parent_perms(p):\n    \"\"\"\n    Create the directory using the permissions of the nearest\n    (existing) parent directory. This is useful for logging, where a\n    root process sometimes has to log in the user's space.\n    :param p: directory to create, ``str``\n    \"\"\"    \n    p = os.path.abspath(p)\n    parent = os.path.dirname(p)\n    # recurse upwards, checking to make sure we haven't reached the\n    # top\n    if not os.path.exists(p) and p and parent != p:\n        makedirs_with_parent_perms(parent)\n        s = os.stat(parent)\n        os.mkdir(p)\n\n        # if perms of new dir don't match, set anew\n        s2 = os.stat(p)\n        if s.st_uid != s2.st_uid or s.st_gid != s2.st_gid:\n            os.chown(p, s.st_uid, s.st_gid)\n        if s.st_mode != s2.st_mode:\n            os.chmod(p, s.st_mode)    \n\n_logging_to_rospy_names = {\n    'DEBUG': ('DEBUG', '\\033[32m'),\n    'INFO': ('INFO', None),\n    'WARNING': ('WARN', '\\033[33m'),\n    'ERROR': ('ERROR', '\\033[31m'),\n    'CRITICAL': ('FATAL', '\\033[31m')\n}\n_color_reset = '\\033[0m'\n_defaultFormatter = logging.Formatter()\n\nclass RosStreamHandler(logging.Handler):\n    def __init__(self, colorize=True, stdout=None, stderr=None):\n        super(RosStreamHandler, self).__init__()\n        self._stdout = stdout or sys.stdout\n        self._stderr = stderr or sys.stderr\n        self._colorize = colorize\n        try:\n            from rospy.rostime import get_time, is_wallclock\n            self._get_time = get_time\n            self._is_wallclock = is_wallclock\n        except ImportError:\n            self._get_time = None\n            self._is_wallclock = None\n\n    def emit(self, record):\n        level, color = _logging_to_rospy_names[record.levelname]\n        record_message = _defaultFormatter.format(record)\n        msg = os.environ.get(\n            'ROSCONSOLE_FORMAT', '[${severity}] [${time}]: ${message}')\n        msg = msg.replace('${severity}', level)\n        msg = msg.replace('${message}', str(record_message))\n        msg = msg.replace('${walltime}', '%f' % time.time())\n        msg = msg.replace('${thread}', str(record.thread))\n        msg = msg.replace('${logger}', str(record.name))\n        msg = msg.replace('${file}', str(record.pathname))\n        msg = msg.replace('${line}', str(record.lineno))\n        msg = msg.replace('${function}', str(record.funcName))\n        try:\n            from rospy import get_name\n            node_name = get_name()\n        except ImportError:\n            node_name = '<unknown_node_name>'\n        msg = msg.replace('${node}', node_name)\n        time_str = '%f' % time.time()\n        if self._get_time is not None and not self._is_wallclock():\n            time_str += ', %f' % self._get_time()\n        msg = msg.replace('${time}', time_str)\n        msg += '\\n'\n        if record.levelno < logging.WARNING:\n            self._write(self._stdout, msg, color)\n        else:\n            self._write(self._stderr, msg, color)\n\n    def _write(self, fd, msg, color):\n        if self._colorize and color and hasattr(fd, 'isatty') and fd.isatty():\n            msg = color + msg + _color_reset\n        fd.write(msg)\n", "path": "tools/rosgraph/src/rosgraph/roslogging.py"}]}