mit neuen venv und exe-Files
This commit is contained in:
351
venv3_12/Lib/site-packages/gevent/_util.py
Normal file
351
venv3_12/Lib/site-packages/gevent/_util.py
Normal file
@@ -0,0 +1,351 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
internal gevent utilities, not for external use.
|
||||
"""
|
||||
|
||||
# Be very careful not to import anything that would cause issues with
|
||||
# monkey-patching.
|
||||
|
||||
from __future__ import print_function, absolute_import, division
|
||||
|
||||
from gevent._compat import iteritems
|
||||
|
||||
|
||||
class _NONE(object):
|
||||
"""
|
||||
A special object you must never pass to any gevent API.
|
||||
Used as a marker object for keyword arguments that cannot have the
|
||||
builtin None (because that might be a valid value).
|
||||
"""
|
||||
__slots__ = ()
|
||||
|
||||
def __repr__(self):
|
||||
return '<default value>'
|
||||
|
||||
_NONE = _NONE()
|
||||
|
||||
WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__qualname__', '__doc__',
|
||||
'__annotations__')
|
||||
WRAPPER_UPDATES = ('__dict__',)
|
||||
def update_wrapper(wrapper,
|
||||
wrapped,
|
||||
assigned=WRAPPER_ASSIGNMENTS,
|
||||
updated=WRAPPER_UPDATES):
|
||||
"""
|
||||
Based on code from the standard library ``functools``, but
|
||||
doesn't perform any of the troublesome imports.
|
||||
|
||||
functools imports RLock from _thread for purposes of the
|
||||
``lru_cache``, making it problematic to use from gevent.
|
||||
|
||||
The other imports are somewhat heavy: abc, collections, types.
|
||||
"""
|
||||
for attr in assigned:
|
||||
try:
|
||||
value = getattr(wrapped, attr)
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
setattr(wrapper, attr, value)
|
||||
for attr in updated:
|
||||
getattr(wrapper, attr).update(getattr(wrapped, attr, {}))
|
||||
# Issue #17482: set __wrapped__ last so we don't inadvertently copy it
|
||||
# from the wrapped function when updating __dict__
|
||||
wrapper.__wrapped__ = wrapped
|
||||
# Return the wrapper so this can be used as a decorator via partial()
|
||||
return wrapper
|
||||
|
||||
|
||||
def copy_globals(source,
|
||||
globs,
|
||||
only_names=None,
|
||||
ignore_missing_names=False,
|
||||
names_to_ignore=(),
|
||||
dunder_names_to_keep=('__implements__', '__all__', '__imports__'),
|
||||
cleanup_globs=True):
|
||||
"""
|
||||
Copy attributes defined in ``source.__dict__`` to the dictionary
|
||||
in globs (which should be the caller's :func:`globals`).
|
||||
|
||||
Names that start with ``__`` are ignored (unless they are in
|
||||
*dunder_names_to_keep*). Anything found in *names_to_ignore* is
|
||||
also ignored.
|
||||
|
||||
If *only_names* is given, only those attributes will be
|
||||
considered. In this case, *ignore_missing_names* says whether or
|
||||
not to raise an :exc:`AttributeError` if one of those names can't
|
||||
be found.
|
||||
|
||||
If *cleanup_globs* has a true value, then common things imported but
|
||||
not used at runtime are removed, including this function.
|
||||
|
||||
Returns a list of the names copied; this should be assigned to ``__imports__``.
|
||||
"""
|
||||
if only_names:
|
||||
if ignore_missing_names:
|
||||
items = ((k, getattr(source, k, _NONE)) for k in only_names)
|
||||
else:
|
||||
items = ((k, getattr(source, k)) for k in only_names)
|
||||
else:
|
||||
items = iteritems(source.__dict__)
|
||||
|
||||
copied = []
|
||||
for key, value in items:
|
||||
if value is _NONE:
|
||||
continue
|
||||
if key in names_to_ignore:
|
||||
continue
|
||||
if key.startswith("__") and key not in dunder_names_to_keep:
|
||||
continue
|
||||
globs[key] = value
|
||||
copied.append(key)
|
||||
|
||||
if cleanup_globs:
|
||||
if 'copy_globals' in globs:
|
||||
del globs['copy_globals']
|
||||
|
||||
return copied
|
||||
|
||||
def import_c_accel(globs, cname):
|
||||
"""
|
||||
Import the C-accelerator for the *cname*
|
||||
and copy its globals.
|
||||
|
||||
The *cname* should be hardcoded to match the expected
|
||||
C accelerator module.
|
||||
|
||||
Unless PURE_PYTHON is set (in the environment or automatically
|
||||
on PyPy), then the C-accelerator is required.
|
||||
"""
|
||||
if not cname.startswith('gevent._gevent_c'):
|
||||
# Old module code that hasn't been updated yet.
|
||||
cname = cname.replace('gevent._',
|
||||
'gevent._gevent_c')
|
||||
|
||||
name = globs.get('__name__')
|
||||
|
||||
if not name or name == cname:
|
||||
# Do nothing if we're being exec'd as a file (no name)
|
||||
# or we're running from the C extension
|
||||
return
|
||||
|
||||
|
||||
from gevent._compat import PURE_PYTHON
|
||||
if PURE_PYTHON:
|
||||
return
|
||||
|
||||
import importlib
|
||||
import warnings
|
||||
with warnings.catch_warnings():
|
||||
# Python 3.7 likes to produce
|
||||
# "ImportWarning: can't resolve
|
||||
# package from __spec__ or __package__, falling back on
|
||||
# __name__ and __path__"
|
||||
# when we load cython compiled files. This is probably a bug in
|
||||
# Cython, but it doesn't seem to have any consequences, it's
|
||||
# just annoying to see and can mess up our unittests.
|
||||
warnings.simplefilter('ignore', ImportWarning)
|
||||
mod = importlib.import_module(cname)
|
||||
|
||||
# By adopting the entire __dict__, we get a more accurate
|
||||
# __file__ and module repr, plus we don't leak any imported
|
||||
# things we no longer need.
|
||||
globs.clear()
|
||||
globs.update(mod.__dict__)
|
||||
|
||||
if 'import_c_accel' in globs:
|
||||
del globs['import_c_accel']
|
||||
|
||||
|
||||
class Lazy(object):
|
||||
"""
|
||||
A non-data descriptor used just like @property. The
|
||||
difference is the function value is assigned to the instance
|
||||
dict the first time it is accessed and then the function is never
|
||||
called again.
|
||||
|
||||
Contrast with `readproperty`.
|
||||
"""
|
||||
def __init__(self, func):
|
||||
self.data = (func, func.__name__)
|
||||
update_wrapper(self, func)
|
||||
|
||||
def __get__(self, inst, class_):
|
||||
if inst is None:
|
||||
return self
|
||||
|
||||
func, name = self.data
|
||||
value = func(inst)
|
||||
inst.__dict__[name] = value
|
||||
return value
|
||||
|
||||
class readproperty(object):
|
||||
"""
|
||||
A non-data descriptor similar to :class:`property`.
|
||||
|
||||
The difference is that the property can be assigned to directly,
|
||||
without invoking a setter function. When the property is assigned
|
||||
to, it is cached in the instance and the function is not called on
|
||||
that instance again.
|
||||
|
||||
Contrast with `Lazy`, which caches the result of the function in the
|
||||
instance the first time it is called and never calls the function on that
|
||||
instance again.
|
||||
"""
|
||||
|
||||
def __init__(self, func):
|
||||
self.func = func
|
||||
update_wrapper(self, func)
|
||||
|
||||
def __get__(self, inst, class_):
|
||||
if inst is None:
|
||||
return self
|
||||
|
||||
return self.func(inst)
|
||||
|
||||
class LazyOnClass(object):
|
||||
"""
|
||||
Similar to `Lazy`, but stores the value in the class.
|
||||
|
||||
This is useful when the getter is expensive and conceptually
|
||||
a shared class value, but we don't want import-time side-effects
|
||||
such as expensive imports because it may not always be used.
|
||||
|
||||
Probably doesn't mix well with inheritance?
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def lazy(cls, cls_dict, func):
|
||||
"Put a LazyOnClass object in *cls_dict* with the same name as *func*"
|
||||
cls_dict[func.__name__] = cls(func)
|
||||
|
||||
def __init__(self, func, name=None):
|
||||
self.name = name or func.__name__
|
||||
self.func = func
|
||||
|
||||
def __get__(self, inst, klass):
|
||||
if inst is None: # pragma: no cover
|
||||
return self
|
||||
|
||||
val = self.func(inst)
|
||||
setattr(klass, self.name, val)
|
||||
return val
|
||||
|
||||
|
||||
def gmctime():
|
||||
"""
|
||||
Returns the current time as a string in RFC3339 format.
|
||||
"""
|
||||
import time
|
||||
return time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())
|
||||
|
||||
|
||||
###
|
||||
# Release automation.
|
||||
#
|
||||
# Most of this is to integrate zest.releaser with towncrier. There is
|
||||
# a plugin package that can do the same:
|
||||
# https://github.com/collective/zestreleaser.towncrier
|
||||
###
|
||||
|
||||
def prereleaser_middle(data): # pragma: no cover
|
||||
"""
|
||||
zest.releaser prerelease middle hook for gevent.
|
||||
|
||||
The prerelease step:
|
||||
|
||||
asks you for a version number
|
||||
updates the setup.py or version.txt and the
|
||||
CHANGES/HISTORY/CHANGELOG file (with either
|
||||
this new version
|
||||
number and offers to commit those changes to git
|
||||
|
||||
The middle hook:
|
||||
|
||||
All data dictionary items are available and some questions
|
||||
(like new version number) have been asked.
|
||||
No filesystem changes have been made yet.
|
||||
|
||||
It is our job to finish up the filesystem changes needed, including:
|
||||
|
||||
- Calling towncrier to handle CHANGES.rst
|
||||
- Add the version number to ``versionadded``, ``versionchanged`` and
|
||||
``deprecated`` directives in Python source.
|
||||
"""
|
||||
if data['name'] != 'gevent':
|
||||
# We are specified in ``setup.cfg``, not ``setup.py``, so we do not
|
||||
# come into play for other projects, only this one. We shouldn't
|
||||
# need this check, but there it is.
|
||||
return
|
||||
|
||||
import re
|
||||
import os
|
||||
import subprocess
|
||||
from gevent.testing import modules
|
||||
|
||||
new_version = data['new_version']
|
||||
|
||||
# Generate CHANGES.rst, remove old news entries.
|
||||
subprocess.check_call([
|
||||
'towncrier',
|
||||
'build',
|
||||
'--version', data['new_version'],
|
||||
'--yes'
|
||||
])
|
||||
|
||||
data['update_history'] = False # Because towncrier already did.
|
||||
|
||||
# But unstage it; we want it to show in the diff zest.releaser will do
|
||||
subprocess.check_call([
|
||||
'git',
|
||||
'restore',
|
||||
'--staged',
|
||||
'CHANGES.rst',
|
||||
])
|
||||
|
||||
# Put the version number in source files.
|
||||
regex = re.compile(b'.. (versionchanged|versionadded|deprecated):: NEXT')
|
||||
if not isinstance(new_version, bytes):
|
||||
new_version_bytes = new_version.encode('ascii')
|
||||
else:
|
||||
new_version_bytes = new_version
|
||||
new_version_bytes = new_version.encode('ascii')
|
||||
replacement = br'.. \1:: %s' % (new_version_bytes,)
|
||||
# TODO: This should also look in the docs/ directory at
|
||||
# *.rst
|
||||
for path, _ in modules.walk_modules(
|
||||
# Start here
|
||||
basedir=os.path.join(data['reporoot'], 'src', 'gevent'),
|
||||
# Include sub-dirs
|
||||
recursive=True,
|
||||
# Include tests
|
||||
include_tests=True,
|
||||
# and other things usually excluded
|
||||
excluded_modules=(),
|
||||
# Don't return build binaries
|
||||
include_so=False,
|
||||
# Don't try to import things; we want all files.
|
||||
check_optional=False,
|
||||
):
|
||||
with open(path, 'rb') as f:
|
||||
contents = f.read()
|
||||
new_contents, count = regex.subn(replacement, contents)
|
||||
if count:
|
||||
print("Replaced version NEXT in", path)
|
||||
with open(path, 'wb') as f:
|
||||
f.write(new_contents)
|
||||
|
||||
def postreleaser_before(data): # pragma: no cover
|
||||
"""
|
||||
Prevents zest.releaser from modifying the CHANGES.rst to add the
|
||||
'no changes yet' section; towncrier is in charge of CHANGES.rst.
|
||||
|
||||
Needs zest.releaser 6.15.0.
|
||||
"""
|
||||
if data['name'] != 'gevent':
|
||||
# We are specified in ``setup.cfg``, not ``setup.py``, so we do not
|
||||
# come into play for other projects, only this one. We shouldn't
|
||||
# need this check, but there it is.
|
||||
return
|
||||
|
||||
data['update_history'] = False
|
||||
Reference in New Issue
Block a user