%global _empty_manifest_terminate_build 0 Name: python-opentracing-instrumentation Version: 3.3.1 Release: 1 Summary: Tracing Instrumentation using OpenTracing API (http://opentracing.io) License: MIT URL: https://github.com/uber-common/opentracing-python-instrumentation Source0: https://mirrors.nju.edu.cn/pypi/web/packages/83/91/03713e8c173d4792cb9dfac9411a739ad64f71f00de44d27b2f9a2e42fcb/opentracing_instrumentation-3.3.1.tar.gz BuildArch: noarch Requires: python3-future Requires: python3-wrapt Requires: python3-tornado Requires: python3-contextlib2 Requires: python3-opentracing Requires: python3-six Requires: python3-boto3 Requires: python3-botocore Requires: python3-celery Requires: python3-doubles Requires: python3-flake8 Requires: python3-flake8-quotes Requires: python3-mock Requires: python3-moto Requires: python3-psycopg2-binary Requires: python3-sqlalchemy Requires: python3-pytest Requires: python3-pytest-cov Requires: python3-pytest-localserver Requires: python3-pytest-mock Requires: python3-pytest-tornado Requires: python3-basictracer Requires: python3-redis Requires: python3-Sphinx Requires: python3-sphinx-rtd-theme Requires: python3-testfixtures Requires: python3-MySQL-python %description [![PyPI version][pypi-img]][pypi] [![Python versions][pyver-img]][pypi] [![Pypi Downloads][pydl-img]][pypi] [![Build Status][ci-img]][ci] [![Coverage Status][cov-img]][cov] # opentracing-python-instrumentation A collection of instrumentation tools to enable tracing with [OpenTracing API](http://opentracing.io). ## Module Make sure you are running recent enough versions of `pip` and `setuptools`, e.g. before installing your project requirements execute this: ``` pip install --upgrade "setuptools>=29" "pip>=9" ``` The module name is `opentracing_instrumentation`. ## What's inside ### Supported client frameworks The following libraries are instrumented for tracing in this module: * [boto3](https://github.com/boto/boto3) — AWS SDK for Python * [Celery](https://github.com/celery/celery) — Distributed Task Queue * `urllib2` * `requests` * `SQLAlchemy` * `MySQLdb` * `psycopg2` * Tornado HTTP client * `redis` #### Limitations For some operations, `Boto3` uses `ThreadPoolExecutor` under the hood. So, in order to make it thread-safe, the instrumentation is implemented using `span_in_stack_context()` which [forces you](https://github.com/uber-common/opentracing-python-instrumentation#in-process-context-propagation) to use `TornadoScopeManager`. ### Server instrumentation For inbound requests a helper function `before_request` is provided for creating middleware for frameworks like Flask and uWSGI. ### Manual instrumentation Finally, a `@traced_function` decorator is provided for manual instrumentation. ### In-process Context Propagation As part of the OpenTracing 2.0 API, in-process `Span` propagation happens through the newly defined [ScopeManager](https://opentracing-python.readthedocs.io/en/latest/api.html#scope-managers) interface. However, the existing functionality has been kept to provide backwards compatibility and ease code migration: `span_in_context()` implements context propagation using the current `opentracing.tracer.scope_manager`, expected to be a thread-local based `ScopeManager`, such as `opentracing.scope_managers.ThreadLocalScopeManager`. `span_in_stack_context()` implements context propagation for Tornado applications using the current `opentracing.tracer.scope_manager` too, expected to be an instance of `opentracing.scope_managers.tornado.TornadoScopeManager`. `get_current_span()` returns the currently active `Span`, if any. Direct access to the `request_context` module as well as usage of `RequestContext` and `RequestContextManager` have been **fully** deprecated, as they do not integrate with the new OpenTracing 2.0 API. Using them along `get_current_span()` is guaranteed to work, but it is **highly** recommended to switch to the previously mentioned functions. ## Usage This library provides two types of instrumentation, explicit instrumentation for server endpoints, and implicit instrumentation for client call sites. Server endpoints are instrumented by creating a middleware class that: 1. initializes the specific tracer implementation 2. wraps incoming request handlers into a method that reads the incoming tracing info from the request and creates a new tracing Span Client call sites are instrumented implicitly by executing a set of available `client_hooks` that monkey-patch some API points in several common libraries like `SQLAlchemy`, `urllib2`, Tornado Async HTTP Client. The initialization of those hooks is usually also done from the middleware class's `__init__` method. There is a client-server example using this library with Flask instrumentation from opentracing-contrib: https://github.com/opentracing-contrib/python-flask/tree/master/example. Here's an example of a middleware for [Clay framework](https://github.com/uber/clay): ```python from opentracing_instrumentation import span_in_context from opentracing_instrumentation.http_server import before_request from opentracing_instrumentation.http_server import WSGIRequestWrapper from opentracing_instrumentation.client_hooks import install_all_patches class TracerMiddleware(object): def __init__(self, app, wsgi_app): self.wsgi_app = wsgi_app self.service_name = app.name CONFIG.app_name = self.service_name CONFIG.caller_name_headers.append('X-Uber-Source') CONFIG.callee_endpoint_headers.append('X-Uber-Endpoint') install_all_patches() self.wsgi_app = create_wsgi_middleware(wsgi_app) self.init_tracer() def __call__(self, environ, start_response): return self.wsgi_app(environ, start_response) def init_tracer(self): # code specific to your tracer implementation pass def create_wsgi_middleware(other_wsgi, tracer=None): """ Create a wrapper middleware for another WSGI response handler. If tracer is not passed in, 'opentracing.tracer' is used. """ def wsgi_tracing_middleware(environ, start_response): # TODO find out if the route can be retrieved from somewhere request = WSGIRequestWrapper.from_wsgi_environ(environ) span = before_request(request=request, tracer=tracer) # Wrapper around the real start_response object to log # additional information to opentracing Span def start_response_wrapper(status, response_headers, exc_info=None): if exc_info is not None: span.set_tag('error', str(exc_info)) span.finish() return start_response(status, response_headers) with span_in_context(span): return other_wsgi(environ, start_response_wrapper) return wsgi_tracing_middleware ``` And here's an example for middleware in Tornado-based app: ```python import opentracing from opentracing.scope_managers.tornado import TornadoScopeManager from opentracing_instrumentation import span_in_stack_context, http_server opentracing.tracer = MyOpenTracingTracer(scope_manager=TornadoScopeManager()) class TracerMiddleware(object): def __init__(self): # perform initialization similar to above, including installing # the client_hooks @gen.coroutine def __call__(self, request, handler, next_mw): request_wrapper = http_server.TornadoRequestWrapper(request=request) span = http_server.before_request(request=request_wrapper) @gen.coroutine def next_middleware_with_span(): yield next_mw() yield run_coroutine_with_span(span=span, func=next_middleware_with_span) span.finish() def run_coroutine_with_span(span, func, *args, **kwargs): """Wrap the execution of a Tornado coroutine func in a tracing span. This makes the span available through the get_current_span() function. :param span: The tracing span to expose. :param func: Co-routine to execute in the scope of tracing span. :param args: Positional args to func, if any. :param kwargs: Keyword args to func, if any. """ with span_in_stack_context(span): return func(*args, **kwargs) ``` ### Customization For the `requests` library, in case you want to set custom tags to spans depending on content or some metadata of responses, you can set `response_handler_hook`. The hook must be a method with a signature `(response, span)`, where `response` and `span` are positional arguments, so you can use different names for them if needed. ```python from opentracing_instrumentation.client_hooks.requests import patcher def hook(response, span): if not response.ok: span.set_tag('error', 'true') patcher.set_response_handler_hook(hook) ``` If you have issues with getting the parent span, it is possible to override default function that retrieves parent span. ```python from opentracing_instrumentation.client_hooks import install_all_patches, set_current_span_func set_current_span_func(my_custom_extractor_func) install_all_patches() ``` ## Development `PostgreSQL`, `RabbitMQ`, `Redis`, and `DynamoDB` are required for certain tests. ```bash docker-compose up -d ``` To prepare a development environment please execute the following commands. ```bash virtualenv env source env/bin/activate make bootstrap make test ``` You can use [tox](https://tox.readthedocs.io) to run tests as well. ```bash tox ``` [ci-img]: https://travis-ci.org/uber-common/opentracing-python-instrumentation.svg?branch=master [ci]: https://travis-ci.org/uber-common/opentracing-python-instrumentation [pypi-img]: https://img.shields.io/pypi/v/opentracing_instrumentation.svg [pypi]: https://pypi.python.org/pypi/opentracing_instrumentation [cov-img]: https://coveralls.io/repos/github/uber-common/opentracing-python-instrumentation/badge.svg [cov]: https://coveralls.io/github/uber-common/opentracing-python-instrumentation [pyver-img]: https://img.shields.io/pypi/pyversions/opentracing-instrumentation.svg [pydl-img]: https://img.shields.io/pypi/dm/opentracing-instrumentation.svg %package -n python3-opentracing-instrumentation Summary: Tracing Instrumentation using OpenTracing API (http://opentracing.io) Provides: python-opentracing-instrumentation BuildRequires: python3-devel BuildRequires: python3-setuptools BuildRequires: python3-pip %description -n python3-opentracing-instrumentation [![PyPI version][pypi-img]][pypi] [![Python versions][pyver-img]][pypi] [![Pypi Downloads][pydl-img]][pypi] [![Build Status][ci-img]][ci] [![Coverage Status][cov-img]][cov] # opentracing-python-instrumentation A collection of instrumentation tools to enable tracing with [OpenTracing API](http://opentracing.io). ## Module Make sure you are running recent enough versions of `pip` and `setuptools`, e.g. before installing your project requirements execute this: ``` pip install --upgrade "setuptools>=29" "pip>=9" ``` The module name is `opentracing_instrumentation`. ## What's inside ### Supported client frameworks The following libraries are instrumented for tracing in this module: * [boto3](https://github.com/boto/boto3) — AWS SDK for Python * [Celery](https://github.com/celery/celery) — Distributed Task Queue * `urllib2` * `requests` * `SQLAlchemy` * `MySQLdb` * `psycopg2` * Tornado HTTP client * `redis` #### Limitations For some operations, `Boto3` uses `ThreadPoolExecutor` under the hood. So, in order to make it thread-safe, the instrumentation is implemented using `span_in_stack_context()` which [forces you](https://github.com/uber-common/opentracing-python-instrumentation#in-process-context-propagation) to use `TornadoScopeManager`. ### Server instrumentation For inbound requests a helper function `before_request` is provided for creating middleware for frameworks like Flask and uWSGI. ### Manual instrumentation Finally, a `@traced_function` decorator is provided for manual instrumentation. ### In-process Context Propagation As part of the OpenTracing 2.0 API, in-process `Span` propagation happens through the newly defined [ScopeManager](https://opentracing-python.readthedocs.io/en/latest/api.html#scope-managers) interface. However, the existing functionality has been kept to provide backwards compatibility and ease code migration: `span_in_context()` implements context propagation using the current `opentracing.tracer.scope_manager`, expected to be a thread-local based `ScopeManager`, such as `opentracing.scope_managers.ThreadLocalScopeManager`. `span_in_stack_context()` implements context propagation for Tornado applications using the current `opentracing.tracer.scope_manager` too, expected to be an instance of `opentracing.scope_managers.tornado.TornadoScopeManager`. `get_current_span()` returns the currently active `Span`, if any. Direct access to the `request_context` module as well as usage of `RequestContext` and `RequestContextManager` have been **fully** deprecated, as they do not integrate with the new OpenTracing 2.0 API. Using them along `get_current_span()` is guaranteed to work, but it is **highly** recommended to switch to the previously mentioned functions. ## Usage This library provides two types of instrumentation, explicit instrumentation for server endpoints, and implicit instrumentation for client call sites. Server endpoints are instrumented by creating a middleware class that: 1. initializes the specific tracer implementation 2. wraps incoming request handlers into a method that reads the incoming tracing info from the request and creates a new tracing Span Client call sites are instrumented implicitly by executing a set of available `client_hooks` that monkey-patch some API points in several common libraries like `SQLAlchemy`, `urllib2`, Tornado Async HTTP Client. The initialization of those hooks is usually also done from the middleware class's `__init__` method. There is a client-server example using this library with Flask instrumentation from opentracing-contrib: https://github.com/opentracing-contrib/python-flask/tree/master/example. Here's an example of a middleware for [Clay framework](https://github.com/uber/clay): ```python from opentracing_instrumentation import span_in_context from opentracing_instrumentation.http_server import before_request from opentracing_instrumentation.http_server import WSGIRequestWrapper from opentracing_instrumentation.client_hooks import install_all_patches class TracerMiddleware(object): def __init__(self, app, wsgi_app): self.wsgi_app = wsgi_app self.service_name = app.name CONFIG.app_name = self.service_name CONFIG.caller_name_headers.append('X-Uber-Source') CONFIG.callee_endpoint_headers.append('X-Uber-Endpoint') install_all_patches() self.wsgi_app = create_wsgi_middleware(wsgi_app) self.init_tracer() def __call__(self, environ, start_response): return self.wsgi_app(environ, start_response) def init_tracer(self): # code specific to your tracer implementation pass def create_wsgi_middleware(other_wsgi, tracer=None): """ Create a wrapper middleware for another WSGI response handler. If tracer is not passed in, 'opentracing.tracer' is used. """ def wsgi_tracing_middleware(environ, start_response): # TODO find out if the route can be retrieved from somewhere request = WSGIRequestWrapper.from_wsgi_environ(environ) span = before_request(request=request, tracer=tracer) # Wrapper around the real start_response object to log # additional information to opentracing Span def start_response_wrapper(status, response_headers, exc_info=None): if exc_info is not None: span.set_tag('error', str(exc_info)) span.finish() return start_response(status, response_headers) with span_in_context(span): return other_wsgi(environ, start_response_wrapper) return wsgi_tracing_middleware ``` And here's an example for middleware in Tornado-based app: ```python import opentracing from opentracing.scope_managers.tornado import TornadoScopeManager from opentracing_instrumentation import span_in_stack_context, http_server opentracing.tracer = MyOpenTracingTracer(scope_manager=TornadoScopeManager()) class TracerMiddleware(object): def __init__(self): # perform initialization similar to above, including installing # the client_hooks @gen.coroutine def __call__(self, request, handler, next_mw): request_wrapper = http_server.TornadoRequestWrapper(request=request) span = http_server.before_request(request=request_wrapper) @gen.coroutine def next_middleware_with_span(): yield next_mw() yield run_coroutine_with_span(span=span, func=next_middleware_with_span) span.finish() def run_coroutine_with_span(span, func, *args, **kwargs): """Wrap the execution of a Tornado coroutine func in a tracing span. This makes the span available through the get_current_span() function. :param span: The tracing span to expose. :param func: Co-routine to execute in the scope of tracing span. :param args: Positional args to func, if any. :param kwargs: Keyword args to func, if any. """ with span_in_stack_context(span): return func(*args, **kwargs) ``` ### Customization For the `requests` library, in case you want to set custom tags to spans depending on content or some metadata of responses, you can set `response_handler_hook`. The hook must be a method with a signature `(response, span)`, where `response` and `span` are positional arguments, so you can use different names for them if needed. ```python from opentracing_instrumentation.client_hooks.requests import patcher def hook(response, span): if not response.ok: span.set_tag('error', 'true') patcher.set_response_handler_hook(hook) ``` If you have issues with getting the parent span, it is possible to override default function that retrieves parent span. ```python from opentracing_instrumentation.client_hooks import install_all_patches, set_current_span_func set_current_span_func(my_custom_extractor_func) install_all_patches() ``` ## Development `PostgreSQL`, `RabbitMQ`, `Redis`, and `DynamoDB` are required for certain tests. ```bash docker-compose up -d ``` To prepare a development environment please execute the following commands. ```bash virtualenv env source env/bin/activate make bootstrap make test ``` You can use [tox](https://tox.readthedocs.io) to run tests as well. ```bash tox ``` [ci-img]: https://travis-ci.org/uber-common/opentracing-python-instrumentation.svg?branch=master [ci]: https://travis-ci.org/uber-common/opentracing-python-instrumentation [pypi-img]: https://img.shields.io/pypi/v/opentracing_instrumentation.svg [pypi]: https://pypi.python.org/pypi/opentracing_instrumentation [cov-img]: https://coveralls.io/repos/github/uber-common/opentracing-python-instrumentation/badge.svg [cov]: https://coveralls.io/github/uber-common/opentracing-python-instrumentation [pyver-img]: https://img.shields.io/pypi/pyversions/opentracing-instrumentation.svg [pydl-img]: https://img.shields.io/pypi/dm/opentracing-instrumentation.svg %package help Summary: Development documents and examples for opentracing-instrumentation Provides: python3-opentracing-instrumentation-doc %description help [![PyPI version][pypi-img]][pypi] [![Python versions][pyver-img]][pypi] [![Pypi Downloads][pydl-img]][pypi] [![Build Status][ci-img]][ci] [![Coverage Status][cov-img]][cov] # opentracing-python-instrumentation A collection of instrumentation tools to enable tracing with [OpenTracing API](http://opentracing.io). ## Module Make sure you are running recent enough versions of `pip` and `setuptools`, e.g. before installing your project requirements execute this: ``` pip install --upgrade "setuptools>=29" "pip>=9" ``` The module name is `opentracing_instrumentation`. ## What's inside ### Supported client frameworks The following libraries are instrumented for tracing in this module: * [boto3](https://github.com/boto/boto3) — AWS SDK for Python * [Celery](https://github.com/celery/celery) — Distributed Task Queue * `urllib2` * `requests` * `SQLAlchemy` * `MySQLdb` * `psycopg2` * Tornado HTTP client * `redis` #### Limitations For some operations, `Boto3` uses `ThreadPoolExecutor` under the hood. So, in order to make it thread-safe, the instrumentation is implemented using `span_in_stack_context()` which [forces you](https://github.com/uber-common/opentracing-python-instrumentation#in-process-context-propagation) to use `TornadoScopeManager`. ### Server instrumentation For inbound requests a helper function `before_request` is provided for creating middleware for frameworks like Flask and uWSGI. ### Manual instrumentation Finally, a `@traced_function` decorator is provided for manual instrumentation. ### In-process Context Propagation As part of the OpenTracing 2.0 API, in-process `Span` propagation happens through the newly defined [ScopeManager](https://opentracing-python.readthedocs.io/en/latest/api.html#scope-managers) interface. However, the existing functionality has been kept to provide backwards compatibility and ease code migration: `span_in_context()` implements context propagation using the current `opentracing.tracer.scope_manager`, expected to be a thread-local based `ScopeManager`, such as `opentracing.scope_managers.ThreadLocalScopeManager`. `span_in_stack_context()` implements context propagation for Tornado applications using the current `opentracing.tracer.scope_manager` too, expected to be an instance of `opentracing.scope_managers.tornado.TornadoScopeManager`. `get_current_span()` returns the currently active `Span`, if any. Direct access to the `request_context` module as well as usage of `RequestContext` and `RequestContextManager` have been **fully** deprecated, as they do not integrate with the new OpenTracing 2.0 API. Using them along `get_current_span()` is guaranteed to work, but it is **highly** recommended to switch to the previously mentioned functions. ## Usage This library provides two types of instrumentation, explicit instrumentation for server endpoints, and implicit instrumentation for client call sites. Server endpoints are instrumented by creating a middleware class that: 1. initializes the specific tracer implementation 2. wraps incoming request handlers into a method that reads the incoming tracing info from the request and creates a new tracing Span Client call sites are instrumented implicitly by executing a set of available `client_hooks` that monkey-patch some API points in several common libraries like `SQLAlchemy`, `urllib2`, Tornado Async HTTP Client. The initialization of those hooks is usually also done from the middleware class's `__init__` method. There is a client-server example using this library with Flask instrumentation from opentracing-contrib: https://github.com/opentracing-contrib/python-flask/tree/master/example. Here's an example of a middleware for [Clay framework](https://github.com/uber/clay): ```python from opentracing_instrumentation import span_in_context from opentracing_instrumentation.http_server import before_request from opentracing_instrumentation.http_server import WSGIRequestWrapper from opentracing_instrumentation.client_hooks import install_all_patches class TracerMiddleware(object): def __init__(self, app, wsgi_app): self.wsgi_app = wsgi_app self.service_name = app.name CONFIG.app_name = self.service_name CONFIG.caller_name_headers.append('X-Uber-Source') CONFIG.callee_endpoint_headers.append('X-Uber-Endpoint') install_all_patches() self.wsgi_app = create_wsgi_middleware(wsgi_app) self.init_tracer() def __call__(self, environ, start_response): return self.wsgi_app(environ, start_response) def init_tracer(self): # code specific to your tracer implementation pass def create_wsgi_middleware(other_wsgi, tracer=None): """ Create a wrapper middleware for another WSGI response handler. If tracer is not passed in, 'opentracing.tracer' is used. """ def wsgi_tracing_middleware(environ, start_response): # TODO find out if the route can be retrieved from somewhere request = WSGIRequestWrapper.from_wsgi_environ(environ) span = before_request(request=request, tracer=tracer) # Wrapper around the real start_response object to log # additional information to opentracing Span def start_response_wrapper(status, response_headers, exc_info=None): if exc_info is not None: span.set_tag('error', str(exc_info)) span.finish() return start_response(status, response_headers) with span_in_context(span): return other_wsgi(environ, start_response_wrapper) return wsgi_tracing_middleware ``` And here's an example for middleware in Tornado-based app: ```python import opentracing from opentracing.scope_managers.tornado import TornadoScopeManager from opentracing_instrumentation import span_in_stack_context, http_server opentracing.tracer = MyOpenTracingTracer(scope_manager=TornadoScopeManager()) class TracerMiddleware(object): def __init__(self): # perform initialization similar to above, including installing # the client_hooks @gen.coroutine def __call__(self, request, handler, next_mw): request_wrapper = http_server.TornadoRequestWrapper(request=request) span = http_server.before_request(request=request_wrapper) @gen.coroutine def next_middleware_with_span(): yield next_mw() yield run_coroutine_with_span(span=span, func=next_middleware_with_span) span.finish() def run_coroutine_with_span(span, func, *args, **kwargs): """Wrap the execution of a Tornado coroutine func in a tracing span. This makes the span available through the get_current_span() function. :param span: The tracing span to expose. :param func: Co-routine to execute in the scope of tracing span. :param args: Positional args to func, if any. :param kwargs: Keyword args to func, if any. """ with span_in_stack_context(span): return func(*args, **kwargs) ``` ### Customization For the `requests` library, in case you want to set custom tags to spans depending on content or some metadata of responses, you can set `response_handler_hook`. The hook must be a method with a signature `(response, span)`, where `response` and `span` are positional arguments, so you can use different names for them if needed. ```python from opentracing_instrumentation.client_hooks.requests import patcher def hook(response, span): if not response.ok: span.set_tag('error', 'true') patcher.set_response_handler_hook(hook) ``` If you have issues with getting the parent span, it is possible to override default function that retrieves parent span. ```python from opentracing_instrumentation.client_hooks import install_all_patches, set_current_span_func set_current_span_func(my_custom_extractor_func) install_all_patches() ``` ## Development `PostgreSQL`, `RabbitMQ`, `Redis`, and `DynamoDB` are required for certain tests. ```bash docker-compose up -d ``` To prepare a development environment please execute the following commands. ```bash virtualenv env source env/bin/activate make bootstrap make test ``` You can use [tox](https://tox.readthedocs.io) to run tests as well. ```bash tox ``` [ci-img]: https://travis-ci.org/uber-common/opentracing-python-instrumentation.svg?branch=master [ci]: https://travis-ci.org/uber-common/opentracing-python-instrumentation [pypi-img]: https://img.shields.io/pypi/v/opentracing_instrumentation.svg [pypi]: https://pypi.python.org/pypi/opentracing_instrumentation [cov-img]: https://coveralls.io/repos/github/uber-common/opentracing-python-instrumentation/badge.svg [cov]: https://coveralls.io/github/uber-common/opentracing-python-instrumentation [pyver-img]: https://img.shields.io/pypi/pyversions/opentracing-instrumentation.svg [pydl-img]: https://img.shields.io/pypi/dm/opentracing-instrumentation.svg %prep %autosetup -n opentracing-instrumentation-3.3.1 %build %py3_build %install %py3_install install -d -m755 %{buildroot}/%{_pkgdocdir} if [ -d doc ]; then cp -arf doc %{buildroot}/%{_pkgdocdir}; fi if [ -d docs ]; then cp -arf docs %{buildroot}/%{_pkgdocdir}; fi if [ -d example ]; then cp -arf example %{buildroot}/%{_pkgdocdir}; fi if [ -d examples ]; then cp -arf examples %{buildroot}/%{_pkgdocdir}; fi pushd %{buildroot} if [ -d usr/lib ]; then find usr/lib -type f -printf "/%h/%f\n" >> filelist.lst fi if [ -d usr/lib64 ]; then find usr/lib64 -type f -printf "/%h/%f\n" >> filelist.lst fi if [ -d usr/bin ]; then find usr/bin -type f -printf "/%h/%f\n" >> filelist.lst fi if [ -d usr/sbin ]; then find usr/sbin -type f -printf "/%h/%f\n" >> filelist.lst fi touch doclist.lst if [ -d usr/share/man ]; then find usr/share/man -type f -printf "/%h/%f.gz\n" >> doclist.lst fi popd mv %{buildroot}/filelist.lst . mv %{buildroot}/doclist.lst . %files -n python3-opentracing-instrumentation -f filelist.lst %dir %{python3_sitelib}/* %files help -f doclist.lst %{_docdir}/* %changelog * Sun Apr 23 2023 Python_Bot - 3.3.1-1 - Package Spec generated