not-pegasus commited on
Commit
568aa87
·
verified ·
1 Parent(s): bddf20b

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. env/lib/python3.13/site-packages/_yaml/__init__.py +33 -0
  2. env/lib/python3.13/site-packages/_yaml/__pycache__/__init__.cpython-313.pyc +0 -0
  3. env/lib/python3.13/site-packages/anyio-4.12.0.dist-info/METADATA +96 -0
  4. env/lib/python3.13/site-packages/anyio-4.12.0.dist-info/top_level.txt +1 -0
  5. env/lib/python3.13/site-packages/certifi/__init__.py +4 -0
  6. env/lib/python3.13/site-packages/certifi/__main__.py +12 -0
  7. env/lib/python3.13/site-packages/certifi/__pycache__/__init__.cpython-313.pyc +0 -0
  8. env/lib/python3.13/site-packages/certifi/__pycache__/__main__.cpython-313.pyc +0 -0
  9. env/lib/python3.13/site-packages/certifi/__pycache__/core.cpython-313.pyc +0 -0
  10. env/lib/python3.13/site-packages/certifi/cacert.pem +0 -0
  11. env/lib/python3.13/site-packages/certifi/core.py +83 -0
  12. env/lib/python3.13/site-packages/certifi/py.typed +0 -0
  13. env/lib/python3.13/site-packages/click-8.3.1.dist-info/INSTALLER +1 -0
  14. env/lib/python3.13/site-packages/click-8.3.1.dist-info/METADATA +84 -0
  15. env/lib/python3.13/site-packages/click-8.3.1.dist-info/RECORD +40 -0
  16. env/lib/python3.13/site-packages/click-8.3.1.dist-info/WHEEL +4 -0
  17. env/lib/python3.13/site-packages/click-8.3.1.dist-info/licenses/LICENSE.txt +28 -0
  18. env/lib/python3.13/site-packages/filelock-3.20.0.dist-info/INSTALLER +1 -0
  19. env/lib/python3.13/site-packages/filelock-3.20.0.dist-info/METADATA +42 -0
  20. env/lib/python3.13/site-packages/filelock-3.20.0.dist-info/RECORD +24 -0
  21. env/lib/python3.13/site-packages/filelock-3.20.0.dist-info/WHEEL +4 -0
  22. env/lib/python3.13/site-packages/filelock-3.20.0.dist-info/licenses/LICENSE +24 -0
  23. env/lib/python3.13/site-packages/filelock/__init__.py +70 -0
  24. env/lib/python3.13/site-packages/filelock/__pycache__/__init__.cpython-313.pyc +0 -0
  25. env/lib/python3.13/site-packages/filelock/__pycache__/_api.cpython-313.pyc +0 -0
  26. env/lib/python3.13/site-packages/filelock/__pycache__/_error.cpython-313.pyc +0 -0
  27. env/lib/python3.13/site-packages/filelock/__pycache__/_soft.cpython-313.pyc +0 -0
  28. env/lib/python3.13/site-packages/filelock/__pycache__/_unix.cpython-313.pyc +0 -0
  29. env/lib/python3.13/site-packages/filelock/__pycache__/_util.cpython-313.pyc +0 -0
  30. env/lib/python3.13/site-packages/filelock/__pycache__/_windows.cpython-313.pyc +0 -0
  31. env/lib/python3.13/site-packages/filelock/__pycache__/asyncio.cpython-313.pyc +0 -0
  32. env/lib/python3.13/site-packages/filelock/__pycache__/version.cpython-313.pyc +0 -0
  33. env/lib/python3.13/site-packages/filelock/_api.py +403 -0
  34. env/lib/python3.13/site-packages/filelock/_error.py +30 -0
  35. env/lib/python3.13/site-packages/filelock/_soft.py +47 -0
  36. env/lib/python3.13/site-packages/filelock/_unix.py +70 -0
  37. env/lib/python3.13/site-packages/filelock/_util.py +52 -0
  38. env/lib/python3.13/site-packages/filelock/_windows.py +65 -0
  39. env/lib/python3.13/site-packages/filelock/asyncio.py +344 -0
  40. env/lib/python3.13/site-packages/filelock/py.typed +0 -0
  41. env/lib/python3.13/site-packages/filelock/version.py +34 -0
  42. env/lib/python3.13/site-packages/h11/__init__.py +62 -0
  43. env/lib/python3.13/site-packages/h11/__pycache__/__init__.cpython-313.pyc +0 -0
  44. env/lib/python3.13/site-packages/h11/__pycache__/_abnf.cpython-313.pyc +0 -0
  45. env/lib/python3.13/site-packages/h11/__pycache__/_connection.cpython-313.pyc +0 -0
  46. env/lib/python3.13/site-packages/h11/__pycache__/_events.cpython-313.pyc +0 -0
  47. env/lib/python3.13/site-packages/h11/__pycache__/_headers.cpython-313.pyc +0 -0
  48. env/lib/python3.13/site-packages/h11/__pycache__/_readers.cpython-313.pyc +0 -0
  49. env/lib/python3.13/site-packages/h11/__pycache__/_receivebuffer.cpython-313.pyc +0 -0
  50. env/lib/python3.13/site-packages/h11/__pycache__/_state.cpython-313.pyc +0 -0
env/lib/python3.13/site-packages/_yaml/__init__.py ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This is a stub package designed to roughly emulate the _yaml
2
+ # extension module, which previously existed as a standalone module
3
+ # and has been moved into the `yaml` package namespace.
4
+ # It does not perfectly mimic its old counterpart, but should get
5
+ # close enough for anyone who's relying on it even when they shouldn't.
6
+ import yaml
7
+
8
+ # in some circumstances, the yaml module we imoprted may be from a different version, so we need
9
+ # to tread carefully when poking at it here (it may not have the attributes we expect)
10
+ if not getattr(yaml, '__with_libyaml__', False):
11
+ from sys import version_info
12
+
13
+ exc = ModuleNotFoundError if version_info >= (3, 6) else ImportError
14
+ raise exc("No module named '_yaml'")
15
+ else:
16
+ from yaml._yaml import *
17
+ import warnings
18
+ warnings.warn(
19
+ 'The _yaml extension module is now located at yaml._yaml'
20
+ ' and its location is subject to change. To use the'
21
+ ' LibYAML-based parser and emitter, import from `yaml`:'
22
+ ' `from yaml import CLoader as Loader, CDumper as Dumper`.',
23
+ DeprecationWarning
24
+ )
25
+ del warnings
26
+ # Don't `del yaml` here because yaml is actually an existing
27
+ # namespace member of _yaml.
28
+
29
+ __name__ = '_yaml'
30
+ # If the module is top-level (i.e. not a part of any specific package)
31
+ # then the attribute should be set to ''.
32
+ # https://docs.python.org/3.8/library/types.html
33
+ __package__ = ''
env/lib/python3.13/site-packages/_yaml/__pycache__/__init__.cpython-313.pyc ADDED
Binary file (892 Bytes). View file
 
env/lib/python3.13/site-packages/anyio-4.12.0.dist-info/METADATA ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Metadata-Version: 2.4
2
+ Name: anyio
3
+ Version: 4.12.0
4
+ Summary: High-level concurrency and networking framework on top of asyncio or Trio
5
+ Author-email: Alex Grönholm <alex.gronholm@nextday.fi>
6
+ License-Expression: MIT
7
+ Project-URL: Documentation, https://anyio.readthedocs.io/en/latest/
8
+ Project-URL: Changelog, https://anyio.readthedocs.io/en/stable/versionhistory.html
9
+ Project-URL: Source code, https://github.com/agronholm/anyio
10
+ Project-URL: Issue tracker, https://github.com/agronholm/anyio/issues
11
+ Classifier: Development Status :: 5 - Production/Stable
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Framework :: AnyIO
14
+ Classifier: Typing :: Typed
15
+ Classifier: Programming Language :: Python
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Programming Language :: Python :: 3.14
23
+ Requires-Python: >=3.9
24
+ Description-Content-Type: text/x-rst
25
+ License-File: LICENSE
26
+ Requires-Dist: exceptiongroup>=1.0.2; python_version < "3.11"
27
+ Requires-Dist: idna>=2.8
28
+ Requires-Dist: typing_extensions>=4.5; python_version < "3.13"
29
+ Provides-Extra: trio
30
+ Requires-Dist: trio>=0.32.0; python_version >= "3.10" and extra == "trio"
31
+ Requires-Dist: trio>=0.31.0; python_version < "3.10" and extra == "trio"
32
+ Dynamic: license-file
33
+
34
+ .. image:: https://github.com/agronholm/anyio/actions/workflows/test.yml/badge.svg
35
+ :target: https://github.com/agronholm/anyio/actions/workflows/test.yml
36
+ :alt: Build Status
37
+ .. image:: https://coveralls.io/repos/github/agronholm/anyio/badge.svg?branch=master
38
+ :target: https://coveralls.io/github/agronholm/anyio?branch=master
39
+ :alt: Code Coverage
40
+ .. image:: https://readthedocs.org/projects/anyio/badge/?version=latest
41
+ :target: https://anyio.readthedocs.io/en/latest/?badge=latest
42
+ :alt: Documentation
43
+ .. image:: https://badges.gitter.im/gitterHQ/gitter.svg
44
+ :target: https://gitter.im/python-trio/AnyIO
45
+ :alt: Gitter chat
46
+
47
+ AnyIO is an asynchronous networking and concurrency library that works on top of either asyncio_ or
48
+ Trio_. It implements Trio-like `structured concurrency`_ (SC) on top of asyncio and works in harmony
49
+ with the native SC of Trio itself.
50
+
51
+ Applications and libraries written against AnyIO's API will run unmodified on either asyncio_ or
52
+ Trio_. AnyIO can also be adopted into a library or application incrementally – bit by bit, no full
53
+ refactoring necessary. It will blend in with the native libraries of your chosen backend.
54
+
55
+ To find out why you might want to use AnyIO's APIs instead of asyncio's, you can read about it
56
+ `here <https://anyio.readthedocs.io/en/stable/why.html>`_.
57
+
58
+ Documentation
59
+ -------------
60
+
61
+ View full documentation at: https://anyio.readthedocs.io/
62
+
63
+ Features
64
+ --------
65
+
66
+ AnyIO offers the following functionality:
67
+
68
+ * Task groups (nurseries_ in trio terminology)
69
+ * High-level networking (TCP, UDP and UNIX sockets)
70
+
71
+ * `Happy eyeballs`_ algorithm for TCP connections (more robust than that of asyncio on Python
72
+ 3.8)
73
+ * async/await style UDP sockets (unlike asyncio where you still have to use Transports and
74
+ Protocols)
75
+
76
+ * A versatile API for byte streams and object streams
77
+ * Inter-task synchronization and communication (locks, conditions, events, semaphores, object
78
+ streams)
79
+ * Worker threads
80
+ * Subprocesses
81
+ * Subinterpreter support for code parallelization (on Python 3.13 and later)
82
+ * Asynchronous file I/O (using worker threads)
83
+ * Signal handling
84
+ * Asynchronous version of the functools_ module
85
+
86
+ AnyIO also comes with its own pytest_ plugin which also supports asynchronous fixtures.
87
+ It even works with the popular Hypothesis_ library.
88
+
89
+ .. _asyncio: https://docs.python.org/3/library/asyncio.html
90
+ .. _Trio: https://github.com/python-trio/trio
91
+ .. _structured concurrency: https://en.wikipedia.org/wiki/Structured_concurrency
92
+ .. _nurseries: https://trio.readthedocs.io/en/stable/reference-core.html#nurseries-and-spawning
93
+ .. _Happy eyeballs: https://en.wikipedia.org/wiki/Happy_Eyeballs
94
+ .. _pytest: https://docs.pytest.org/en/latest/
95
+ .. _functools: https://docs.python.org/3/library/functools.html
96
+ .. _Hypothesis: https://hypothesis.works/
env/lib/python3.13/site-packages/anyio-4.12.0.dist-info/top_level.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ anyio
env/lib/python3.13/site-packages/certifi/__init__.py ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ from .core import contents, where
2
+
3
+ __all__ = ["contents", "where"]
4
+ __version__ = "2025.11.12"
env/lib/python3.13/site-packages/certifi/__main__.py ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import argparse
2
+
3
+ from certifi import contents, where
4
+
5
+ parser = argparse.ArgumentParser()
6
+ parser.add_argument("-c", "--contents", action="store_true")
7
+ args = parser.parse_args()
8
+
9
+ if args.contents:
10
+ print(contents())
11
+ else:
12
+ print(where())
env/lib/python3.13/site-packages/certifi/__pycache__/__init__.cpython-313.pyc ADDED
Binary file (326 Bytes). View file
 
env/lib/python3.13/site-packages/certifi/__pycache__/__main__.cpython-313.pyc ADDED
Binary file (643 Bytes). View file
 
env/lib/python3.13/site-packages/certifi/__pycache__/core.cpython-313.pyc ADDED
Binary file (2.08 kB). View file
 
env/lib/python3.13/site-packages/certifi/cacert.pem ADDED
The diff for this file is too large to render. See raw diff
 
env/lib/python3.13/site-packages/certifi/core.py ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ certifi.py
3
+ ~~~~~~~~~~
4
+
5
+ This module returns the installation location of cacert.pem or its contents.
6
+ """
7
+ import sys
8
+ import atexit
9
+
10
+ def exit_cacert_ctx() -> None:
11
+ _CACERT_CTX.__exit__(None, None, None) # type: ignore[union-attr]
12
+
13
+
14
+ if sys.version_info >= (3, 11):
15
+
16
+ from importlib.resources import as_file, files
17
+
18
+ _CACERT_CTX = None
19
+ _CACERT_PATH = None
20
+
21
+ def where() -> str:
22
+ # This is slightly terrible, but we want to delay extracting the file
23
+ # in cases where we're inside of a zipimport situation until someone
24
+ # actually calls where(), but we don't want to re-extract the file
25
+ # on every call of where(), so we'll do it once then store it in a
26
+ # global variable.
27
+ global _CACERT_CTX
28
+ global _CACERT_PATH
29
+ if _CACERT_PATH is None:
30
+ # This is slightly janky, the importlib.resources API wants you to
31
+ # manage the cleanup of this file, so it doesn't actually return a
32
+ # path, it returns a context manager that will give you the path
33
+ # when you enter it and will do any cleanup when you leave it. In
34
+ # the common case of not needing a temporary file, it will just
35
+ # return the file system location and the __exit__() is a no-op.
36
+ #
37
+ # We also have to hold onto the actual context manager, because
38
+ # it will do the cleanup whenever it gets garbage collected, so
39
+ # we will also store that at the global level as well.
40
+ _CACERT_CTX = as_file(files("certifi").joinpath("cacert.pem"))
41
+ _CACERT_PATH = str(_CACERT_CTX.__enter__())
42
+ atexit.register(exit_cacert_ctx)
43
+
44
+ return _CACERT_PATH
45
+
46
+ def contents() -> str:
47
+ return files("certifi").joinpath("cacert.pem").read_text(encoding="ascii")
48
+
49
+ else:
50
+
51
+ from importlib.resources import path as get_path, read_text
52
+
53
+ _CACERT_CTX = None
54
+ _CACERT_PATH = None
55
+
56
+ def where() -> str:
57
+ # This is slightly terrible, but we want to delay extracting the
58
+ # file in cases where we're inside of a zipimport situation until
59
+ # someone actually calls where(), but we don't want to re-extract
60
+ # the file on every call of where(), so we'll do it once then store
61
+ # it in a global variable.
62
+ global _CACERT_CTX
63
+ global _CACERT_PATH
64
+ if _CACERT_PATH is None:
65
+ # This is slightly janky, the importlib.resources API wants you
66
+ # to manage the cleanup of this file, so it doesn't actually
67
+ # return a path, it returns a context manager that will give
68
+ # you the path when you enter it and will do any cleanup when
69
+ # you leave it. In the common case of not needing a temporary
70
+ # file, it will just return the file system location and the
71
+ # __exit__() is a no-op.
72
+ #
73
+ # We also have to hold onto the actual context manager, because
74
+ # it will do the cleanup whenever it gets garbage collected, so
75
+ # we will also store that at the global level as well.
76
+ _CACERT_CTX = get_path("certifi", "cacert.pem")
77
+ _CACERT_PATH = str(_CACERT_CTX.__enter__())
78
+ atexit.register(exit_cacert_ctx)
79
+
80
+ return _CACERT_PATH
81
+
82
+ def contents() -> str:
83
+ return read_text("certifi", "cacert.pem", encoding="ascii")
env/lib/python3.13/site-packages/certifi/py.typed ADDED
File without changes
env/lib/python3.13/site-packages/click-8.3.1.dist-info/INSTALLER ADDED
@@ -0,0 +1 @@
 
 
1
+ pip
env/lib/python3.13/site-packages/click-8.3.1.dist-info/METADATA ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Metadata-Version: 2.4
2
+ Name: click
3
+ Version: 8.3.1
4
+ Summary: Composable command line interface toolkit
5
+ Maintainer-email: Pallets <contact@palletsprojects.com>
6
+ Requires-Python: >=3.10
7
+ Description-Content-Type: text/markdown
8
+ License-Expression: BSD-3-Clause
9
+ Classifier: Development Status :: 5 - Production/Stable
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Operating System :: OS Independent
12
+ Classifier: Programming Language :: Python
13
+ Classifier: Typing :: Typed
14
+ License-File: LICENSE.txt
15
+ Requires-Dist: colorama; platform_system == 'Windows'
16
+ Project-URL: Changes, https://click.palletsprojects.com/page/changes/
17
+ Project-URL: Chat, https://discord.gg/pallets
18
+ Project-URL: Documentation, https://click.palletsprojects.com/
19
+ Project-URL: Donate, https://palletsprojects.com/donate
20
+ Project-URL: Source, https://github.com/pallets/click/
21
+
22
+ <div align="center"><img src="https://raw.githubusercontent.com/pallets/click/refs/heads/stable/docs/_static/click-name.svg" alt="" height="150"></div>
23
+
24
+ # Click
25
+
26
+ Click is a Python package for creating beautiful command line interfaces
27
+ in a composable way with as little code as necessary. It's the "Command
28
+ Line Interface Creation Kit". It's highly configurable but comes with
29
+ sensible defaults out of the box.
30
+
31
+ It aims to make the process of writing command line tools quick and fun
32
+ while also preventing any frustration caused by the inability to
33
+ implement an intended CLI API.
34
+
35
+ Click in three points:
36
+
37
+ - Arbitrary nesting of commands
38
+ - Automatic help page generation
39
+ - Supports lazy loading of subcommands at runtime
40
+
41
+
42
+ ## A Simple Example
43
+
44
+ ```python
45
+ import click
46
+
47
+ @click.command()
48
+ @click.option("--count", default=1, help="Number of greetings.")
49
+ @click.option("--name", prompt="Your name", help="The person to greet.")
50
+ def hello(count, name):
51
+ """Simple program that greets NAME for a total of COUNT times."""
52
+ for _ in range(count):
53
+ click.echo(f"Hello, {name}!")
54
+
55
+ if __name__ == '__main__':
56
+ hello()
57
+ ```
58
+
59
+ ```
60
+ $ python hello.py --count=3
61
+ Your name: Click
62
+ Hello, Click!
63
+ Hello, Click!
64
+ Hello, Click!
65
+ ```
66
+
67
+
68
+ ## Donate
69
+
70
+ The Pallets organization develops and supports Click and other popular
71
+ packages. In order to grow the community of contributors and users, and
72
+ allow the maintainers to devote more time to the projects, [please
73
+ donate today][].
74
+
75
+ [please donate today]: https://palletsprojects.com/donate
76
+
77
+ ## Contributing
78
+
79
+ See our [detailed contributing documentation][contrib] for many ways to
80
+ contribute, including reporting issues, requesting features, asking or answering
81
+ questions, and making PRs.
82
+
83
+ [contrib]: https://palletsprojects.com/contributing/
84
+
env/lib/python3.13/site-packages/click-8.3.1.dist-info/RECORD ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ click-8.3.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
2
+ click-8.3.1.dist-info/METADATA,sha256=XZeBrMAE0ghTE88SjfrSDuSyNCpBPplxJR1tbwD9oZg,2621
3
+ click-8.3.1.dist-info/RECORD,,
4
+ click-8.3.1.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
5
+ click-8.3.1.dist-info/licenses/LICENSE.txt,sha256=morRBqOU6FO_4h9C9OctWSgZoigF2ZG18ydQKSkrZY0,1475
6
+ click/__init__.py,sha256=6YyS1aeyknZ0LYweWozNZy0A9nZ_11wmYIhv3cbQrYo,4473
7
+ click/__pycache__/__init__.cpython-313.pyc,,
8
+ click/__pycache__/_compat.cpython-313.pyc,,
9
+ click/__pycache__/_termui_impl.cpython-313.pyc,,
10
+ click/__pycache__/_textwrap.cpython-313.pyc,,
11
+ click/__pycache__/_utils.cpython-313.pyc,,
12
+ click/__pycache__/_winconsole.cpython-313.pyc,,
13
+ click/__pycache__/core.cpython-313.pyc,,
14
+ click/__pycache__/decorators.cpython-313.pyc,,
15
+ click/__pycache__/exceptions.cpython-313.pyc,,
16
+ click/__pycache__/formatting.cpython-313.pyc,,
17
+ click/__pycache__/globals.cpython-313.pyc,,
18
+ click/__pycache__/parser.cpython-313.pyc,,
19
+ click/__pycache__/shell_completion.cpython-313.pyc,,
20
+ click/__pycache__/termui.cpython-313.pyc,,
21
+ click/__pycache__/testing.cpython-313.pyc,,
22
+ click/__pycache__/types.cpython-313.pyc,,
23
+ click/__pycache__/utils.cpython-313.pyc,,
24
+ click/_compat.py,sha256=v3xBZkFbvA1BXPRkFfBJc6-pIwPI7345m-kQEnpVAs4,18693
25
+ click/_termui_impl.py,sha256=rgCb3On8X5A4200rA5L6i13u5iapmFer7sru57Jy6zA,27093
26
+ click/_textwrap.py,sha256=BOae0RQ6vg3FkNgSJyOoGzG1meGMxJ_ukWVZKx_v-0o,1400
27
+ click/_utils.py,sha256=kZwtTf5gMuCilJJceS2iTCvRvCY-0aN5rJq8gKw7p8g,943
28
+ click/_winconsole.py,sha256=_vxUuUaxwBhoR0vUWCNuHY8VUefiMdCIyU2SXPqoF-A,8465
29
+ click/core.py,sha256=U6Bfxt8GkjNDqyJ0HqXvluJHtyZ4sY5USAvM1Cdq7mQ,132105
30
+ click/decorators.py,sha256=5P7abhJtAQYp_KHgjUvhMv464ERwOzrv2enNknlwHyQ,18461
31
+ click/exceptions.py,sha256=8utf8w6V5hJXMnO_ic1FNrtbwuEn1NUu1aDwV8UqnG4,9954
32
+ click/formatting.py,sha256=RVfwwr0rwWNpgGr8NaHodPzkIr7_tUyVh_nDdanLMNc,9730
33
+ click/globals.py,sha256=gM-Nh6A4M0HB_SgkaF5M4ncGGMDHc_flHXu9_oh4GEU,1923
34
+ click/parser.py,sha256=Q31pH0FlQZEq-UXE_ABRzlygEfvxPTuZbWNh4xfXmzw,19010
35
+ click/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
+ click/shell_completion.py,sha256=Cc4GQUFuWpfQBa9sF5qXeeYI7n3tI_1k6ZdSn4BZbT0,20994
37
+ click/termui.py,sha256=hqCEjNndU-nzW08nRAkBaVgfZp_FdCA9KxfIWlKYaMc,31037
38
+ click/testing.py,sha256=EERbzcl1br0mW0qBS9EqkknfNfXB9WQEW0ELIpkvuSs,19102
39
+ click/types.py,sha256=ek54BNSFwPKsqtfT7jsqcc4WHui8AIFVMKM4oVZIXhc,39927
40
+ click/utils.py,sha256=gCUoewdAhA-QLBUUHxrLh4uj6m7T1WjZZMNPvR0I7YA,20257
env/lib/python3.13/site-packages/click-8.3.1.dist-info/WHEEL ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ Wheel-Version: 1.0
2
+ Generator: flit 3.12.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
env/lib/python3.13/site-packages/click-8.3.1.dist-info/licenses/LICENSE.txt ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright 2014 Pallets
2
+
3
+ Redistribution and use in source and binary forms, with or without
4
+ modification, are permitted provided that the following conditions are
5
+ met:
6
+
7
+ 1. Redistributions of source code must retain the above copyright
8
+ notice, this list of conditions and the following disclaimer.
9
+
10
+ 2. Redistributions in binary form must reproduce the above copyright
11
+ notice, this list of conditions and the following disclaimer in the
12
+ documentation and/or other materials provided with the distribution.
13
+
14
+ 3. Neither the name of the copyright holder nor the names of its
15
+ contributors may be used to endorse or promote products derived from
16
+ this software without specific prior written permission.
17
+
18
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
21
+ PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22
+ HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
24
+ TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
env/lib/python3.13/site-packages/filelock-3.20.0.dist-info/INSTALLER ADDED
@@ -0,0 +1 @@
 
 
1
+ pip
env/lib/python3.13/site-packages/filelock-3.20.0.dist-info/METADATA ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Metadata-Version: 2.4
2
+ Name: filelock
3
+ Version: 3.20.0
4
+ Summary: A platform independent file lock.
5
+ Project-URL: Documentation, https://py-filelock.readthedocs.io
6
+ Project-URL: Homepage, https://github.com/tox-dev/py-filelock
7
+ Project-URL: Source, https://github.com/tox-dev/py-filelock
8
+ Project-URL: Tracker, https://github.com/tox-dev/py-filelock/issues
9
+ Maintainer-email: Bernát Gábor <gaborjbernat@gmail.com>
10
+ License-Expression: Unlicense
11
+ License-File: LICENSE
12
+ Keywords: application,cache,directory,log,user
13
+ Classifier: Development Status :: 5 - Production/Stable
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: The Unlicense (Unlicense)
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python
18
+ Classifier: Programming Language :: Python :: 3 :: Only
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Programming Language :: Python :: 3.14
24
+ Classifier: Topic :: Internet
25
+ Classifier: Topic :: Software Development :: Libraries
26
+ Classifier: Topic :: System
27
+ Requires-Python: >=3.10
28
+ Description-Content-Type: text/markdown
29
+
30
+ # filelock
31
+
32
+ [![PyPI](https://img.shields.io/pypi/v/filelock)](https://pypi.org/project/filelock/)
33
+ [![Supported Python
34
+ versions](https://img.shields.io/pypi/pyversions/filelock.svg)](https://pypi.org/project/filelock/)
35
+ [![Documentation
36
+ status](https://readthedocs.org/projects/py-filelock/badge/?version=latest)](https://py-filelock.readthedocs.io/en/latest/?badge=latest)
37
+ [![Code style:
38
+ black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
39
+ [![Downloads](https://static.pepy.tech/badge/filelock/month)](https://pepy.tech/project/filelock)
40
+ [![check](https://github.com/tox-dev/py-filelock/actions/workflows/check.yaml/badge.svg)](https://github.com/tox-dev/py-filelock/actions/workflows/check.yaml)
41
+
42
+ For more information checkout the [official documentation](https://py-filelock.readthedocs.io/en/latest/index.html).
env/lib/python3.13/site-packages/filelock-3.20.0.dist-info/RECORD ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ filelock-3.20.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
2
+ filelock-3.20.0.dist-info/METADATA,sha256=gIghqdcbGNywxw52pN02_a9OxFqzhjA8v-9GsDWtNog,2110
3
+ filelock-3.20.0.dist-info/RECORD,,
4
+ filelock-3.20.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
5
+ filelock-3.20.0.dist-info/licenses/LICENSE,sha256=iNm062BXnBkew5HKBMFhMFctfu3EqG2qWL8oxuFMm80,1210
6
+ filelock/__init__.py,sha256=_t_-OAGXo_qyPa9lNQ1YnzVYEvSW3I0onPqzpomsVVg,1769
7
+ filelock/__pycache__/__init__.cpython-313.pyc,,
8
+ filelock/__pycache__/_api.cpython-313.pyc,,
9
+ filelock/__pycache__/_error.cpython-313.pyc,,
10
+ filelock/__pycache__/_soft.cpython-313.pyc,,
11
+ filelock/__pycache__/_unix.cpython-313.pyc,,
12
+ filelock/__pycache__/_util.cpython-313.pyc,,
13
+ filelock/__pycache__/_windows.cpython-313.pyc,,
14
+ filelock/__pycache__/asyncio.cpython-313.pyc,,
15
+ filelock/__pycache__/version.cpython-313.pyc,,
16
+ filelock/_api.py,sha256=2aATBeJ3-jtMj5OSm7EE539iNaTBsf13KXtcBMoi8oM,14545
17
+ filelock/_error.py,sha256=-5jMcjTu60YAvAO1UbqDD1GIEjVkwr8xCFwDBtMeYDg,787
18
+ filelock/_soft.py,sha256=haqtc_TB_KJbYv2a8iuEAclKuM4fMG1vTcp28sK919c,1711
19
+ filelock/_unix.py,sha256=eGOs4gDgZ-5fGnJUz-OkJDeZkAMzgvYcD8hVD6XH7e4,2351
20
+ filelock/_util.py,sha256=QHBoNFIYfbAThhotH3Q8E2acFc84wpG49-T-uu017ZE,1715
21
+ filelock/_windows.py,sha256=8k4XIBl_zZVfGC2gz0kEr8DZBvpNa8wdU9qeM1YrBb8,2179
22
+ filelock/asyncio.py,sha256=dSLe6XZSECFOgsVpcQUSh5Y5zAHxHGPu_tfpPX9I45k,12514
23
+ filelock/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
+ filelock/version.py,sha256=AW5MeEjK4TaQWWJrGb_AlBw8PlmFoIcn7GodG_AVSOM,706
env/lib/python3.13/site-packages/filelock-3.20.0.dist-info/WHEEL ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.27.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
env/lib/python3.13/site-packages/filelock-3.20.0.dist-info/licenses/LICENSE ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ This is free and unencumbered software released into the public domain.
2
+
3
+ Anyone is free to copy, modify, publish, use, compile, sell, or
4
+ distribute this software, either in source code form or as a compiled
5
+ binary, for any purpose, commercial or non-commercial, and by any
6
+ means.
7
+
8
+ In jurisdictions that recognize copyright laws, the author or authors
9
+ of this software dedicate any and all copyright interest in the
10
+ software to the public domain. We make this dedication for the benefit
11
+ of the public at large and to the detriment of our heirs and
12
+ successors. We intend this dedication to be an overt act of
13
+ relinquishment in perpetuity of all present and future rights to this
14
+ software under copyright law.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20
+ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ For more information, please refer to <http://unlicense.org>
env/lib/python3.13/site-packages/filelock/__init__.py ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ A platform independent file lock that supports the with-statement.
3
+
4
+ .. autodata:: filelock.__version__
5
+ :no-value:
6
+
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import sys
12
+ import warnings
13
+ from typing import TYPE_CHECKING
14
+
15
+ from ._api import AcquireReturnProxy, BaseFileLock
16
+ from ._error import Timeout
17
+ from ._soft import SoftFileLock
18
+ from ._unix import UnixFileLock, has_fcntl
19
+ from ._windows import WindowsFileLock
20
+ from .asyncio import (
21
+ AsyncAcquireReturnProxy,
22
+ AsyncSoftFileLock,
23
+ AsyncUnixFileLock,
24
+ AsyncWindowsFileLock,
25
+ BaseAsyncFileLock,
26
+ )
27
+ from .version import version
28
+
29
+ #: version of the project as a string
30
+ __version__: str = version
31
+
32
+
33
+ if sys.platform == "win32": # pragma: win32 cover
34
+ _FileLock: type[BaseFileLock] = WindowsFileLock
35
+ _AsyncFileLock: type[BaseAsyncFileLock] = AsyncWindowsFileLock
36
+ else: # pragma: win32 no cover # noqa: PLR5501
37
+ if has_fcntl:
38
+ _FileLock: type[BaseFileLock] = UnixFileLock
39
+ _AsyncFileLock: type[BaseAsyncFileLock] = AsyncUnixFileLock
40
+ else:
41
+ _FileLock = SoftFileLock
42
+ _AsyncFileLock = AsyncSoftFileLock
43
+ if warnings is not None:
44
+ warnings.warn("only soft file lock is available", stacklevel=2)
45
+
46
+ if TYPE_CHECKING:
47
+ FileLock = SoftFileLock
48
+ AsyncFileLock = AsyncSoftFileLock
49
+ else:
50
+ #: Alias for the lock, which should be used for the current platform.
51
+ FileLock = _FileLock
52
+ AsyncFileLock = _AsyncFileLock
53
+
54
+
55
+ __all__ = [
56
+ "AcquireReturnProxy",
57
+ "AsyncAcquireReturnProxy",
58
+ "AsyncFileLock",
59
+ "AsyncSoftFileLock",
60
+ "AsyncUnixFileLock",
61
+ "AsyncWindowsFileLock",
62
+ "BaseAsyncFileLock",
63
+ "BaseFileLock",
64
+ "FileLock",
65
+ "SoftFileLock",
66
+ "Timeout",
67
+ "UnixFileLock",
68
+ "WindowsFileLock",
69
+ "__version__",
70
+ ]
env/lib/python3.13/site-packages/filelock/__pycache__/__init__.cpython-313.pyc ADDED
Binary file (1.6 kB). View file
 
env/lib/python3.13/site-packages/filelock/__pycache__/_api.cpython-313.pyc ADDED
Binary file (16.5 kB). View file
 
env/lib/python3.13/site-packages/filelock/__pycache__/_error.cpython-313.pyc ADDED
Binary file (1.84 kB). View file
 
env/lib/python3.13/site-packages/filelock/__pycache__/_soft.cpython-313.pyc ADDED
Binary file (2.55 kB). View file
 
env/lib/python3.13/site-packages/filelock/__pycache__/_unix.cpython-313.pyc ADDED
Binary file (3.64 kB). View file
 
env/lib/python3.13/site-packages/filelock/__pycache__/_util.cpython-313.pyc ADDED
Binary file (2.02 kB). View file
 
env/lib/python3.13/site-packages/filelock/__pycache__/_windows.cpython-313.pyc ADDED
Binary file (3.32 kB). View file
 
env/lib/python3.13/site-packages/filelock/__pycache__/asyncio.cpython-313.pyc ADDED
Binary file (15.5 kB). View file
 
env/lib/python3.13/site-packages/filelock/__pycache__/version.cpython-313.pyc ADDED
Binary file (818 Bytes). View file
 
env/lib/python3.13/site-packages/filelock/_api.py ADDED
@@ -0,0 +1,403 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import contextlib
4
+ import inspect
5
+ import logging
6
+ import os
7
+ import time
8
+ import warnings
9
+ from abc import ABCMeta, abstractmethod
10
+ from dataclasses import dataclass
11
+ from threading import local
12
+ from typing import TYPE_CHECKING, Any, cast
13
+ from weakref import WeakValueDictionary
14
+
15
+ from ._error import Timeout
16
+
17
+ if TYPE_CHECKING:
18
+ import sys
19
+ from types import TracebackType
20
+
21
+ if sys.version_info >= (3, 11): # pragma: no cover (py311+)
22
+ from typing import Self
23
+ else: # pragma: no cover (<py311)
24
+ from typing_extensions import Self
25
+
26
+
27
+ _LOGGER = logging.getLogger("filelock")
28
+
29
+
30
+ # This is a helper class which is returned by :meth:`BaseFileLock.acquire` and wraps the lock to make sure __enter__
31
+ # is not called twice when entering the with statement. If we would simply return *self*, the lock would be acquired
32
+ # again in the *__enter__* method of the BaseFileLock, but not released again automatically. issue #37 (memory leak)
33
+ class AcquireReturnProxy:
34
+ """A context-aware object that will release the lock file when exiting."""
35
+
36
+ def __init__(self, lock: BaseFileLock) -> None:
37
+ self.lock = lock
38
+
39
+ def __enter__(self) -> BaseFileLock:
40
+ return self.lock
41
+
42
+ def __exit__(
43
+ self,
44
+ exc_type: type[BaseException] | None,
45
+ exc_value: BaseException | None,
46
+ traceback: TracebackType | None,
47
+ ) -> None:
48
+ self.lock.release()
49
+
50
+
51
+ @dataclass
52
+ class FileLockContext:
53
+ """A dataclass which holds the context for a ``BaseFileLock`` object."""
54
+
55
+ # The context is held in a separate class to allow optional use of thread local storage via the
56
+ # ThreadLocalFileContext class.
57
+
58
+ #: The path to the lock file.
59
+ lock_file: str
60
+
61
+ #: The default timeout value.
62
+ timeout: float
63
+
64
+ #: The mode for the lock files
65
+ mode: int
66
+
67
+ #: Whether the lock should be blocking or not
68
+ blocking: bool
69
+
70
+ #: The file descriptor for the *_lock_file* as it is returned by the os.open() function, not None when lock held
71
+ lock_file_fd: int | None = None
72
+
73
+ #: The lock counter is used for implementing the nested locking mechanism.
74
+ lock_counter: int = 0 # When the lock is acquired is increased and the lock is only released, when this value is 0
75
+
76
+
77
+ class ThreadLocalFileContext(FileLockContext, local):
78
+ """A thread local version of the ``FileLockContext`` class."""
79
+
80
+
81
+ class FileLockMeta(ABCMeta):
82
+ def __call__( # noqa: PLR0913
83
+ cls,
84
+ lock_file: str | os.PathLike[str],
85
+ timeout: float = -1,
86
+ mode: int = 0o644,
87
+ thread_local: bool = True, # noqa: FBT001, FBT002
88
+ *,
89
+ blocking: bool = True,
90
+ is_singleton: bool = False,
91
+ **kwargs: Any, # capture remaining kwargs for subclasses # noqa: ANN401
92
+ ) -> BaseFileLock:
93
+ if is_singleton:
94
+ instance = cls._instances.get(str(lock_file)) # type: ignore[attr-defined]
95
+ if instance:
96
+ params_to_check = {
97
+ "thread_local": (thread_local, instance.is_thread_local()),
98
+ "timeout": (timeout, instance.timeout),
99
+ "mode": (mode, instance.mode),
100
+ "blocking": (blocking, instance.blocking),
101
+ }
102
+
103
+ non_matching_params = {
104
+ name: (passed_param, set_param)
105
+ for name, (passed_param, set_param) in params_to_check.items()
106
+ if passed_param != set_param
107
+ }
108
+ if not non_matching_params:
109
+ return cast("BaseFileLock", instance)
110
+
111
+ # parameters do not match; raise error
112
+ msg = "Singleton lock instances cannot be initialized with differing arguments"
113
+ msg += "\nNon-matching arguments: "
114
+ for param_name, (passed_param, set_param) in non_matching_params.items():
115
+ msg += f"\n\t{param_name} (existing lock has {set_param} but {passed_param} was passed)"
116
+ raise ValueError(msg)
117
+
118
+ # Workaround to make `__init__`'s params optional in subclasses
119
+ # E.g. virtualenv changes the signature of the `__init__` method in the `BaseFileLock` class descendant
120
+ # (https://github.com/tox-dev/filelock/pull/340)
121
+
122
+ all_params = {
123
+ "timeout": timeout,
124
+ "mode": mode,
125
+ "thread_local": thread_local,
126
+ "blocking": blocking,
127
+ "is_singleton": is_singleton,
128
+ **kwargs,
129
+ }
130
+
131
+ present_params = inspect.signature(cls.__init__).parameters # type: ignore[misc]
132
+ init_params = {key: value for key, value in all_params.items() if key in present_params}
133
+
134
+ instance = super().__call__(lock_file, **init_params)
135
+
136
+ if is_singleton:
137
+ cls._instances[str(lock_file)] = instance # type: ignore[attr-defined]
138
+
139
+ return cast("BaseFileLock", instance)
140
+
141
+
142
+ class BaseFileLock(contextlib.ContextDecorator, metaclass=FileLockMeta):
143
+ """Abstract base class for a file lock object."""
144
+
145
+ _instances: WeakValueDictionary[str, BaseFileLock]
146
+
147
+ def __init_subclass__(cls, **kwargs: dict[str, Any]) -> None:
148
+ """Setup unique state for lock subclasses."""
149
+ super().__init_subclass__(**kwargs)
150
+ cls._instances = WeakValueDictionary()
151
+
152
+ def __init__( # noqa: PLR0913
153
+ self,
154
+ lock_file: str | os.PathLike[str],
155
+ timeout: float = -1,
156
+ mode: int = 0o644,
157
+ thread_local: bool = True, # noqa: FBT001, FBT002
158
+ *,
159
+ blocking: bool = True,
160
+ is_singleton: bool = False,
161
+ ) -> None:
162
+ """
163
+ Create a new lock object.
164
+
165
+ :param lock_file: path to the file
166
+ :param timeout: default timeout when acquiring the lock, in seconds. It will be used as fallback value in \
167
+ the acquire method, if no timeout value (``None``) is given. If you want to disable the timeout, set it \
168
+ to a negative value. A timeout of 0 means that there is exactly one attempt to acquire the file lock.
169
+ :param mode: file permissions for the lockfile
170
+ :param thread_local: Whether this object's internal context should be thread local or not. If this is set to \
171
+ ``False`` then the lock will be reentrant across threads.
172
+ :param blocking: whether the lock should be blocking or not
173
+ :param is_singleton: If this is set to ``True`` then only one instance of this class will be created \
174
+ per lock file. This is useful if you want to use the lock object for reentrant locking without needing \
175
+ to pass the same object around.
176
+
177
+ """
178
+ self._is_thread_local = thread_local
179
+ self._is_singleton = is_singleton
180
+
181
+ # Create the context. Note that external code should not work with the context directly and should instead use
182
+ # properties of this class.
183
+ kwargs: dict[str, Any] = {
184
+ "lock_file": os.fspath(lock_file),
185
+ "timeout": timeout,
186
+ "mode": mode,
187
+ "blocking": blocking,
188
+ }
189
+ self._context: FileLockContext = (ThreadLocalFileContext if thread_local else FileLockContext)(**kwargs)
190
+
191
+ def is_thread_local(self) -> bool:
192
+ """:return: a flag indicating if this lock is thread local or not"""
193
+ return self._is_thread_local
194
+
195
+ @property
196
+ def is_singleton(self) -> bool:
197
+ """:return: a flag indicating if this lock is singleton or not"""
198
+ return self._is_singleton
199
+
200
+ @property
201
+ def lock_file(self) -> str:
202
+ """:return: path to the lock file"""
203
+ return self._context.lock_file
204
+
205
+ @property
206
+ def timeout(self) -> float:
207
+ """
208
+ :return: the default timeout value, in seconds
209
+
210
+ .. versionadded:: 2.0.0
211
+ """
212
+ return self._context.timeout
213
+
214
+ @timeout.setter
215
+ def timeout(self, value: float | str) -> None:
216
+ """
217
+ Change the default timeout value.
218
+
219
+ :param value: the new value, in seconds
220
+
221
+ """
222
+ self._context.timeout = float(value)
223
+
224
+ @property
225
+ def blocking(self) -> bool:
226
+ """:return: whether the locking is blocking or not"""
227
+ return self._context.blocking
228
+
229
+ @blocking.setter
230
+ def blocking(self, value: bool) -> None:
231
+ """
232
+ Change the default blocking value.
233
+
234
+ :param value: the new value as bool
235
+
236
+ """
237
+ self._context.blocking = value
238
+
239
+ @property
240
+ def mode(self) -> int:
241
+ """:return: the file permissions for the lockfile"""
242
+ return self._context.mode
243
+
244
+ @abstractmethod
245
+ def _acquire(self) -> None:
246
+ """If the file lock could be acquired, self._context.lock_file_fd holds the file descriptor of the lock file."""
247
+ raise NotImplementedError
248
+
249
+ @abstractmethod
250
+ def _release(self) -> None:
251
+ """Releases the lock and sets self._context.lock_file_fd to None."""
252
+ raise NotImplementedError
253
+
254
+ @property
255
+ def is_locked(self) -> bool:
256
+ """
257
+
258
+ :return: A boolean indicating if the lock file is holding the lock currently.
259
+
260
+ .. versionchanged:: 2.0.0
261
+
262
+ This was previously a method and is now a property.
263
+ """
264
+ return self._context.lock_file_fd is not None
265
+
266
+ @property
267
+ def lock_counter(self) -> int:
268
+ """:return: The number of times this lock has been acquired (but not yet released)."""
269
+ return self._context.lock_counter
270
+
271
+ def acquire(
272
+ self,
273
+ timeout: float | None = None,
274
+ poll_interval: float = 0.05,
275
+ *,
276
+ poll_intervall: float | None = None,
277
+ blocking: bool | None = None,
278
+ ) -> AcquireReturnProxy:
279
+ """
280
+ Try to acquire the file lock.
281
+
282
+ :param timeout: maximum wait time for acquiring the lock, ``None`` means use the default :attr:`~timeout` is and
283
+ if ``timeout < 0``, there is no timeout and this method will block until the lock could be acquired
284
+ :param poll_interval: interval of trying to acquire the lock file
285
+ :param poll_intervall: deprecated, kept for backwards compatibility, use ``poll_interval`` instead
286
+ :param blocking: defaults to True. If False, function will return immediately if it cannot obtain a lock on the
287
+ first attempt. Otherwise, this method will block until the timeout expires or the lock is acquired.
288
+ :raises Timeout: if fails to acquire lock within the timeout period
289
+ :return: a context object that will unlock the file when the context is exited
290
+
291
+ .. code-block:: python
292
+
293
+ # You can use this method in the context manager (recommended)
294
+ with lock.acquire():
295
+ pass
296
+
297
+ # Or use an equivalent try-finally construct:
298
+ lock.acquire()
299
+ try:
300
+ pass
301
+ finally:
302
+ lock.release()
303
+
304
+ .. versionchanged:: 2.0.0
305
+
306
+ This method returns now a *proxy* object instead of *self*,
307
+ so that it can be used in a with statement without side effects.
308
+
309
+ """
310
+ # Use the default timeout, if no timeout is provided.
311
+ if timeout is None:
312
+ timeout = self._context.timeout
313
+
314
+ if blocking is None:
315
+ blocking = self._context.blocking
316
+
317
+ if poll_intervall is not None:
318
+ msg = "use poll_interval instead of poll_intervall"
319
+ warnings.warn(msg, DeprecationWarning, stacklevel=2)
320
+ poll_interval = poll_intervall
321
+
322
+ # Increment the number right at the beginning. We can still undo it, if something fails.
323
+ self._context.lock_counter += 1
324
+
325
+ lock_id = id(self)
326
+ lock_filename = self.lock_file
327
+ start_time = time.perf_counter()
328
+ try:
329
+ while True:
330
+ if not self.is_locked:
331
+ _LOGGER.debug("Attempting to acquire lock %s on %s", lock_id, lock_filename)
332
+ self._acquire()
333
+ if self.is_locked:
334
+ _LOGGER.debug("Lock %s acquired on %s", lock_id, lock_filename)
335
+ break
336
+ if blocking is False:
337
+ _LOGGER.debug("Failed to immediately acquire lock %s on %s", lock_id, lock_filename)
338
+ raise Timeout(lock_filename) # noqa: TRY301
339
+ if 0 <= timeout < time.perf_counter() - start_time:
340
+ _LOGGER.debug("Timeout on acquiring lock %s on %s", lock_id, lock_filename)
341
+ raise Timeout(lock_filename) # noqa: TRY301
342
+ msg = "Lock %s not acquired on %s, waiting %s seconds ..."
343
+ _LOGGER.debug(msg, lock_id, lock_filename, poll_interval)
344
+ time.sleep(poll_interval)
345
+ except BaseException: # Something did go wrong, so decrement the counter.
346
+ self._context.lock_counter = max(0, self._context.lock_counter - 1)
347
+ raise
348
+ return AcquireReturnProxy(lock=self)
349
+
350
+ def release(self, force: bool = False) -> None: # noqa: FBT001, FBT002
351
+ """
352
+ Releases the file lock. Please note, that the lock is only completely released, if the lock counter is 0.
353
+ Also note, that the lock file itself is not automatically deleted.
354
+
355
+ :param force: If true, the lock counter is ignored and the lock is released in every case/
356
+
357
+ """
358
+ if self.is_locked:
359
+ self._context.lock_counter -= 1
360
+
361
+ if self._context.lock_counter == 0 or force:
362
+ lock_id, lock_filename = id(self), self.lock_file
363
+
364
+ _LOGGER.debug("Attempting to release lock %s on %s", lock_id, lock_filename)
365
+ self._release()
366
+ self._context.lock_counter = 0
367
+ _LOGGER.debug("Lock %s released on %s", lock_id, lock_filename)
368
+
369
+ def __enter__(self) -> Self:
370
+ """
371
+ Acquire the lock.
372
+
373
+ :return: the lock object
374
+
375
+ """
376
+ self.acquire()
377
+ return self
378
+
379
+ def __exit__(
380
+ self,
381
+ exc_type: type[BaseException] | None,
382
+ exc_value: BaseException | None,
383
+ traceback: TracebackType | None,
384
+ ) -> None:
385
+ """
386
+ Release the lock.
387
+
388
+ :param exc_type: the exception type if raised
389
+ :param exc_value: the exception value if raised
390
+ :param traceback: the exception traceback if raised
391
+
392
+ """
393
+ self.release()
394
+
395
+ def __del__(self) -> None:
396
+ """Called when the lock object is deleted."""
397
+ self.release(force=True)
398
+
399
+
400
+ __all__ = [
401
+ "AcquireReturnProxy",
402
+ "BaseFileLock",
403
+ ]
env/lib/python3.13/site-packages/filelock/_error.py ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+
6
+ class Timeout(TimeoutError): # noqa: N818
7
+ """Raised when the lock could not be acquired in *timeout* seconds."""
8
+
9
+ def __init__(self, lock_file: str) -> None:
10
+ super().__init__()
11
+ self._lock_file = lock_file
12
+
13
+ def __reduce__(self) -> str | tuple[Any, ...]:
14
+ return self.__class__, (self._lock_file,) # Properly pickle the exception
15
+
16
+ def __str__(self) -> str:
17
+ return f"The file lock '{self._lock_file}' could not be acquired."
18
+
19
+ def __repr__(self) -> str:
20
+ return f"{self.__class__.__name__}({self.lock_file!r})"
21
+
22
+ @property
23
+ def lock_file(self) -> str:
24
+ """:return: The path of the file lock."""
25
+ return self._lock_file
26
+
27
+
28
+ __all__ = [
29
+ "Timeout",
30
+ ]
env/lib/python3.13/site-packages/filelock/_soft.py ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ import sys
5
+ from contextlib import suppress
6
+ from errno import EACCES, EEXIST
7
+ from pathlib import Path
8
+
9
+ from ._api import BaseFileLock
10
+ from ._util import ensure_directory_exists, raise_on_not_writable_file
11
+
12
+
13
+ class SoftFileLock(BaseFileLock):
14
+ """Simply watches the existence of the lock file."""
15
+
16
+ def _acquire(self) -> None:
17
+ raise_on_not_writable_file(self.lock_file)
18
+ ensure_directory_exists(self.lock_file)
19
+ # first check for exists and read-only mode as the open will mask this case as EEXIST
20
+ flags = (
21
+ os.O_WRONLY # open for writing only
22
+ | os.O_CREAT
23
+ | os.O_EXCL # together with above raise EEXIST if the file specified by filename exists
24
+ | os.O_TRUNC # truncate the file to zero byte
25
+ )
26
+ try:
27
+ file_handler = os.open(self.lock_file, flags, self._context.mode)
28
+ except OSError as exception: # re-raise unless expected exception
29
+ if not (
30
+ exception.errno == EEXIST # lock already exist
31
+ or (exception.errno == EACCES and sys.platform == "win32") # has no access to this lock
32
+ ): # pragma: win32 no cover
33
+ raise
34
+ else:
35
+ self._context.lock_file_fd = file_handler
36
+
37
+ def _release(self) -> None:
38
+ assert self._context.lock_file_fd is not None # noqa: S101
39
+ os.close(self._context.lock_file_fd) # the lock file is definitely not None
40
+ self._context.lock_file_fd = None
41
+ with suppress(OSError): # the file is already deleted and that's what we want
42
+ Path(self.lock_file).unlink()
43
+
44
+
45
+ __all__ = [
46
+ "SoftFileLock",
47
+ ]
env/lib/python3.13/site-packages/filelock/_unix.py ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ import sys
5
+ from contextlib import suppress
6
+ from errno import ENOSYS
7
+ from pathlib import Path
8
+ from typing import cast
9
+
10
+ from ._api import BaseFileLock
11
+ from ._util import ensure_directory_exists
12
+
13
+ #: a flag to indicate if the fcntl API is available
14
+ has_fcntl = False
15
+ if sys.platform == "win32": # pragma: win32 cover
16
+
17
+ class UnixFileLock(BaseFileLock):
18
+ """Uses the :func:`fcntl.flock` to hard lock the lock file on unix systems."""
19
+
20
+ def _acquire(self) -> None:
21
+ raise NotImplementedError
22
+
23
+ def _release(self) -> None:
24
+ raise NotImplementedError
25
+
26
+ else: # pragma: win32 no cover
27
+ try:
28
+ import fcntl
29
+
30
+ _ = (fcntl.flock, fcntl.LOCK_EX, fcntl.LOCK_NB, fcntl.LOCK_UN)
31
+ except (ImportError, AttributeError):
32
+ pass
33
+ else:
34
+ has_fcntl = True
35
+
36
+ class UnixFileLock(BaseFileLock):
37
+ """Uses the :func:`fcntl.flock` to hard lock the lock file on unix systems."""
38
+
39
+ def _acquire(self) -> None:
40
+ ensure_directory_exists(self.lock_file)
41
+ open_flags = os.O_RDWR | os.O_TRUNC
42
+ if not Path(self.lock_file).exists():
43
+ open_flags |= os.O_CREAT
44
+ fd = os.open(self.lock_file, open_flags, self._context.mode)
45
+ with suppress(PermissionError): # This locked is not owned by this UID
46
+ os.fchmod(fd, self._context.mode)
47
+ try:
48
+ fcntl.flock(fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
49
+ except OSError as exception:
50
+ os.close(fd)
51
+ if exception.errno == ENOSYS: # NotImplemented error
52
+ msg = "FileSystem does not appear to support flock; use SoftFileLock instead"
53
+ raise NotImplementedError(msg) from exception
54
+ else:
55
+ self._context.lock_file_fd = fd
56
+
57
+ def _release(self) -> None:
58
+ # Do not remove the lockfile:
59
+ # https://github.com/tox-dev/py-filelock/issues/31
60
+ # https://stackoverflow.com/questions/17708885/flock-removing-locked-file-without-race-condition
61
+ fd = cast("int", self._context.lock_file_fd)
62
+ self._context.lock_file_fd = None
63
+ fcntl.flock(fd, fcntl.LOCK_UN)
64
+ os.close(fd)
65
+
66
+
67
+ __all__ = [
68
+ "UnixFileLock",
69
+ "has_fcntl",
70
+ ]
env/lib/python3.13/site-packages/filelock/_util.py ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ import stat
5
+ import sys
6
+ from errno import EACCES, EISDIR
7
+ from pathlib import Path
8
+
9
+
10
+ def raise_on_not_writable_file(filename: str) -> None:
11
+ """
12
+ Raise an exception if attempting to open the file for writing would fail.
13
+
14
+ This is done so files that will never be writable can be separated from files that are writable but currently
15
+ locked.
16
+
17
+ :param filename: file to check
18
+ :raises OSError: as if the file was opened for writing.
19
+
20
+ """
21
+ try: # use stat to do exists + can write to check without race condition
22
+ file_stat = os.stat(filename) # noqa: PTH116
23
+ except OSError:
24
+ return # swallow does not exist or other errors
25
+
26
+ if file_stat.st_mtime != 0: # if os.stat returns but modification is zero that's an invalid os.stat - ignore it
27
+ if not (file_stat.st_mode & stat.S_IWUSR):
28
+ raise PermissionError(EACCES, "Permission denied", filename)
29
+
30
+ if stat.S_ISDIR(file_stat.st_mode):
31
+ if sys.platform == "win32": # pragma: win32 cover
32
+ # On Windows, this is PermissionError
33
+ raise PermissionError(EACCES, "Permission denied", filename)
34
+ else: # pragma: win32 no cover # noqa: RET506
35
+ # On linux / macOS, this is IsADirectoryError
36
+ raise IsADirectoryError(EISDIR, "Is a directory", filename)
37
+
38
+
39
+ def ensure_directory_exists(filename: Path | str) -> None:
40
+ """
41
+ Ensure the directory containing the file exists (create it if necessary).
42
+
43
+ :param filename: file.
44
+
45
+ """
46
+ Path(filename).parent.mkdir(parents=True, exist_ok=True)
47
+
48
+
49
+ __all__ = [
50
+ "ensure_directory_exists",
51
+ "raise_on_not_writable_file",
52
+ ]
env/lib/python3.13/site-packages/filelock/_windows.py ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ import sys
5
+ from contextlib import suppress
6
+ from errno import EACCES
7
+ from pathlib import Path
8
+ from typing import cast
9
+
10
+ from ._api import BaseFileLock
11
+ from ._util import ensure_directory_exists, raise_on_not_writable_file
12
+
13
+ if sys.platform == "win32": # pragma: win32 cover
14
+ import msvcrt
15
+
16
+ class WindowsFileLock(BaseFileLock):
17
+ """Uses the :func:`msvcrt.locking` function to hard lock the lock file on Windows systems."""
18
+
19
+ def _acquire(self) -> None:
20
+ raise_on_not_writable_file(self.lock_file)
21
+ ensure_directory_exists(self.lock_file)
22
+ flags = (
23
+ os.O_RDWR # open for read and write
24
+ | os.O_CREAT # create file if not exists
25
+ | os.O_TRUNC # truncate file if not empty
26
+ )
27
+ try:
28
+ fd = os.open(self.lock_file, flags, self._context.mode)
29
+ except OSError as exception:
30
+ if exception.errno != EACCES: # has no access to this lock
31
+ raise
32
+ else:
33
+ try:
34
+ msvcrt.locking(fd, msvcrt.LK_NBLCK, 1)
35
+ except OSError as exception:
36
+ os.close(fd) # close file first
37
+ if exception.errno != EACCES: # file is already locked
38
+ raise
39
+ else:
40
+ self._context.lock_file_fd = fd
41
+
42
+ def _release(self) -> None:
43
+ fd = cast("int", self._context.lock_file_fd)
44
+ self._context.lock_file_fd = None
45
+ msvcrt.locking(fd, msvcrt.LK_UNLCK, 1)
46
+ os.close(fd)
47
+
48
+ with suppress(OSError): # Probably another instance of the application hat acquired the file lock.
49
+ Path(self.lock_file).unlink()
50
+
51
+ else: # pragma: win32 no cover
52
+
53
+ class WindowsFileLock(BaseFileLock):
54
+ """Uses the :func:`msvcrt.locking` function to hard lock the lock file on Windows systems."""
55
+
56
+ def _acquire(self) -> None:
57
+ raise NotImplementedError
58
+
59
+ def _release(self) -> None:
60
+ raise NotImplementedError
61
+
62
+
63
+ __all__ = [
64
+ "WindowsFileLock",
65
+ ]
env/lib/python3.13/site-packages/filelock/asyncio.py ADDED
@@ -0,0 +1,344 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """An asyncio-based implementation of the file lock."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import asyncio
6
+ import contextlib
7
+ import logging
8
+ import os
9
+ import time
10
+ from dataclasses import dataclass
11
+ from inspect import iscoroutinefunction
12
+ from threading import local
13
+ from typing import TYPE_CHECKING, Any, NoReturn, cast
14
+
15
+ from ._api import BaseFileLock, FileLockContext, FileLockMeta
16
+ from ._error import Timeout
17
+ from ._soft import SoftFileLock
18
+ from ._unix import UnixFileLock
19
+ from ._windows import WindowsFileLock
20
+
21
+ if TYPE_CHECKING:
22
+ import sys
23
+ from collections.abc import Callable
24
+ from concurrent import futures
25
+ from types import TracebackType
26
+
27
+ if sys.version_info >= (3, 11): # pragma: no cover (py311+)
28
+ from typing import Self
29
+ else: # pragma: no cover (<py311)
30
+ from typing_extensions import Self
31
+
32
+
33
+ _LOGGER = logging.getLogger("filelock")
34
+
35
+
36
+ @dataclass
37
+ class AsyncFileLockContext(FileLockContext):
38
+ """A dataclass which holds the context for a ``BaseAsyncFileLock`` object."""
39
+
40
+ #: Whether run in executor
41
+ run_in_executor: bool = True
42
+
43
+ #: The executor
44
+ executor: futures.Executor | None = None
45
+
46
+ #: The loop
47
+ loop: asyncio.AbstractEventLoop | None = None
48
+
49
+
50
+ class AsyncThreadLocalFileContext(AsyncFileLockContext, local):
51
+ """A thread local version of the ``FileLockContext`` class."""
52
+
53
+
54
+ class AsyncAcquireReturnProxy:
55
+ """A context-aware object that will release the lock file when exiting."""
56
+
57
+ def __init__(self, lock: BaseAsyncFileLock) -> None: # noqa: D107
58
+ self.lock = lock
59
+
60
+ async def __aenter__(self) -> BaseAsyncFileLock: # noqa: D105
61
+ return self.lock
62
+
63
+ async def __aexit__( # noqa: D105
64
+ self,
65
+ exc_type: type[BaseException] | None,
66
+ exc_value: BaseException | None,
67
+ traceback: TracebackType | None,
68
+ ) -> None:
69
+ await self.lock.release()
70
+
71
+
72
+ class AsyncFileLockMeta(FileLockMeta):
73
+ def __call__( # type: ignore[override] # noqa: PLR0913
74
+ cls, # noqa: N805
75
+ lock_file: str | os.PathLike[str],
76
+ timeout: float = -1,
77
+ mode: int = 0o644,
78
+ thread_local: bool = False, # noqa: FBT001, FBT002
79
+ *,
80
+ blocking: bool = True,
81
+ is_singleton: bool = False,
82
+ loop: asyncio.AbstractEventLoop | None = None,
83
+ run_in_executor: bool = True,
84
+ executor: futures.Executor | None = None,
85
+ ) -> BaseAsyncFileLock:
86
+ if thread_local and run_in_executor:
87
+ msg = "run_in_executor is not supported when thread_local is True"
88
+ raise ValueError(msg)
89
+ instance = super().__call__(
90
+ lock_file=lock_file,
91
+ timeout=timeout,
92
+ mode=mode,
93
+ thread_local=thread_local,
94
+ blocking=blocking,
95
+ is_singleton=is_singleton,
96
+ loop=loop,
97
+ run_in_executor=run_in_executor,
98
+ executor=executor,
99
+ )
100
+ return cast("BaseAsyncFileLock", instance)
101
+
102
+
103
+ class BaseAsyncFileLock(BaseFileLock, metaclass=AsyncFileLockMeta):
104
+ """Base class for asynchronous file locks."""
105
+
106
+ def __init__( # noqa: PLR0913
107
+ self,
108
+ lock_file: str | os.PathLike[str],
109
+ timeout: float = -1,
110
+ mode: int = 0o644,
111
+ thread_local: bool = False, # noqa: FBT001, FBT002
112
+ *,
113
+ blocking: bool = True,
114
+ is_singleton: bool = False,
115
+ loop: asyncio.AbstractEventLoop | None = None,
116
+ run_in_executor: bool = True,
117
+ executor: futures.Executor | None = None,
118
+ ) -> None:
119
+ """
120
+ Create a new lock object.
121
+
122
+ :param lock_file: path to the file
123
+ :param timeout: default timeout when acquiring the lock, in seconds. It will be used as fallback value in \
124
+ the acquire method, if no timeout value (``None``) is given. If you want to disable the timeout, set it \
125
+ to a negative value. A timeout of 0 means that there is exactly one attempt to acquire the file lock.
126
+ :param mode: file permissions for the lockfile
127
+ :param thread_local: Whether this object's internal context should be thread local or not. If this is set to \
128
+ ``False`` then the lock will be reentrant across threads.
129
+ :param blocking: whether the lock should be blocking or not
130
+ :param is_singleton: If this is set to ``True`` then only one instance of this class will be created \
131
+ per lock file. This is useful if you want to use the lock object for reentrant locking without needing \
132
+ to pass the same object around.
133
+ :param loop: The event loop to use. If not specified, the running event loop will be used.
134
+ :param run_in_executor: If this is set to ``True`` then the lock will be acquired in an executor.
135
+ :param executor: The executor to use. If not specified, the default executor will be used.
136
+
137
+ """
138
+ self._is_thread_local = thread_local
139
+ self._is_singleton = is_singleton
140
+
141
+ # Create the context. Note that external code should not work with the context directly and should instead use
142
+ # properties of this class.
143
+ kwargs: dict[str, Any] = {
144
+ "lock_file": os.fspath(lock_file),
145
+ "timeout": timeout,
146
+ "mode": mode,
147
+ "blocking": blocking,
148
+ "loop": loop,
149
+ "run_in_executor": run_in_executor,
150
+ "executor": executor,
151
+ }
152
+ self._context: AsyncFileLockContext = (AsyncThreadLocalFileContext if thread_local else AsyncFileLockContext)(
153
+ **kwargs
154
+ )
155
+
156
+ @property
157
+ def run_in_executor(self) -> bool:
158
+ """::return: whether run in executor."""
159
+ return self._context.run_in_executor
160
+
161
+ @property
162
+ def executor(self) -> futures.Executor | None:
163
+ """::return: the executor."""
164
+ return self._context.executor
165
+
166
+ @executor.setter
167
+ def executor(self, value: futures.Executor | None) -> None: # pragma: no cover
168
+ """
169
+ Change the executor.
170
+
171
+ :param value: the new executor or ``None``
172
+ :type value: futures.Executor | None
173
+
174
+ """
175
+ self._context.executor = value
176
+
177
+ @property
178
+ def loop(self) -> asyncio.AbstractEventLoop | None:
179
+ """::return: the event loop."""
180
+ return self._context.loop
181
+
182
+ async def acquire( # type: ignore[override]
183
+ self,
184
+ timeout: float | None = None,
185
+ poll_interval: float = 0.05,
186
+ *,
187
+ blocking: bool | None = None,
188
+ ) -> AsyncAcquireReturnProxy:
189
+ """
190
+ Try to acquire the file lock.
191
+
192
+ :param timeout: maximum wait time for acquiring the lock, ``None`` means use the default
193
+ :attr:`~BaseFileLock.timeout` is and if ``timeout < 0``, there is no timeout and
194
+ this method will block until the lock could be acquired
195
+ :param poll_interval: interval of trying to acquire the lock file
196
+ :param blocking: defaults to True. If False, function will return immediately if it cannot obtain a lock on the
197
+ first attempt. Otherwise, this method will block until the timeout expires or the lock is acquired.
198
+ :raises Timeout: if fails to acquire lock within the timeout period
199
+ :return: a context object that will unlock the file when the context is exited
200
+
201
+ .. code-block:: python
202
+
203
+ # You can use this method in the context manager (recommended)
204
+ with lock.acquire():
205
+ pass
206
+
207
+ # Or use an equivalent try-finally construct:
208
+ lock.acquire()
209
+ try:
210
+ pass
211
+ finally:
212
+ lock.release()
213
+
214
+ """
215
+ # Use the default timeout, if no timeout is provided.
216
+ if timeout is None:
217
+ timeout = self._context.timeout
218
+
219
+ if blocking is None:
220
+ blocking = self._context.blocking
221
+
222
+ # Increment the number right at the beginning. We can still undo it, if something fails.
223
+ self._context.lock_counter += 1
224
+
225
+ lock_id = id(self)
226
+ lock_filename = self.lock_file
227
+ start_time = time.perf_counter()
228
+ try:
229
+ while True:
230
+ if not self.is_locked:
231
+ _LOGGER.debug("Attempting to acquire lock %s on %s", lock_id, lock_filename)
232
+ await self._run_internal_method(self._acquire)
233
+ if self.is_locked:
234
+ _LOGGER.debug("Lock %s acquired on %s", lock_id, lock_filename)
235
+ break
236
+ if blocking is False:
237
+ _LOGGER.debug("Failed to immediately acquire lock %s on %s", lock_id, lock_filename)
238
+ raise Timeout(lock_filename) # noqa: TRY301
239
+ if 0 <= timeout < time.perf_counter() - start_time:
240
+ _LOGGER.debug("Timeout on acquiring lock %s on %s", lock_id, lock_filename)
241
+ raise Timeout(lock_filename) # noqa: TRY301
242
+ msg = "Lock %s not acquired on %s, waiting %s seconds ..."
243
+ _LOGGER.debug(msg, lock_id, lock_filename, poll_interval)
244
+ await asyncio.sleep(poll_interval)
245
+ except BaseException: # Something did go wrong, so decrement the counter.
246
+ self._context.lock_counter = max(0, self._context.lock_counter - 1)
247
+ raise
248
+ return AsyncAcquireReturnProxy(lock=self)
249
+
250
+ async def release(self, force: bool = False) -> None: # type: ignore[override] # noqa: FBT001, FBT002
251
+ """
252
+ Releases the file lock. Please note, that the lock is only completely released, if the lock counter is 0.
253
+ Also note, that the lock file itself is not automatically deleted.
254
+
255
+ :param force: If true, the lock counter is ignored and the lock is released in every case/
256
+
257
+ """
258
+ if self.is_locked:
259
+ self._context.lock_counter -= 1
260
+
261
+ if self._context.lock_counter == 0 or force:
262
+ lock_id, lock_filename = id(self), self.lock_file
263
+
264
+ _LOGGER.debug("Attempting to release lock %s on %s", lock_id, lock_filename)
265
+ await self._run_internal_method(self._release)
266
+ self._context.lock_counter = 0
267
+ _LOGGER.debug("Lock %s released on %s", lock_id, lock_filename)
268
+
269
+ async def _run_internal_method(self, method: Callable[[], Any]) -> None:
270
+ if iscoroutinefunction(method):
271
+ await method()
272
+ elif self.run_in_executor:
273
+ loop = self.loop or asyncio.get_running_loop()
274
+ await loop.run_in_executor(self.executor, method)
275
+ else:
276
+ method()
277
+
278
+ def __enter__(self) -> NoReturn:
279
+ """
280
+ Replace old __enter__ method to avoid using it.
281
+
282
+ NOTE: DO NOT USE `with` FOR ASYNCIO LOCKS, USE `async with` INSTEAD.
283
+
284
+ :return: none
285
+ :rtype: NoReturn
286
+ """
287
+ msg = "Do not use `with` for asyncio locks, use `async with` instead."
288
+ raise NotImplementedError(msg)
289
+
290
+ async def __aenter__(self) -> Self:
291
+ """
292
+ Acquire the lock.
293
+
294
+ :return: the lock object
295
+
296
+ """
297
+ await self.acquire()
298
+ return self
299
+
300
+ async def __aexit__(
301
+ self,
302
+ exc_type: type[BaseException] | None,
303
+ exc_value: BaseException | None,
304
+ traceback: TracebackType | None,
305
+ ) -> None:
306
+ """
307
+ Release the lock.
308
+
309
+ :param exc_type: the exception type if raised
310
+ :param exc_value: the exception value if raised
311
+ :param traceback: the exception traceback if raised
312
+
313
+ """
314
+ await self.release()
315
+
316
+ def __del__(self) -> None:
317
+ """Called when the lock object is deleted."""
318
+ with contextlib.suppress(RuntimeError):
319
+ loop = self.loop or asyncio.get_running_loop()
320
+ if not loop.is_running(): # pragma: no cover
321
+ loop.run_until_complete(self.release(force=True))
322
+ else:
323
+ loop.create_task(self.release(force=True))
324
+
325
+
326
+ class AsyncSoftFileLock(SoftFileLock, BaseAsyncFileLock):
327
+ """Simply watches the existence of the lock file."""
328
+
329
+
330
+ class AsyncUnixFileLock(UnixFileLock, BaseAsyncFileLock):
331
+ """Uses the :func:`fcntl.flock` to hard lock the lock file on unix systems."""
332
+
333
+
334
+ class AsyncWindowsFileLock(WindowsFileLock, BaseAsyncFileLock):
335
+ """Uses the :func:`msvcrt.locking` to hard lock the lock file on windows systems."""
336
+
337
+
338
+ __all__ = [
339
+ "AsyncAcquireReturnProxy",
340
+ "AsyncSoftFileLock",
341
+ "AsyncUnixFileLock",
342
+ "AsyncWindowsFileLock",
343
+ "BaseAsyncFileLock",
344
+ ]
env/lib/python3.13/site-packages/filelock/py.typed ADDED
File without changes
env/lib/python3.13/site-packages/filelock/version.py ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # file generated by setuptools-scm
2
+ # don't change, don't track in version control
3
+
4
+ __all__ = [
5
+ "__version__",
6
+ "__version_tuple__",
7
+ "version",
8
+ "version_tuple",
9
+ "__commit_id__",
10
+ "commit_id",
11
+ ]
12
+
13
+ TYPE_CHECKING = False
14
+ if TYPE_CHECKING:
15
+ from typing import Tuple
16
+ from typing import Union
17
+
18
+ VERSION_TUPLE = Tuple[Union[int, str], ...]
19
+ COMMIT_ID = Union[str, None]
20
+ else:
21
+ VERSION_TUPLE = object
22
+ COMMIT_ID = object
23
+
24
+ version: str
25
+ __version__: str
26
+ __version_tuple__: VERSION_TUPLE
27
+ version_tuple: VERSION_TUPLE
28
+ commit_id: COMMIT_ID
29
+ __commit_id__: COMMIT_ID
30
+
31
+ __version__ = version = '3.20.0'
32
+ __version_tuple__ = version_tuple = (3, 20, 0)
33
+
34
+ __commit_id__ = commit_id = None
env/lib/python3.13/site-packages/h11/__init__.py ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # A highish-level implementation of the HTTP/1.1 wire protocol (RFC 7230),
2
+ # containing no networking code at all, loosely modelled on hyper-h2's generic
3
+ # implementation of HTTP/2 (and in particular the h2.connection.H2Connection
4
+ # class). There's still a bunch of subtle details you need to get right if you
5
+ # want to make this actually useful, because it doesn't implement all the
6
+ # semantics to check that what you're asking to write to the wire is sensible,
7
+ # but at least it gets you out of dealing with the wire itself.
8
+
9
+ from h11._connection import Connection, NEED_DATA, PAUSED
10
+ from h11._events import (
11
+ ConnectionClosed,
12
+ Data,
13
+ EndOfMessage,
14
+ Event,
15
+ InformationalResponse,
16
+ Request,
17
+ Response,
18
+ )
19
+ from h11._state import (
20
+ CLIENT,
21
+ CLOSED,
22
+ DONE,
23
+ ERROR,
24
+ IDLE,
25
+ MIGHT_SWITCH_PROTOCOL,
26
+ MUST_CLOSE,
27
+ SEND_BODY,
28
+ SEND_RESPONSE,
29
+ SERVER,
30
+ SWITCHED_PROTOCOL,
31
+ )
32
+ from h11._util import LocalProtocolError, ProtocolError, RemoteProtocolError
33
+ from h11._version import __version__
34
+
35
+ PRODUCT_ID = "python-h11/" + __version__
36
+
37
+
38
+ __all__ = (
39
+ "Connection",
40
+ "NEED_DATA",
41
+ "PAUSED",
42
+ "ConnectionClosed",
43
+ "Data",
44
+ "EndOfMessage",
45
+ "Event",
46
+ "InformationalResponse",
47
+ "Request",
48
+ "Response",
49
+ "CLIENT",
50
+ "CLOSED",
51
+ "DONE",
52
+ "ERROR",
53
+ "IDLE",
54
+ "MUST_CLOSE",
55
+ "SEND_BODY",
56
+ "SEND_RESPONSE",
57
+ "SERVER",
58
+ "SWITCHED_PROTOCOL",
59
+ "ProtocolError",
60
+ "LocalProtocolError",
61
+ "RemoteProtocolError",
62
+ )
env/lib/python3.13/site-packages/h11/__pycache__/__init__.cpython-313.pyc ADDED
Binary file (1.09 kB). View file
 
env/lib/python3.13/site-packages/h11/__pycache__/_abnf.cpython-313.pyc ADDED
Binary file (1.78 kB). View file
 
env/lib/python3.13/site-packages/h11/__pycache__/_connection.cpython-313.pyc ADDED
Binary file (22.8 kB). View file
 
env/lib/python3.13/site-packages/h11/__pycache__/_events.cpython-313.pyc ADDED
Binary file (13.2 kB). View file
 
env/lib/python3.13/site-packages/h11/__pycache__/_headers.cpython-313.pyc ADDED
Binary file (8.06 kB). View file
 
env/lib/python3.13/site-packages/h11/__pycache__/_readers.cpython-313.pyc ADDED
Binary file (9.88 kB). View file
 
env/lib/python3.13/site-packages/h11/__pycache__/_receivebuffer.cpython-313.pyc ADDED
Binary file (4.79 kB). View file
 
env/lib/python3.13/site-packages/h11/__pycache__/_state.cpython-313.pyc ADDED
Binary file (8.79 kB). View file