Bug 1928630 - Update glean_parser to v15.2.1 r=janerik,mach-reviewers,ahal
Differential Revision: https://phabricator.services.mozilla.com/D228092
This commit is contained in:
@@ -36,6 +36,7 @@ vendored:third_party/python/mohawk
|
|||||||
vendored:third_party/python/mozilla_repo_urls
|
vendored:third_party/python/mozilla_repo_urls
|
||||||
vendored:third_party/python/multidict
|
vendored:third_party/python/multidict
|
||||||
vendored:third_party/python/pathspec
|
vendored:third_party/python/pathspec
|
||||||
|
vendored:third_party/python/platformdirs
|
||||||
vendored:third_party/python/ply
|
vendored:third_party/python/ply
|
||||||
vendored:third_party/python/pyasn1
|
vendored:third_party/python/pyasn1
|
||||||
vendored:third_party/python/pyasn1_modules
|
vendored:third_party/python/pyasn1_modules
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ vendored:third_party/python/mohawk
|
|||||||
vendored:third_party/python/mozilla_repo_urls
|
vendored:third_party/python/mozilla_repo_urls
|
||||||
vendored:third_party/python/multidict
|
vendored:third_party/python/multidict
|
||||||
vendored:third_party/python/pathspec
|
vendored:third_party/python/pathspec
|
||||||
|
vendored:third_party/python/platformdirs
|
||||||
vendored:third_party/python/ply
|
vendored:third_party/python/ply
|
||||||
vendored:third_party/python/pyasn1
|
vendored:third_party/python/pyasn1
|
||||||
vendored:third_party/python/pyasn1_modules
|
vendored:third_party/python/pyasn1_modules
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ vendored:third_party/python/packaging
|
|||||||
vendored:third_party/python/pip
|
vendored:third_party/python/pip
|
||||||
vendored:third_party/python/pip_tools
|
vendored:third_party/python/pip_tools
|
||||||
vendored:third_party/python/pkgutil_resolve_name
|
vendored:third_party/python/pkgutil_resolve_name
|
||||||
|
vendored:third_party/python/platformdirs
|
||||||
vendored:third_party/python/pyproject_hooks
|
vendored:third_party/python/pyproject_hooks
|
||||||
vendored:third_party/python/pyrsistent
|
vendored:third_party/python/pyrsistent
|
||||||
vendored:third_party/python/python-hglib
|
vendored:third_party/python/python-hglib
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ vendored:third_party/python/mohawk
|
|||||||
vendored:third_party/python/mozilla_repo_urls
|
vendored:third_party/python/mozilla_repo_urls
|
||||||
vendored:third_party/python/multidict
|
vendored:third_party/python/multidict
|
||||||
vendored:third_party/python/pathspec
|
vendored:third_party/python/pathspec
|
||||||
|
vendored:third_party/python/platformdirs
|
||||||
vendored:third_party/python/ply
|
vendored:third_party/python/ply
|
||||||
vendored:third_party/python/pyasn1
|
vendored:third_party/python/pyasn1
|
||||||
vendored:third_party/python/pyasn1_modules
|
vendored:third_party/python/pyasn1_modules
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ vendored:third_party/python/mozilla_repo_urls
|
|||||||
vendored:third_party/python/multidict
|
vendored:third_party/python/multidict
|
||||||
vendored:third_party/python/pathspec
|
vendored:third_party/python/pathspec
|
||||||
vendored:third_party/python/pkgutil_resolve_name
|
vendored:third_party/python/pkgutil_resolve_name
|
||||||
|
vendored:third_party/python/platformdirs
|
||||||
vendored:third_party/python/ply
|
vendored:third_party/python/ply
|
||||||
vendored:third_party/python/pyasn1
|
vendored:third_party/python/pyasn1
|
||||||
vendored:third_party/python/pyasn1_modules
|
vendored:third_party/python/pyasn1_modules
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
Metadata-Version: 2.1
|
Metadata-Version: 2.1
|
||||||
Name: glean_parser
|
Name: glean_parser
|
||||||
Version: 15.0.1
|
Version: 15.2.1
|
||||||
Summary: Parser tools for Mozilla's Glean telemetry
|
Summary: Parser tools for Mozilla's Glean telemetry
|
||||||
Home-page: https://github.com/mozilla/glean_parser
|
Home-page: https://github.com/mozilla/glean_parser
|
||||||
Author: The Glean Team
|
Author: The Glean Team
|
||||||
@@ -18,11 +18,11 @@ Classifier: Programming Language :: Python :: 3.12
|
|||||||
Description-Content-Type: text/markdown
|
Description-Content-Type: text/markdown
|
||||||
License-File: LICENSE
|
License-File: LICENSE
|
||||||
License-File: AUTHORS.md
|
License-File: AUTHORS.md
|
||||||
Requires-Dist: appdirs>=1.4
|
|
||||||
Requires-Dist: Click>=7
|
Requires-Dist: Click>=7
|
||||||
Requires-Dist: diskcache>=4
|
Requires-Dist: diskcache>=4
|
||||||
Requires-Dist: Jinja2>=2.10.1
|
Requires-Dist: Jinja2>=2.10.1
|
||||||
Requires-Dist: jsonschema>=3.0.2
|
Requires-Dist: jsonschema>=3.0.2
|
||||||
|
Requires-Dist: platformdirs>=2.4.0
|
||||||
Requires-Dist: PyYAML>=5.3.1
|
Requires-Dist: PyYAML>=5.3.1
|
||||||
|
|
||||||
# Glean Parser
|
# Glean Parser
|
||||||
@@ -48,11 +48,11 @@ code for various integrations, linting and coverage testing.
|
|||||||
The following library requirements are installed automatically when
|
The following library requirements are installed automatically when
|
||||||
`glean_parser` is installed by `pip`.
|
`glean_parser` is installed by `pip`.
|
||||||
|
|
||||||
- appdirs
|
|
||||||
- Click
|
- Click
|
||||||
- diskcache
|
- diskcache
|
||||||
- Jinja2
|
- Jinja2
|
||||||
- jsonschema
|
- jsonschema
|
||||||
|
- platformdirs
|
||||||
- PyYAML
|
- PyYAML
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
@@ -79,6 +79,19 @@ $ glean_parser check < ping.json
|
|||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
## 15.2.1
|
||||||
|
|
||||||
|
- Allow earlier versions of platformdirs ([#769](https://github.com/mozilla/glean_parser/pull/769))
|
||||||
|
|
||||||
|
## 15.2.0
|
||||||
|
|
||||||
|
- New Metric Type: `labeled_quantity` ([bug 1925346](https://bugzilla.mozilla.org/show_bug.cgi?id=1925346))
|
||||||
|
|
||||||
|
## 15.1.0
|
||||||
|
|
||||||
|
- Bugfix: Remove unused keyword argument from exception ([#755](https://github.com/mozilla/glean_parser/pull/755))
|
||||||
|
- Add Go log outputter support for custom pings (`go_server`) ([#758](https://github.com/mozilla/glean_parser/pull/758))
|
||||||
|
|
||||||
## 15.0.1
|
## 15.0.1
|
||||||
|
|
||||||
- Rust codegen: use correctly named parameter for events without extras ([#750](https://github.com/mozilla/glean_parser/pull/750))
|
- Rust codegen: use correctly named parameter for events without extras ([#750](https://github.com/mozilla/glean_parser/pull/750))
|
||||||
@@ -2,13 +2,13 @@ glean_parser/__init__.py,sha256=mB3nXWXhV9zJXymgmeGCjUnPFzQgcexx0Klw0XvLkS8,515
|
|||||||
glean_parser/__main__.py,sha256=Rw0PpuQtAvdHJMK1YLozeZkc6x1yjeNZwidu4faovdk,8633
|
glean_parser/__main__.py,sha256=Rw0PpuQtAvdHJMK1YLozeZkc6x1yjeNZwidu4faovdk,8633
|
||||||
glean_parser/coverage.py,sha256=2IwC4XMDtDamMkBFoYilmqJzW4gyypq65YVCur8SNas,4405
|
glean_parser/coverage.py,sha256=2IwC4XMDtDamMkBFoYilmqJzW4gyypq65YVCur8SNas,4405
|
||||||
glean_parser/data_review.py,sha256=BweeeTkNNS6HrIDkztawhbDByrk_-Avxpg7YeST3VAs,2152
|
glean_parser/data_review.py,sha256=BweeeTkNNS6HrIDkztawhbDByrk_-Avxpg7YeST3VAs,2152
|
||||||
glean_parser/go_server.py,sha256=VaPymy5bxAM9jlD0UkkzOndRxT3Wqym193pMMrfBYz0,5421
|
glean_parser/go_server.py,sha256=NOx66OpNDVIos6n3ejoJeFM5Dk4u7E3u86XV2G54tww,5583
|
||||||
glean_parser/javascript.py,sha256=w4ZhNBHBKWYk0h3t7G0Ud2tR__hRqzn9dlEXNKLdQrA,11230
|
glean_parser/javascript.py,sha256=w4ZhNBHBKWYk0h3t7G0Ud2tR__hRqzn9dlEXNKLdQrA,11230
|
||||||
glean_parser/javascript_server.py,sha256=BJpVFuKG3tKFP0_xVyrR9Pn0UrvhumObCEgLeE0Lxhk,9028
|
glean_parser/javascript_server.py,sha256=BJpVFuKG3tKFP0_xVyrR9Pn0UrvhumObCEgLeE0Lxhk,9028
|
||||||
glean_parser/kotlin.py,sha256=X2YNmx4boQ6Yb5CPoCIyRFDADrXPKIcIC-AyjkaSLtM,9519
|
glean_parser/kotlin.py,sha256=X2YNmx4boQ6Yb5CPoCIyRFDADrXPKIcIC-AyjkaSLtM,9519
|
||||||
glean_parser/lint.py,sha256=STqdgyOhR4Q3fHivSizgn9bOOyqrNHhzjaqyJxz6qzI,19948
|
glean_parser/lint.py,sha256=STqdgyOhR4Q3fHivSizgn9bOOyqrNHhzjaqyJxz6qzI,19948
|
||||||
glean_parser/markdown.py,sha256=GkCr1CrV6mnRQseT6FO1-JJ7Eup8X3lxUfRMBTxXpe4,9066
|
glean_parser/markdown.py,sha256=GkCr1CrV6mnRQseT6FO1-JJ7Eup8X3lxUfRMBTxXpe4,9066
|
||||||
glean_parser/metrics.py,sha256=aNRZrH1J90j3npD8Bmy3Wi-ae5mI7lik47nmPGa5v3o,14936
|
glean_parser/metrics.py,sha256=NtWRI7KbnUyMwh8mddWr8dxBKz-8pKZHbAerwPd4N9o,15012
|
||||||
glean_parser/parser.py,sha256=eIlXYUOeeqy6-Ec2V-XFf4dFc2gnRhkgd9ZXjp1RYvU,16366
|
glean_parser/parser.py,sha256=eIlXYUOeeqy6-Ec2V-XFf4dFc2gnRhkgd9ZXjp1RYvU,16366
|
||||||
glean_parser/pings.py,sha256=-CIiMBVOTFULmNybV8YTFI7vmfOYOGQ5TD9hEfYPUII,3435
|
glean_parser/pings.py,sha256=-CIiMBVOTFULmNybV8YTFI7vmfOYOGQ5TD9hEfYPUII,3435
|
||||||
glean_parser/python_server.py,sha256=ERpYcbSwF19xKFagxX0mZAvlR1y6D7Ah5DSvW8LipCY,4791
|
glean_parser/python_server.py,sha256=ERpYcbSwF19xKFagxX0mZAvlR1y6D7Ah5DSvW8LipCY,4791
|
||||||
@@ -16,17 +16,17 @@ glean_parser/ruby_server.py,sha256=e5lkfcLQAUMUBQDCjqNU82LkdUzT5x-G6HOnsUInbsU,5
|
|||||||
glean_parser/rust.py,sha256=u1IeluyxFj6NrZZrBQwwa0nWz0TABv93lYxVBx0aN3I,7334
|
glean_parser/rust.py,sha256=u1IeluyxFj6NrZZrBQwwa0nWz0TABv93lYxVBx0aN3I,7334
|
||||||
glean_parser/swift.py,sha256=paUzF6tItdktFwIQYCKsYpqXfn8zxR2coU_jMYrmwlc,8957
|
glean_parser/swift.py,sha256=paUzF6tItdktFwIQYCKsYpqXfn8zxR2coU_jMYrmwlc,8957
|
||||||
glean_parser/tags.py,sha256=bemKYvcbMO4JrghiNSe-A4BNNDtx_FlUPkgrPPJy84Y,1391
|
glean_parser/tags.py,sha256=bemKYvcbMO4JrghiNSe-A4BNNDtx_FlUPkgrPPJy84Y,1391
|
||||||
glean_parser/translate.py,sha256=luKQoraARZ2tjenHs0SVtCxflnYaMkzPYFfKEdKdSqQ,8403
|
glean_parser/translate.py,sha256=TCcOlvxVR6rX8NCbaSn1ZdHarVgrsEAgrnr-Y0rS4e4,8359
|
||||||
glean_parser/translation_options.py,sha256=Lxzr6G7MP0tC_ZYlZXftS4j0SLiqO-5mGVTEc7ggXis,2037
|
glean_parser/translation_options.py,sha256=Lxzr6G7MP0tC_ZYlZXftS4j0SLiqO-5mGVTEc7ggXis,2037
|
||||||
glean_parser/util.py,sha256=xECYZVlcVzmUn7PT4zp5hVa0iYW2Qh3ik71iPgjeQvY,16223
|
glean_parser/util.py,sha256=OiJsyAhfq2sr5R0stYlSCc-HGl9xCc42kXNabfSu-pU,16233
|
||||||
glean_parser/validate_ping.py,sha256=0TNvILH6dtzJDys3W8Kqorw6kk03me73OCUDtpoHcXU,2118
|
glean_parser/validate_ping.py,sha256=0TNvILH6dtzJDys3W8Kqorw6kk03me73OCUDtpoHcXU,2118
|
||||||
glean_parser/schemas/metrics.1-0-0.schema.yaml,sha256=cND3cvi6iBfPUVmtfIBQfGJV9AALpbvN7nu8E33_J-o,19566
|
glean_parser/schemas/metrics.1-0-0.schema.yaml,sha256=cND3cvi6iBfPUVmtfIBQfGJV9AALpbvN7nu8E33_J-o,19566
|
||||||
glean_parser/schemas/metrics.2-0-0.schema.yaml,sha256=8k0hLEOxyZz_Ap6s-6vPVlwgeOyHiMu54rUogg-KlxY,26687
|
glean_parser/schemas/metrics.2-0-0.schema.yaml,sha256=07Jk9ShjTl-_oRFAs8hrrDSIMfLC-9yPTvGQht7DK18,26736
|
||||||
glean_parser/schemas/pings.1-0-0.schema.yaml,sha256=hwCnsKpEysmrmVp-QHGBArEkVY3vaU1rVsxlTwhAzws,4315
|
glean_parser/schemas/pings.1-0-0.schema.yaml,sha256=hwCnsKpEysmrmVp-QHGBArEkVY3vaU1rVsxlTwhAzws,4315
|
||||||
glean_parser/schemas/pings.2-0-0.schema.yaml,sha256=f8PClAlMoLTmX6ANq8Ai0CpiE74i3LOgU5SoTJpoh0M,6149
|
glean_parser/schemas/pings.2-0-0.schema.yaml,sha256=tgL_mRPDIFa1mBJzHl11RgBuvBpZxfBYWKD4YFVDSSU,6145
|
||||||
glean_parser/schemas/tags.1-0-0.schema.yaml,sha256=OGXIJlvvVW1vaqB_NVZnwKeZ-sLlfH57vjBSHbj6DNI,1231
|
glean_parser/schemas/tags.1-0-0.schema.yaml,sha256=OGXIJlvvVW1vaqB_NVZnwKeZ-sLlfH57vjBSHbj6DNI,1231
|
||||||
glean_parser/templates/data_review.jinja2,sha256=jeYU29T1zLSyu9fKBBFu5BFPfIw8_hmOUXw8RXhRXK8,3287
|
glean_parser/templates/data_review.jinja2,sha256=jeYU29T1zLSyu9fKBBFu5BFPfIw8_hmOUXw8RXhRXK8,3287
|
||||||
glean_parser/templates/go_server.jinja2,sha256=EHf4KBKNPzC1sLugN9yS6_vPNlSl3YCxcoVQGWGL6aM,7039
|
glean_parser/templates/go_server.jinja2,sha256=0_I6Yhys9Gd_BDYjOdJxt2GMfPGSgHoVF-9I89dn9vs,8263
|
||||||
glean_parser/templates/javascript.buildinfo.jinja2,sha256=4mXiZCQIk9if4lxlA05kpSIL4a95IdwGwqle2OqqNAs,474
|
glean_parser/templates/javascript.buildinfo.jinja2,sha256=4mXiZCQIk9if4lxlA05kpSIL4a95IdwGwqle2OqqNAs,474
|
||||||
glean_parser/templates/javascript.jinja2,sha256=cT_bG-jC6m4afECXmcsqHwiiHjRuVtJnfv90OD2Mwxw,2669
|
glean_parser/templates/javascript.jinja2,sha256=cT_bG-jC6m4afECXmcsqHwiiHjRuVtJnfv90OD2Mwxw,2669
|
||||||
glean_parser/templates/javascript_server.jinja2,sha256=tXorqOXOvbhJSjnkxY2p6N6sRqNYxoNNohWoEiCORo4,9737
|
glean_parser/templates/javascript_server.jinja2,sha256=tXorqOXOvbhJSjnkxY2p6N6sRqNYxoNNohWoEiCORo4,9737
|
||||||
@@ -36,12 +36,12 @@ glean_parser/templates/markdown.jinja2,sha256=vAHHGGm28HRDPd3zO_wQMAUZIuxE9uQ7hl
|
|||||||
glean_parser/templates/python_server.jinja2,sha256=gu2C1rkn760IqBCG2SWaK7o32T1ify94wDEsudLPUg8,7260
|
glean_parser/templates/python_server.jinja2,sha256=gu2C1rkn760IqBCG2SWaK7o32T1ify94wDEsudLPUg8,7260
|
||||||
glean_parser/templates/qmldir.jinja2,sha256=m6IGsp-tgTiOfQ7VN8XW6GqX0gJqJkt3B6Pkaul6FVo,156
|
glean_parser/templates/qmldir.jinja2,sha256=m6IGsp-tgTiOfQ7VN8XW6GqX0gJqJkt3B6Pkaul6FVo,156
|
||||||
glean_parser/templates/ruby_server.jinja2,sha256=B0pbuld3j_0s7uMjoaCo8_6ehJUZeTXZlZZ9QRS4J_8,6252
|
glean_parser/templates/ruby_server.jinja2,sha256=B0pbuld3j_0s7uMjoaCo8_6ehJUZeTXZlZZ9QRS4J_8,6252
|
||||||
glean_parser/templates/rust.jinja2,sha256=sr3omkSETQbNyL0JRM1-T9q62l02P7ece0V2nr0XpVw,7197
|
glean_parser/templates/rust.jinja2,sha256=dSHRMcomwEnIa1ZaoShbC3i3mnk-aOwDc9jG_dmRM24,7204
|
||||||
glean_parser/templates/swift.jinja2,sha256=6R--HvvpGum-lZEDIwedyLEFz7KGcc1tei90TiYlMks,6761
|
glean_parser/templates/swift.jinja2,sha256=6R--HvvpGum-lZEDIwedyLEFz7KGcc1tei90TiYlMks,6761
|
||||||
glean_parser-15.0.1.dist-info/AUTHORS.md,sha256=yxgj8MioO4wUnrh0gmfb8l3DJJrf-l4HmmEDbQsbbNI,455
|
glean_parser-15.2.1.dist-info/AUTHORS.md,sha256=yxgj8MioO4wUnrh0gmfb8l3DJJrf-l4HmmEDbQsbbNI,455
|
||||||
glean_parser-15.0.1.dist-info/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725
|
glean_parser-15.2.1.dist-info/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725
|
||||||
glean_parser-15.0.1.dist-info/METADATA,sha256=D0AYTGykO6suojiqCEu8gJMjqmWSB9VLJFLRoRBvQR8,34871
|
glean_parser-15.2.1.dist-info/METADATA,sha256=g1_y-btdpSW0Xiro5M5x14mcv9HBaBjKMt63uiu-ZUE,35363
|
||||||
glean_parser-15.0.1.dist-info/WHEEL,sha256=eOLhNAGa2EW3wWl_TU484h7q1UNgy0JXjjoqKoxAAQc,92
|
glean_parser-15.2.1.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
|
||||||
glean_parser-15.0.1.dist-info/entry_points.txt,sha256=mf9d3sv8BwSjjR58x9KDnpVkONCnv3fPQC2NjJl15Xg,68
|
glean_parser-15.2.1.dist-info/entry_points.txt,sha256=mf9d3sv8BwSjjR58x9KDnpVkONCnv3fPQC2NjJl15Xg,68
|
||||||
glean_parser-15.0.1.dist-info/top_level.txt,sha256=q7T3duD-9tYZFyDry6Wv2LcdMsK2jGnzdDFhxWcT2Z8,13
|
glean_parser-15.2.1.dist-info/top_level.txt,sha256=q7T3duD-9tYZFyDry6Wv2LcdMsK2jGnzdDFhxWcT2Z8,13
|
||||||
glean_parser-15.0.1.dist-info/RECORD,,
|
glean_parser-15.2.1.dist-info/RECORD,,
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
Wheel-Version: 1.0
|
Wheel-Version: 1.0
|
||||||
Generator: bdist_wheel (0.44.0)
|
Generator: setuptools (74.1.2)
|
||||||
Root-Is-Purelib: true
|
Root-Is-Purelib: true
|
||||||
Tag: py3-none-any
|
Tag: py3-none-any
|
||||||
|
|
||||||
@@ -17,9 +17,9 @@ conforming to Glean schema.
|
|||||||
Warning: this outputter supports limited set of metrics,
|
Warning: this outputter supports limited set of metrics,
|
||||||
see `SUPPORTED_METRIC_TYPES` below.
|
see `SUPPORTED_METRIC_TYPES` below.
|
||||||
|
|
||||||
The generated code creates the following:
|
Generated code creates two methods for each ping (`RecordPingX` and `RecordPingXWithoutUserInfo`)
|
||||||
* Two methods for logging an Event metric
|
that are used for submitting (logging) them.
|
||||||
one with and one without user request info specified
|
If pings have `event` metrics assigned, they can be passed to these methods.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
@@ -32,11 +32,19 @@ from . import util
|
|||||||
|
|
||||||
# Adding a metric here will require updating the `generate_metric_type` function
|
# Adding a metric here will require updating the `generate_metric_type` function
|
||||||
# and require adjustments to `metrics` variables the the template.
|
# and require adjustments to `metrics` variables the the template.
|
||||||
SUPPORTED_METRIC_TYPES = ["string", "quantity", "event", "datetime"]
|
SUPPORTED_METRIC_TYPES = ["string", "quantity", "event", "datetime", "boolean"]
|
||||||
|
|
||||||
|
|
||||||
|
def generate_ping_type_name(ping_name: str) -> str:
|
||||||
|
return f"{util.Camelize(ping_name)}Ping"
|
||||||
|
|
||||||
|
|
||||||
|
def generate_ping_events_type_name(ping_name: str) -> str:
|
||||||
|
return f"{util.Camelize(ping_name)}PingEvent"
|
||||||
|
|
||||||
|
|
||||||
def generate_event_type_name(metric: metrics.Metric) -> str:
|
def generate_event_type_name(metric: metrics.Metric) -> str:
|
||||||
return f"Event{util.Camelize(metric.category)}{util.Camelize(metric.name)}"
|
return f"{util.Camelize(metric.category)}{util.Camelize(metric.name)}Event"
|
||||||
|
|
||||||
|
|
||||||
def generate_metric_name(metric: metrics.Metric) -> str:
|
def generate_metric_name(metric: metrics.Metric) -> str:
|
||||||
@@ -87,6 +95,8 @@ def output_go(
|
|||||||
template = util.get_jinja2_template(
|
template = util.get_jinja2_template(
|
||||||
"go_server.jinja2",
|
"go_server.jinja2",
|
||||||
filters=(
|
filters=(
|
||||||
|
("ping_type_name", generate_ping_type_name),
|
||||||
|
("ping_events_type_name", generate_ping_events_type_name),
|
||||||
("event_type_name", generate_event_type_name),
|
("event_type_name", generate_event_type_name),
|
||||||
("event_extra_name", generate_extra_name),
|
("event_extra_name", generate_extra_name),
|
||||||
("metric_name", generate_metric_name),
|
("metric_name", generate_metric_name),
|
||||||
@@ -96,14 +106,8 @@ def output_go(
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
PING_METRIC_ERROR_MSG = (
|
# unique list of event metrics used in any ping
|
||||||
" Server-side environment is simplified and only supports the events ping type."
|
event_metrics: List[metrics.Metric] = []
|
||||||
+ " You should not be including pings.yaml with your parser call"
|
|
||||||
+ " or referencing any other pings in your metric configuration."
|
|
||||||
)
|
|
||||||
if "pings" in objs:
|
|
||||||
print("❌ Ping definition found." + PING_METRIC_ERROR_MSG)
|
|
||||||
return
|
|
||||||
|
|
||||||
# Go through all metrics in objs and build a map of
|
# Go through all metrics in objs and build a map of
|
||||||
# ping->list of metric categories->list of metrics
|
# ping->list of metric categories->list of metrics
|
||||||
@@ -120,22 +124,22 @@ def output_go(
|
|||||||
+ " metric type."
|
+ " metric type."
|
||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for ping in metric.send_in_pings:
|
for ping in metric.send_in_pings:
|
||||||
if ping != "events":
|
if metric.type == "event" and metric not in event_metrics:
|
||||||
(
|
event_metrics.append(metric)
|
||||||
print(
|
|
||||||
"❌ Non-events ping reference found."
|
|
||||||
+ PING_METRIC_ERROR_MSG
|
|
||||||
+ f"Ignoring the {ping} ping type."
|
|
||||||
)
|
|
||||||
)
|
|
||||||
continue
|
|
||||||
metrics_by_type = ping_to_metrics[ping]
|
metrics_by_type = ping_to_metrics[ping]
|
||||||
metrics_list = metrics_by_type.setdefault(metric.type, [])
|
metrics_list = metrics_by_type.setdefault(metric.type, [])
|
||||||
metrics_list.append(metric)
|
metrics_list.append(metric)
|
||||||
|
|
||||||
if "event" not in ping_to_metrics["events"]:
|
PING_METRIC_ERROR_MSG = (
|
||||||
print("❌ No event metrics found...at least one event metric is required")
|
" Server-side environment is simplified and this"
|
||||||
|
+ " parser doesn't generate individual metric files. Make sure to pass all"
|
||||||
|
+ " your ping and metric definitions in a single invocation of the parser."
|
||||||
|
)
|
||||||
|
if not ping_to_metrics:
|
||||||
|
print("❌ No pings with metrics found." + PING_METRIC_ERROR_MSG)
|
||||||
return
|
return
|
||||||
|
|
||||||
extension = ".go"
|
extension = ".go"
|
||||||
@@ -143,6 +147,8 @@ def output_go(
|
|||||||
with filepath.open("w", encoding="utf-8") as fd:
|
with filepath.open("w", encoding="utf-8") as fd:
|
||||||
fd.write(
|
fd.write(
|
||||||
template.render(
|
template.render(
|
||||||
parser_version=__version__, events_ping=ping_to_metrics["events"]
|
parser_version=__version__,
|
||||||
|
pings=ping_to_metrics,
|
||||||
|
events=event_metrics
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -425,6 +425,8 @@ class LabeledMemoryDistribution(Labeled, MemoryDistribution):
|
|||||||
class LabeledTimingDistribution(Labeled, TimingDistribution):
|
class LabeledTimingDistribution(Labeled, TimingDistribution):
|
||||||
typename = "labeled_timing_distribution"
|
typename = "labeled_timing_distribution"
|
||||||
|
|
||||||
|
class LabeledQuantity(Labeled, Quantity):
|
||||||
|
typename = "labeled_quantity"
|
||||||
|
|
||||||
class Rate(Metric):
|
class Rate(Metric):
|
||||||
typename = "rate"
|
typename = "rate"
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ definitions:
|
|||||||
|
|
||||||
`labeled_boolean`, `labeled_string`, `labeled_counter`,
|
`labeled_boolean`, `labeled_string`, `labeled_counter`,
|
||||||
`labeled_custom_distribution`, `labeled_memory_distribution`,
|
`labeled_custom_distribution`, `labeled_memory_distribution`,
|
||||||
`labeled_timing_distribution`.
|
`labeled_timing_distribution`, `labeled_quantity`.
|
||||||
|
|
||||||
- `text`: Record long text data.
|
- `text`: Record long text data.
|
||||||
|
|
||||||
@@ -151,6 +151,7 @@ definitions:
|
|||||||
- labeled_custom_distribution
|
- labeled_custom_distribution
|
||||||
- labeled_memory_distribution
|
- labeled_memory_distribution
|
||||||
- labeled_timing_distribution
|
- labeled_timing_distribution
|
||||||
|
- labeled_quantity
|
||||||
- rate
|
- rate
|
||||||
- text
|
- text
|
||||||
- object
|
- object
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ additionalProperties:
|
|||||||
|
|
||||||
When `true`, the ping will be sent as usual.
|
When `true`, the ping will be sent as usual.
|
||||||
When `false`, the ping will not be sent, but the data will continue to
|
When `false`, the ping will not be sent, but the data will continue to
|
||||||
be collected but will not be cleared when the ping is submitted.
|
be collected and will be cleared when the ping is submitted.
|
||||||
|
|
||||||
Defaults to `true` if omitted.
|
Defaults to `true` if omitted.
|
||||||
type: boolean
|
type: boolean
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ func (g GleanEventsLogger) createPing(documentType string, config RequestInfo, p
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// method called by each event method.
|
// method called by each ping-specific record method.
|
||||||
// construct the ping, wrap it in the envelope, and print to stdout
|
// construct the ping, wrap it in the envelope, and print to stdout
|
||||||
func (g GleanEventsLogger) record(
|
func (g GleanEventsLogger) record(
|
||||||
documentType string,
|
documentType string,
|
||||||
@@ -159,29 +159,82 @@ func (g GleanEventsLogger) record(
|
|||||||
}
|
}
|
||||||
fmt.Println(string(envelopeJson))
|
fmt.Println(string(envelopeJson))
|
||||||
}
|
}
|
||||||
|
{# if any ping has an event metric, create methods and types for them #}
|
||||||
|
{% if events %}
|
||||||
|
|
||||||
|
func newGleanEvent(category, name string, extra map[string]string) gleanEvent {
|
||||||
|
return gleanEvent{
|
||||||
|
Category: category,
|
||||||
|
Name: name,
|
||||||
|
Timestamp: time.Now().UnixMilli(),
|
||||||
|
Extra: extra,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{# each event has a type and method to create a gleanEvent #}
|
||||||
|
{% for event in events %}
|
||||||
|
|
||||||
{% for event in events_ping["event"] %}
|
|
||||||
type {{ event|event_type_name }} struct {
|
type {{ event|event_type_name }} struct {
|
||||||
{% for metric_type, metrics in events_ping.items() %}
|
|
||||||
{% if metric_type != 'event' %}
|
|
||||||
{% for metric in metrics %}
|
|
||||||
{{ metric|metric_argument_name }} {{ metric.type|go_metric_type }} // {{ metric.description|clean_string }}
|
|
||||||
{% endfor %}
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
{% for extra, metadata in event.extra_keys.items() %}
|
{% for extra, metadata in event.extra_keys.items() %}
|
||||||
{{ extra|event_extra_name }} {{ metadata.type|go_metric_type }} // {{ metadata.description|clean_string }}
|
{{ extra|event_extra_name }} {{ metadata.type|go_metric_type }} // {{ metadata.description|clean_string }}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Record and submit an {{ event|event_type_name }} event.
|
func (e {{ event|event_type_name }}) gleanEvent() gleanEvent {
|
||||||
// {{ event.description|clean_string }}
|
return newGleanEvent(
|
||||||
func (g GleanEventsLogger) Record{{ event|event_type_name }}(
|
"{{ event.category }}",
|
||||||
|
"{{ event.name }}",
|
||||||
|
map[string]string{
|
||||||
|
{% for extra, metadata in event.extra_keys.items() %}
|
||||||
|
{# convert all extra fields to string for submission #}
|
||||||
|
{% if metadata.type == 'boolean' %}
|
||||||
|
"{{ extra }}": fmt.Sprintf("%t", e.{{ extra|event_extra_name }}),
|
||||||
|
{% elif metadata.type == 'quantity' %}
|
||||||
|
"{{ extra }}": fmt.Sprintf("%d", e.{{ extra|event_extra_name }}),
|
||||||
|
{% else %}
|
||||||
|
"{{ extra }}": e.{{ extra|event_extra_name }},
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{# struct & methods for submitting pings #}
|
||||||
|
{% for ping, metrics_by_type in pings.items() %}
|
||||||
|
{% if metrics_by_type['event'] %}
|
||||||
|
|
||||||
|
{# interface that eligible events for this ping will implement #}
|
||||||
|
type {{ ping|ping_events_type_name }} interface {
|
||||||
|
is{{ping|ping_events_type_name }}()
|
||||||
|
gleanEvent() gleanEvent
|
||||||
|
}
|
||||||
|
|
||||||
|
{# create functions for valid events for this ping #}
|
||||||
|
{% for metric in metrics_by_type['event'] %}
|
||||||
|
func (e {{ metric|event_type_name}}) is{{ ping|ping_events_type_name }}() {}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
type {{ ping|ping_type_name }} struct {
|
||||||
|
{% for metric_type, metrics in metrics_by_type.items() %}
|
||||||
|
{% if metric_type != 'event' %}
|
||||||
|
{% for metric in metrics %}
|
||||||
|
{{ metric|metric_argument_name }} {{ metric_type|go_metric_type}} // {{ metric.description|clean_string }}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
{% if metrics_by_type['event'] %}
|
||||||
|
Event {{ ping|ping_events_type_name }} // valid event for this ping
|
||||||
|
{% endif %}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record and submit `{{ ping }}` ping
|
||||||
|
func (g GleanEventsLogger) Record{{ ping|ping_type_name }}(
|
||||||
requestInfo RequestInfo,
|
requestInfo RequestInfo,
|
||||||
params {{ event|event_type_name }},
|
params {{ ping|ping_type_name }},
|
||||||
) {
|
) {
|
||||||
var metrics = metrics{
|
var metrics = metrics{
|
||||||
{% for metric_type, metrics in events_ping.items() %}
|
{% for metric_type, metrics in metrics_by_type.items() %}
|
||||||
{% if metric_type != 'event' %}
|
{% if metric_type != 'event' %}
|
||||||
"{{ metric_type }}": {
|
"{{ metric_type }}": {
|
||||||
{% for metric in metrics %}
|
{% for metric in metrics %}
|
||||||
@@ -195,35 +248,20 @@ func (g GleanEventsLogger) Record{{ event|event_type_name }}(
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
}
|
}
|
||||||
var extraKeys = map[string]string{
|
|
||||||
{% for extra, metadata in event.extra_keys.items() %}
|
events := []gleanEvent{}
|
||||||
{# convert all extra fields to string for submission #}
|
{% if metrics_by_type['event'] %}
|
||||||
{% if metadata.type == 'boolean' %}
|
if params.Event != nil {
|
||||||
"{{ extra }}": fmt.Sprintf("%t", params.{{ extra|event_extra_name }}),
|
events = append(events, params.Event.gleanEvent())
|
||||||
{% elif metadata.type == 'quantity' %}
|
}
|
||||||
"{{ extra }}": fmt.Sprintf("%d", params.{{ extra|event_extra_name }}),
|
|
||||||
{% else %}
|
|
||||||
"{{ extra }}": params.{{ extra|event_extra_name }},
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
g.record("{{ ping }}", requestInfo, metrics, events)
|
||||||
}
|
|
||||||
var events = []gleanEvent{
|
|
||||||
gleanEvent{
|
|
||||||
Category: "{{ event.category }}",
|
|
||||||
Name: "{{ event.name }}",
|
|
||||||
Timestamp: time.Now().UnixMilli(),
|
|
||||||
Extra: extraKeys,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
g.record("events", requestInfo, metrics, events)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Record and submit an {{ event|event_type_name }} event omitting user request info
|
// Record and submit `{{ ping }}` ping omitting user request info
|
||||||
// {{ event.description|clean_string }}
|
func (g GleanEventsLogger) Record{{ ping|ping_type_name}}WithoutUserInfo(
|
||||||
func (g GleanEventsLogger) Record{{ event|event_type_name }}WithoutUserInfo(
|
params {{ ping|ping_type_name}},
|
||||||
params {{ event|event_type_name }},
|
|
||||||
) {
|
) {
|
||||||
g.Record{{ event|event_type_name }}(defaultRequestInfo, params)
|
g.Record{{ ping|ping_type_name }}(defaultRequestInfo, params)
|
||||||
}
|
}
|
||||||
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ Jinja2 template is not. Please file bugs! #}
|
|||||||
{{ generate_structure(name ~ "Item", struct["items"]) }}
|
{{ generate_structure(name ~ "Item", struct["items"]) }}
|
||||||
|
|
||||||
{% elif struct.type == "object" %}
|
{% elif struct.type == "object" %}
|
||||||
#[derive(Debug, Hash, Eq, PartialEq, ::glean::traits::__serde::Serialize, ::glean::traits::__serde::Deserialize)]
|
#[derive(Debug, Hash, Eq, PartialEq, Clone, ::glean::traits::__serde::Serialize, ::glean::traits::__serde::Deserialize)]
|
||||||
#[serde(crate = "::glean::traits::__serde")]
|
#[serde(crate = "::glean::traits::__serde")]
|
||||||
#[serde(deny_unknown_fields)]
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct {{ name }} {
|
pub struct {{ name }} {
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ High-level interface for translating `metrics.yaml` into other formats.
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import sys
|
|
||||||
import tempfile
|
import tempfile
|
||||||
from typing import Any, Callable, Dict, Iterable, List, Optional
|
from typing import Any, Callable, Dict, Iterable, List, Optional
|
||||||
|
|
||||||
@@ -98,7 +97,6 @@ def transform_metrics(objects):
|
|||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"No `counter` named {denominator_name} found to be used as"
|
f"No `counter` named {denominator_name} found to be used as"
|
||||||
"denominator for {numerators}",
|
"denominator for {numerators}",
|
||||||
file=sys.stderr,
|
|
||||||
)
|
)
|
||||||
counters[denominator_name].__class__ = metrics.Denominator
|
counters[denominator_name].__class__ = metrics.Denominator
|
||||||
counters[denominator_name].type = "denominator"
|
counters[denominator_name].type = "denominator"
|
||||||
|
|||||||
@@ -13,11 +13,11 @@ import textwrap
|
|||||||
from typing import Any, Callable, Iterable, Sequence, Tuple, Union, Optional
|
from typing import Any, Callable, Iterable, Sequence, Tuple, Union, Optional
|
||||||
import urllib.request
|
import urllib.request
|
||||||
|
|
||||||
import appdirs # type: ignore
|
|
||||||
import diskcache # type: ignore
|
import diskcache # type: ignore
|
||||||
import jinja2
|
import jinja2
|
||||||
import jsonschema # type: ignore
|
import jsonschema # type: ignore
|
||||||
from jsonschema import _utils # type: ignore
|
from jsonschema import _utils # type: ignore
|
||||||
|
import platformdirs # type: ignore
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -278,7 +278,7 @@ def fetch_remote_url(url: str, cache: bool = True):
|
|||||||
return fd.read()
|
return fd.read()
|
||||||
|
|
||||||
if cache:
|
if cache:
|
||||||
cache_dir = appdirs.user_cache_dir("glean_parser", "mozilla")
|
cache_dir = platformdirs.user_cache_dir("glean_parser", "mozilla")
|
||||||
with diskcache.Cache(cache_dir) as dc:
|
with diskcache.Cache(cache_dir) as dc:
|
||||||
if key in dc:
|
if key in dc:
|
||||||
return dc[key]
|
return dc[key]
|
||||||
|
|||||||
327
third_party/python/platformdirs/platformdirs-4.3.6.dist-info/METADATA
vendored
Normal file
327
third_party/python/platformdirs/platformdirs-4.3.6.dist-info/METADATA
vendored
Normal file
@@ -0,0 +1,327 @@
|
|||||||
|
Metadata-Version: 2.3
|
||||||
|
Name: platformdirs
|
||||||
|
Version: 4.3.6
|
||||||
|
Summary: A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`.
|
||||||
|
Project-URL: Changelog, https://github.com/tox-dev/platformdirs/releases
|
||||||
|
Project-URL: Documentation, https://platformdirs.readthedocs.io
|
||||||
|
Project-URL: Homepage, https://github.com/tox-dev/platformdirs
|
||||||
|
Project-URL: Source, https://github.com/tox-dev/platformdirs
|
||||||
|
Project-URL: Tracker, https://github.com/tox-dev/platformdirs/issues
|
||||||
|
Maintainer-email: Bernát Gábor <gaborjbernat@gmail.com>, Julian Berman <Julian@GrayVines.com>, Ofek Lev <oss@ofek.dev>, Ronny Pfannschmidt <opensource@ronnypfannschmidt.de>
|
||||||
|
License-Expression: MIT
|
||||||
|
License-File: LICENSE
|
||||||
|
Keywords: appdirs,application,cache,directory,log,user
|
||||||
|
Classifier: Development Status :: 5 - Production/Stable
|
||||||
|
Classifier: Intended Audience :: Developers
|
||||||
|
Classifier: License :: OSI Approved :: MIT License
|
||||||
|
Classifier: Operating System :: OS Independent
|
||||||
|
Classifier: Programming Language :: Python
|
||||||
|
Classifier: Programming Language :: Python :: 3 :: Only
|
||||||
|
Classifier: Programming Language :: Python :: 3.8
|
||||||
|
Classifier: Programming Language :: Python :: 3.9
|
||||||
|
Classifier: Programming Language :: Python :: 3.10
|
||||||
|
Classifier: Programming Language :: Python :: 3.11
|
||||||
|
Classifier: Programming Language :: Python :: 3.12
|
||||||
|
Classifier: Programming Language :: Python :: 3.13
|
||||||
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
||||||
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
||||||
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
||||||
|
Requires-Python: >=3.8
|
||||||
|
Provides-Extra: docs
|
||||||
|
Requires-Dist: furo>=2024.8.6; extra == 'docs'
|
||||||
|
Requires-Dist: proselint>=0.14; extra == 'docs'
|
||||||
|
Requires-Dist: sphinx-autodoc-typehints>=2.4; extra == 'docs'
|
||||||
|
Requires-Dist: sphinx>=8.0.2; extra == 'docs'
|
||||||
|
Provides-Extra: test
|
||||||
|
Requires-Dist: appdirs==1.4.4; extra == 'test'
|
||||||
|
Requires-Dist: covdefaults>=2.3; extra == 'test'
|
||||||
|
Requires-Dist: pytest-cov>=5; extra == 'test'
|
||||||
|
Requires-Dist: pytest-mock>=3.14; extra == 'test'
|
||||||
|
Requires-Dist: pytest>=8.3.2; extra == 'test'
|
||||||
|
Provides-Extra: type
|
||||||
|
Requires-Dist: mypy>=1.11.2; extra == 'type'
|
||||||
|
Description-Content-Type: text/x-rst
|
||||||
|
|
||||||
|
The problem
|
||||||
|
===========
|
||||||
|
|
||||||
|
.. image:: https://badge.fury.io/py/platformdirs.svg
|
||||||
|
:target: https://badge.fury.io/py/platformdirs
|
||||||
|
.. image:: https://img.shields.io/pypi/pyversions/platformdirs.svg
|
||||||
|
:target: https://pypi.python.org/pypi/platformdirs/
|
||||||
|
.. image:: https://github.com/tox-dev/platformdirs/actions/workflows/check.yaml/badge.svg
|
||||||
|
:target: https://github.com/platformdirs/platformdirs/actions
|
||||||
|
.. image:: https://static.pepy.tech/badge/platformdirs/month
|
||||||
|
:target: https://pepy.tech/project/platformdirs
|
||||||
|
|
||||||
|
When writing desktop application, finding the right location to store user data
|
||||||
|
and configuration varies per platform. Even for single-platform apps, there
|
||||||
|
may by plenty of nuances in figuring out the right location.
|
||||||
|
|
||||||
|
For example, if running on macOS, you should use::
|
||||||
|
|
||||||
|
~/Library/Application Support/<AppName>
|
||||||
|
|
||||||
|
If on Windows (at least English Win) that should be::
|
||||||
|
|
||||||
|
C:\Documents and Settings\<User>\Application Data\Local Settings\<AppAuthor>\<AppName>
|
||||||
|
|
||||||
|
or possibly::
|
||||||
|
|
||||||
|
C:\Documents and Settings\<User>\Application Data\<AppAuthor>\<AppName>
|
||||||
|
|
||||||
|
for `roaming profiles <https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-vista/cc766489(v=ws.10)>`_ but that is another story.
|
||||||
|
|
||||||
|
On Linux (and other Unices), according to the `XDG Basedir Spec`_, it should be::
|
||||||
|
|
||||||
|
~/.local/share/<AppName>
|
||||||
|
|
||||||
|
.. _XDG Basedir Spec: https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
|
||||||
|
|
||||||
|
``platformdirs`` to the rescue
|
||||||
|
==============================
|
||||||
|
|
||||||
|
This kind of thing is what the ``platformdirs`` package is for.
|
||||||
|
``platformdirs`` will help you choose an appropriate:
|
||||||
|
|
||||||
|
- user data dir (``user_data_dir``)
|
||||||
|
- user config dir (``user_config_dir``)
|
||||||
|
- user cache dir (``user_cache_dir``)
|
||||||
|
- site data dir (``site_data_dir``)
|
||||||
|
- site config dir (``site_config_dir``)
|
||||||
|
- user log dir (``user_log_dir``)
|
||||||
|
- user documents dir (``user_documents_dir``)
|
||||||
|
- user downloads dir (``user_downloads_dir``)
|
||||||
|
- user pictures dir (``user_pictures_dir``)
|
||||||
|
- user videos dir (``user_videos_dir``)
|
||||||
|
- user music dir (``user_music_dir``)
|
||||||
|
- user desktop dir (``user_desktop_dir``)
|
||||||
|
- user runtime dir (``user_runtime_dir``)
|
||||||
|
|
||||||
|
And also:
|
||||||
|
|
||||||
|
- Is slightly opinionated on the directory names used. Look for "OPINION" in
|
||||||
|
documentation and code for when an opinion is being applied.
|
||||||
|
|
||||||
|
Example output
|
||||||
|
==============
|
||||||
|
|
||||||
|
On macOS:
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> from platformdirs import *
|
||||||
|
>>> appname = "SuperApp"
|
||||||
|
>>> appauthor = "Acme"
|
||||||
|
>>> user_data_dir(appname, appauthor)
|
||||||
|
'/Users/trentm/Library/Application Support/SuperApp'
|
||||||
|
>>> site_data_dir(appname, appauthor)
|
||||||
|
'/Library/Application Support/SuperApp'
|
||||||
|
>>> user_cache_dir(appname, appauthor)
|
||||||
|
'/Users/trentm/Library/Caches/SuperApp'
|
||||||
|
>>> user_log_dir(appname, appauthor)
|
||||||
|
'/Users/trentm/Library/Logs/SuperApp'
|
||||||
|
>>> user_documents_dir()
|
||||||
|
'/Users/trentm/Documents'
|
||||||
|
>>> user_downloads_dir()
|
||||||
|
'/Users/trentm/Downloads'
|
||||||
|
>>> user_pictures_dir()
|
||||||
|
'/Users/trentm/Pictures'
|
||||||
|
>>> user_videos_dir()
|
||||||
|
'/Users/trentm/Movies'
|
||||||
|
>>> user_music_dir()
|
||||||
|
'/Users/trentm/Music'
|
||||||
|
>>> user_desktop_dir()
|
||||||
|
'/Users/trentm/Desktop'
|
||||||
|
>>> user_runtime_dir(appname, appauthor)
|
||||||
|
'/Users/trentm/Library/Caches/TemporaryItems/SuperApp'
|
||||||
|
|
||||||
|
On Windows:
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> from platformdirs import *
|
||||||
|
>>> appname = "SuperApp"
|
||||||
|
>>> appauthor = "Acme"
|
||||||
|
>>> user_data_dir(appname, appauthor)
|
||||||
|
'C:\\Users\\trentm\\AppData\\Local\\Acme\\SuperApp'
|
||||||
|
>>> user_data_dir(appname, appauthor, roaming=True)
|
||||||
|
'C:\\Users\\trentm\\AppData\\Roaming\\Acme\\SuperApp'
|
||||||
|
>>> user_cache_dir(appname, appauthor)
|
||||||
|
'C:\\Users\\trentm\\AppData\\Local\\Acme\\SuperApp\\Cache'
|
||||||
|
>>> user_log_dir(appname, appauthor)
|
||||||
|
'C:\\Users\\trentm\\AppData\\Local\\Acme\\SuperApp\\Logs'
|
||||||
|
>>> user_documents_dir()
|
||||||
|
'C:\\Users\\trentm\\Documents'
|
||||||
|
>>> user_downloads_dir()
|
||||||
|
'C:\\Users\\trentm\\Downloads'
|
||||||
|
>>> user_pictures_dir()
|
||||||
|
'C:\\Users\\trentm\\Pictures'
|
||||||
|
>>> user_videos_dir()
|
||||||
|
'C:\\Users\\trentm\\Videos'
|
||||||
|
>>> user_music_dir()
|
||||||
|
'C:\\Users\\trentm\\Music'
|
||||||
|
>>> user_desktop_dir()
|
||||||
|
'C:\\Users\\trentm\\Desktop'
|
||||||
|
>>> user_runtime_dir(appname, appauthor)
|
||||||
|
'C:\\Users\\trentm\\AppData\\Local\\Temp\\Acme\\SuperApp'
|
||||||
|
|
||||||
|
On Linux:
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> from platformdirs import *
|
||||||
|
>>> appname = "SuperApp"
|
||||||
|
>>> appauthor = "Acme"
|
||||||
|
>>> user_data_dir(appname, appauthor)
|
||||||
|
'/home/trentm/.local/share/SuperApp'
|
||||||
|
>>> site_data_dir(appname, appauthor)
|
||||||
|
'/usr/local/share/SuperApp'
|
||||||
|
>>> site_data_dir(appname, appauthor, multipath=True)
|
||||||
|
'/usr/local/share/SuperApp:/usr/share/SuperApp'
|
||||||
|
>>> user_cache_dir(appname, appauthor)
|
||||||
|
'/home/trentm/.cache/SuperApp'
|
||||||
|
>>> user_log_dir(appname, appauthor)
|
||||||
|
'/home/trentm/.local/state/SuperApp/log'
|
||||||
|
>>> user_config_dir(appname)
|
||||||
|
'/home/trentm/.config/SuperApp'
|
||||||
|
>>> user_documents_dir()
|
||||||
|
'/home/trentm/Documents'
|
||||||
|
>>> user_downloads_dir()
|
||||||
|
'/home/trentm/Downloads'
|
||||||
|
>>> user_pictures_dir()
|
||||||
|
'/home/trentm/Pictures'
|
||||||
|
>>> user_videos_dir()
|
||||||
|
'/home/trentm/Videos'
|
||||||
|
>>> user_music_dir()
|
||||||
|
'/home/trentm/Music'
|
||||||
|
>>> user_desktop_dir()
|
||||||
|
'/home/trentm/Desktop'
|
||||||
|
>>> user_runtime_dir(appname, appauthor)
|
||||||
|
'/run/user/{os.getuid()}/SuperApp'
|
||||||
|
>>> site_config_dir(appname)
|
||||||
|
'/etc/xdg/SuperApp'
|
||||||
|
>>> os.environ["XDG_CONFIG_DIRS"] = "/etc:/usr/local/etc"
|
||||||
|
>>> site_config_dir(appname, multipath=True)
|
||||||
|
'/etc/SuperApp:/usr/local/etc/SuperApp'
|
||||||
|
|
||||||
|
On Android::
|
||||||
|
|
||||||
|
>>> from platformdirs import *
|
||||||
|
>>> appname = "SuperApp"
|
||||||
|
>>> appauthor = "Acme"
|
||||||
|
>>> user_data_dir(appname, appauthor)
|
||||||
|
'/data/data/com.myApp/files/SuperApp'
|
||||||
|
>>> user_cache_dir(appname, appauthor)
|
||||||
|
'/data/data/com.myApp/cache/SuperApp'
|
||||||
|
>>> user_log_dir(appname, appauthor)
|
||||||
|
'/data/data/com.myApp/cache/SuperApp/log'
|
||||||
|
>>> user_config_dir(appname)
|
||||||
|
'/data/data/com.myApp/shared_prefs/SuperApp'
|
||||||
|
>>> user_documents_dir()
|
||||||
|
'/storage/emulated/0/Documents'
|
||||||
|
>>> user_downloads_dir()
|
||||||
|
'/storage/emulated/0/Downloads'
|
||||||
|
>>> user_pictures_dir()
|
||||||
|
'/storage/emulated/0/Pictures'
|
||||||
|
>>> user_videos_dir()
|
||||||
|
'/storage/emulated/0/DCIM/Camera'
|
||||||
|
>>> user_music_dir()
|
||||||
|
'/storage/emulated/0/Music'
|
||||||
|
>>> user_desktop_dir()
|
||||||
|
'/storage/emulated/0/Desktop'
|
||||||
|
>>> user_runtime_dir(appname, appauthor)
|
||||||
|
'/data/data/com.myApp/cache/SuperApp/tmp'
|
||||||
|
|
||||||
|
Note: Some android apps like Termux and Pydroid are used as shells. These
|
||||||
|
apps are used by the end user to emulate Linux environment. Presence of
|
||||||
|
``SHELL`` environment variable is used by Platformdirs to differentiate
|
||||||
|
between general android apps and android apps used as shells. Shell android
|
||||||
|
apps also support ``XDG_*`` environment variables.
|
||||||
|
|
||||||
|
|
||||||
|
``PlatformDirs`` for convenience
|
||||||
|
================================
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> from platformdirs import PlatformDirs
|
||||||
|
>>> dirs = PlatformDirs("SuperApp", "Acme")
|
||||||
|
>>> dirs.user_data_dir
|
||||||
|
'/Users/trentm/Library/Application Support/SuperApp'
|
||||||
|
>>> dirs.site_data_dir
|
||||||
|
'/Library/Application Support/SuperApp'
|
||||||
|
>>> dirs.user_cache_dir
|
||||||
|
'/Users/trentm/Library/Caches/SuperApp'
|
||||||
|
>>> dirs.user_log_dir
|
||||||
|
'/Users/trentm/Library/Logs/SuperApp'
|
||||||
|
>>> dirs.user_documents_dir
|
||||||
|
'/Users/trentm/Documents'
|
||||||
|
>>> dirs.user_downloads_dir
|
||||||
|
'/Users/trentm/Downloads'
|
||||||
|
>>> dirs.user_pictures_dir
|
||||||
|
'/Users/trentm/Pictures'
|
||||||
|
>>> dirs.user_videos_dir
|
||||||
|
'/Users/trentm/Movies'
|
||||||
|
>>> dirs.user_music_dir
|
||||||
|
'/Users/trentm/Music'
|
||||||
|
>>> dirs.user_desktop_dir
|
||||||
|
'/Users/trentm/Desktop'
|
||||||
|
>>> dirs.user_runtime_dir
|
||||||
|
'/Users/trentm/Library/Caches/TemporaryItems/SuperApp'
|
||||||
|
|
||||||
|
Per-version isolation
|
||||||
|
=====================
|
||||||
|
|
||||||
|
If you have multiple versions of your app in use that you want to be
|
||||||
|
able to run side-by-side, then you may want version-isolation for these
|
||||||
|
dirs::
|
||||||
|
|
||||||
|
>>> from platformdirs import PlatformDirs
|
||||||
|
>>> dirs = PlatformDirs("SuperApp", "Acme", version="1.0")
|
||||||
|
>>> dirs.user_data_dir
|
||||||
|
'/Users/trentm/Library/Application Support/SuperApp/1.0'
|
||||||
|
>>> dirs.site_data_dir
|
||||||
|
'/Library/Application Support/SuperApp/1.0'
|
||||||
|
>>> dirs.user_cache_dir
|
||||||
|
'/Users/trentm/Library/Caches/SuperApp/1.0'
|
||||||
|
>>> dirs.user_log_dir
|
||||||
|
'/Users/trentm/Library/Logs/SuperApp/1.0'
|
||||||
|
>>> dirs.user_documents_dir
|
||||||
|
'/Users/trentm/Documents'
|
||||||
|
>>> dirs.user_downloads_dir
|
||||||
|
'/Users/trentm/Downloads'
|
||||||
|
>>> dirs.user_pictures_dir
|
||||||
|
'/Users/trentm/Pictures'
|
||||||
|
>>> dirs.user_videos_dir
|
||||||
|
'/Users/trentm/Movies'
|
||||||
|
>>> dirs.user_music_dir
|
||||||
|
'/Users/trentm/Music'
|
||||||
|
>>> dirs.user_desktop_dir
|
||||||
|
'/Users/trentm/Desktop'
|
||||||
|
>>> dirs.user_runtime_dir
|
||||||
|
'/Users/trentm/Library/Caches/TemporaryItems/SuperApp/1.0'
|
||||||
|
|
||||||
|
Be wary of using this for configuration files though; you'll need to handle
|
||||||
|
migrating configuration files manually.
|
||||||
|
|
||||||
|
Why this Fork?
|
||||||
|
==============
|
||||||
|
|
||||||
|
This repository is a friendly fork of the wonderful work started by
|
||||||
|
`ActiveState <https://github.com/ActiveState/appdirs>`_ who created
|
||||||
|
``appdirs``, this package's ancestor.
|
||||||
|
|
||||||
|
Maintaining an open source project is no easy task, particularly
|
||||||
|
from within an organization, and the Python community is indebted
|
||||||
|
to ``appdirs`` (and to Trent Mick and Jeff Rouse in particular) for
|
||||||
|
creating an incredibly useful simple module, as evidenced by the wide
|
||||||
|
number of users it has attracted over the years.
|
||||||
|
|
||||||
|
Nonetheless, given the number of long-standing open issues
|
||||||
|
and pull requests, and no clear path towards `ensuring
|
||||||
|
that maintenance of the package would continue or grow
|
||||||
|
<https://github.com/ActiveState/appdirs/issues/79>`_, this fork was
|
||||||
|
created.
|
||||||
|
|
||||||
|
Contributions are most welcome.
|
||||||
13
third_party/python/platformdirs/platformdirs-4.3.6.dist-info/RECORD
vendored
Normal file
13
third_party/python/platformdirs/platformdirs-4.3.6.dist-info/RECORD
vendored
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
platformdirs/__init__.py,sha256=mVCfMmBM4q24lq6336V3VJncdxaOegI4qQSmQCjkR5E,22284
|
||||||
|
platformdirs/__main__.py,sha256=HnsUQHpiBaiTxwcmwVw-nFaPdVNZtQIdi1eWDtI-MzI,1493
|
||||||
|
platformdirs/android.py,sha256=kV5oL3V3DZ6WZKu9yFiQupv18yp_jlSV2ChH1TmPcds,9007
|
||||||
|
platformdirs/api.py,sha256=2dfUDNbEXeDhDKarqtR5NY7oUikUZ4RZhs3ozstmhBQ,9246
|
||||||
|
platformdirs/macos.py,sha256=UlbyFZ8Rzu3xndCqQEHrfsYTeHwYdFap1Ioz-yxveT4,6154
|
||||||
|
platformdirs/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||||
|
platformdirs/unix.py,sha256=uRPJWRyQEtv7yOSvU94rUmsblo5XKDLA1SzFg55kbK0,10393
|
||||||
|
platformdirs/version.py,sha256=oH4KgTfK4AklbTYVcV_yynvJ9JLI3pyvDVay0hRsLCs,411
|
||||||
|
platformdirs/windows.py,sha256=IFpiohUBwxPtCzlyKwNtxyW4Jk8haa6W8o59mfrDXVo,10125
|
||||||
|
platformdirs-4.3.6.dist-info/METADATA,sha256=085GgRFo5U1nc9NR8e6unEWKxUjDMsgSHDyaCETsCQ4,11868
|
||||||
|
platformdirs-4.3.6.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
|
||||||
|
platformdirs-4.3.6.dist-info/licenses/LICENSE,sha256=KeD9YukphQ6G6yjD_czwzv30-pSHkBHP-z0NS-1tTbY,1089
|
||||||
|
platformdirs-4.3.6.dist-info/RECORD,,
|
||||||
4
third_party/python/platformdirs/platformdirs-4.3.6.dist-info/WHEEL
vendored
Normal file
4
third_party/python/platformdirs/platformdirs-4.3.6.dist-info/WHEEL
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
Wheel-Version: 1.0
|
||||||
|
Generator: hatchling 1.25.0
|
||||||
|
Root-Is-Purelib: true
|
||||||
|
Tag: py3-none-any
|
||||||
21
third_party/python/platformdirs/platformdirs-4.3.6.dist-info/licenses/LICENSE
vendored
Normal file
21
third_party/python/platformdirs/platformdirs-4.3.6.dist-info/licenses/LICENSE
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2010-202x The platformdirs developers
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
631
third_party/python/platformdirs/platformdirs/__init__.py
vendored
Normal file
631
third_party/python/platformdirs/platformdirs/__init__.py
vendored
Normal file
@@ -0,0 +1,631 @@
|
|||||||
|
"""
|
||||||
|
Utilities for determining application-specific dirs.
|
||||||
|
|
||||||
|
See <https://github.com/platformdirs/platformdirs> for details and usage.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
from .api import PlatformDirsABC
|
||||||
|
from .version import __version__
|
||||||
|
from .version import __version_tuple__ as __version_info__
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Literal
|
||||||
|
|
||||||
|
if sys.platform == "win32":
|
||||||
|
from platformdirs.windows import Windows as _Result
|
||||||
|
elif sys.platform == "darwin":
|
||||||
|
from platformdirs.macos import MacOS as _Result
|
||||||
|
else:
|
||||||
|
from platformdirs.unix import Unix as _Result
|
||||||
|
|
||||||
|
|
||||||
|
def _set_platform_dir_class() -> type[PlatformDirsABC]:
|
||||||
|
if os.getenv("ANDROID_DATA") == "/data" and os.getenv("ANDROID_ROOT") == "/system":
|
||||||
|
if os.getenv("SHELL") or os.getenv("PREFIX"):
|
||||||
|
return _Result
|
||||||
|
|
||||||
|
from platformdirs.android import _android_folder # noqa: PLC0415
|
||||||
|
|
||||||
|
if _android_folder() is not None:
|
||||||
|
from platformdirs.android import Android # noqa: PLC0415
|
||||||
|
|
||||||
|
return Android # return to avoid redefinition of a result
|
||||||
|
|
||||||
|
return _Result
|
||||||
|
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
# Work around mypy issue: https://github.com/python/mypy/issues/10962
|
||||||
|
PlatformDirs = _Result
|
||||||
|
else:
|
||||||
|
PlatformDirs = _set_platform_dir_class() #: Currently active platform
|
||||||
|
AppDirs = PlatformDirs #: Backwards compatibility with appdirs
|
||||||
|
|
||||||
|
|
||||||
|
def user_data_dir(
|
||||||
|
appname: str | None = None,
|
||||||
|
appauthor: str | None | Literal[False] = None,
|
||||||
|
version: str | None = None,
|
||||||
|
roaming: bool = False, # noqa: FBT001, FBT002
|
||||||
|
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||||
|
) -> str:
|
||||||
|
"""
|
||||||
|
:param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
|
||||||
|
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
|
||||||
|
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
|
||||||
|
:param roaming: See `roaming <platformdirs.api.PlatformDirsABC.roaming>`.
|
||||||
|
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||||
|
:returns: data directory tied to the user
|
||||||
|
"""
|
||||||
|
return PlatformDirs(
|
||||||
|
appname=appname,
|
||||||
|
appauthor=appauthor,
|
||||||
|
version=version,
|
||||||
|
roaming=roaming,
|
||||||
|
ensure_exists=ensure_exists,
|
||||||
|
).user_data_dir
|
||||||
|
|
||||||
|
|
||||||
|
def site_data_dir(
|
||||||
|
appname: str | None = None,
|
||||||
|
appauthor: str | None | Literal[False] = None,
|
||||||
|
version: str | None = None,
|
||||||
|
multipath: bool = False, # noqa: FBT001, FBT002
|
||||||
|
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||||
|
) -> str:
|
||||||
|
"""
|
||||||
|
:param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
|
||||||
|
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
|
||||||
|
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
|
||||||
|
:param multipath: See `roaming <platformdirs.api.PlatformDirsABC.multipath>`.
|
||||||
|
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||||
|
:returns: data directory shared by users
|
||||||
|
"""
|
||||||
|
return PlatformDirs(
|
||||||
|
appname=appname,
|
||||||
|
appauthor=appauthor,
|
||||||
|
version=version,
|
||||||
|
multipath=multipath,
|
||||||
|
ensure_exists=ensure_exists,
|
||||||
|
).site_data_dir
|
||||||
|
|
||||||
|
|
||||||
|
def user_config_dir(
|
||||||
|
appname: str | None = None,
|
||||||
|
appauthor: str | None | Literal[False] = None,
|
||||||
|
version: str | None = None,
|
||||||
|
roaming: bool = False, # noqa: FBT001, FBT002
|
||||||
|
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||||
|
) -> str:
|
||||||
|
"""
|
||||||
|
:param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
|
||||||
|
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
|
||||||
|
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
|
||||||
|
:param roaming: See `roaming <platformdirs.api.PlatformDirsABC.roaming>`.
|
||||||
|
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||||
|
:returns: config directory tied to the user
|
||||||
|
"""
|
||||||
|
return PlatformDirs(
|
||||||
|
appname=appname,
|
||||||
|
appauthor=appauthor,
|
||||||
|
version=version,
|
||||||
|
roaming=roaming,
|
||||||
|
ensure_exists=ensure_exists,
|
||||||
|
).user_config_dir
|
||||||
|
|
||||||
|
|
||||||
|
def site_config_dir(
|
||||||
|
appname: str | None = None,
|
||||||
|
appauthor: str | None | Literal[False] = None,
|
||||||
|
version: str | None = None,
|
||||||
|
multipath: bool = False, # noqa: FBT001, FBT002
|
||||||
|
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||||
|
) -> str:
|
||||||
|
"""
|
||||||
|
:param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
|
||||||
|
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
|
||||||
|
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
|
||||||
|
:param multipath: See `roaming <platformdirs.api.PlatformDirsABC.multipath>`.
|
||||||
|
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||||
|
:returns: config directory shared by the users
|
||||||
|
"""
|
||||||
|
return PlatformDirs(
|
||||||
|
appname=appname,
|
||||||
|
appauthor=appauthor,
|
||||||
|
version=version,
|
||||||
|
multipath=multipath,
|
||||||
|
ensure_exists=ensure_exists,
|
||||||
|
).site_config_dir
|
||||||
|
|
||||||
|
|
||||||
|
def user_cache_dir(
|
||||||
|
appname: str | None = None,
|
||||||
|
appauthor: str | None | Literal[False] = None,
|
||||||
|
version: str | None = None,
|
||||||
|
opinion: bool = True, # noqa: FBT001, FBT002
|
||||||
|
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||||
|
) -> str:
|
||||||
|
"""
|
||||||
|
:param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
|
||||||
|
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
|
||||||
|
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
|
||||||
|
:param opinion: See `roaming <platformdirs.api.PlatformDirsABC.opinion>`.
|
||||||
|
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||||
|
:returns: cache directory tied to the user
|
||||||
|
"""
|
||||||
|
return PlatformDirs(
|
||||||
|
appname=appname,
|
||||||
|
appauthor=appauthor,
|
||||||
|
version=version,
|
||||||
|
opinion=opinion,
|
||||||
|
ensure_exists=ensure_exists,
|
||||||
|
).user_cache_dir
|
||||||
|
|
||||||
|
|
||||||
|
def site_cache_dir(
|
||||||
|
appname: str | None = None,
|
||||||
|
appauthor: str | None | Literal[False] = None,
|
||||||
|
version: str | None = None,
|
||||||
|
opinion: bool = True, # noqa: FBT001, FBT002
|
||||||
|
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||||
|
) -> str:
|
||||||
|
"""
|
||||||
|
:param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
|
||||||
|
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
|
||||||
|
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
|
||||||
|
:param opinion: See `opinion <platformdirs.api.PlatformDirsABC.opinion>`.
|
||||||
|
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||||
|
:returns: cache directory tied to the user
|
||||||
|
"""
|
||||||
|
return PlatformDirs(
|
||||||
|
appname=appname,
|
||||||
|
appauthor=appauthor,
|
||||||
|
version=version,
|
||||||
|
opinion=opinion,
|
||||||
|
ensure_exists=ensure_exists,
|
||||||
|
).site_cache_dir
|
||||||
|
|
||||||
|
|
||||||
|
def user_state_dir(
|
||||||
|
appname: str | None = None,
|
||||||
|
appauthor: str | None | Literal[False] = None,
|
||||||
|
version: str | None = None,
|
||||||
|
roaming: bool = False, # noqa: FBT001, FBT002
|
||||||
|
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||||
|
) -> str:
|
||||||
|
"""
|
||||||
|
:param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
|
||||||
|
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
|
||||||
|
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
|
||||||
|
:param roaming: See `roaming <platformdirs.api.PlatformDirsABC.roaming>`.
|
||||||
|
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||||
|
:returns: state directory tied to the user
|
||||||
|
"""
|
||||||
|
return PlatformDirs(
|
||||||
|
appname=appname,
|
||||||
|
appauthor=appauthor,
|
||||||
|
version=version,
|
||||||
|
roaming=roaming,
|
||||||
|
ensure_exists=ensure_exists,
|
||||||
|
).user_state_dir
|
||||||
|
|
||||||
|
|
||||||
|
def user_log_dir(
|
||||||
|
appname: str | None = None,
|
||||||
|
appauthor: str | None | Literal[False] = None,
|
||||||
|
version: str | None = None,
|
||||||
|
opinion: bool = True, # noqa: FBT001, FBT002
|
||||||
|
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||||
|
) -> str:
|
||||||
|
"""
|
||||||
|
:param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
|
||||||
|
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
|
||||||
|
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
|
||||||
|
:param opinion: See `roaming <platformdirs.api.PlatformDirsABC.opinion>`.
|
||||||
|
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||||
|
:returns: log directory tied to the user
|
||||||
|
"""
|
||||||
|
return PlatformDirs(
|
||||||
|
appname=appname,
|
||||||
|
appauthor=appauthor,
|
||||||
|
version=version,
|
||||||
|
opinion=opinion,
|
||||||
|
ensure_exists=ensure_exists,
|
||||||
|
).user_log_dir
|
||||||
|
|
||||||
|
|
||||||
|
def user_documents_dir() -> str:
|
||||||
|
""":returns: documents directory tied to the user"""
|
||||||
|
return PlatformDirs().user_documents_dir
|
||||||
|
|
||||||
|
|
||||||
|
def user_downloads_dir() -> str:
|
||||||
|
""":returns: downloads directory tied to the user"""
|
||||||
|
return PlatformDirs().user_downloads_dir
|
||||||
|
|
||||||
|
|
||||||
|
def user_pictures_dir() -> str:
|
||||||
|
""":returns: pictures directory tied to the user"""
|
||||||
|
return PlatformDirs().user_pictures_dir
|
||||||
|
|
||||||
|
|
||||||
|
def user_videos_dir() -> str:
|
||||||
|
""":returns: videos directory tied to the user"""
|
||||||
|
return PlatformDirs().user_videos_dir
|
||||||
|
|
||||||
|
|
||||||
|
def user_music_dir() -> str:
|
||||||
|
""":returns: music directory tied to the user"""
|
||||||
|
return PlatformDirs().user_music_dir
|
||||||
|
|
||||||
|
|
||||||
|
def user_desktop_dir() -> str:
|
||||||
|
""":returns: desktop directory tied to the user"""
|
||||||
|
return PlatformDirs().user_desktop_dir
|
||||||
|
|
||||||
|
|
||||||
|
def user_runtime_dir(
|
||||||
|
appname: str | None = None,
|
||||||
|
appauthor: str | None | Literal[False] = None,
|
||||||
|
version: str | None = None,
|
||||||
|
opinion: bool = True, # noqa: FBT001, FBT002
|
||||||
|
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||||
|
) -> str:
|
||||||
|
"""
|
||||||
|
:param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
|
||||||
|
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
|
||||||
|
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
|
||||||
|
:param opinion: See `opinion <platformdirs.api.PlatformDirsABC.opinion>`.
|
||||||
|
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||||
|
:returns: runtime directory tied to the user
|
||||||
|
"""
|
||||||
|
return PlatformDirs(
|
||||||
|
appname=appname,
|
||||||
|
appauthor=appauthor,
|
||||||
|
version=version,
|
||||||
|
opinion=opinion,
|
||||||
|
ensure_exists=ensure_exists,
|
||||||
|
).user_runtime_dir
|
||||||
|
|
||||||
|
|
||||||
|
def site_runtime_dir(
|
||||||
|
appname: str | None = None,
|
||||||
|
appauthor: str | None | Literal[False] = None,
|
||||||
|
version: str | None = None,
|
||||||
|
opinion: bool = True, # noqa: FBT001, FBT002
|
||||||
|
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||||
|
) -> str:
|
||||||
|
"""
|
||||||
|
:param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
|
||||||
|
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
|
||||||
|
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
|
||||||
|
:param opinion: See `opinion <platformdirs.api.PlatformDirsABC.opinion>`.
|
||||||
|
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||||
|
:returns: runtime directory shared by users
|
||||||
|
"""
|
||||||
|
return PlatformDirs(
|
||||||
|
appname=appname,
|
||||||
|
appauthor=appauthor,
|
||||||
|
version=version,
|
||||||
|
opinion=opinion,
|
||||||
|
ensure_exists=ensure_exists,
|
||||||
|
).site_runtime_dir
|
||||||
|
|
||||||
|
|
||||||
|
def user_data_path(
|
||||||
|
appname: str | None = None,
|
||||||
|
appauthor: str | None | Literal[False] = None,
|
||||||
|
version: str | None = None,
|
||||||
|
roaming: bool = False, # noqa: FBT001, FBT002
|
||||||
|
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||||
|
) -> Path:
|
||||||
|
"""
|
||||||
|
:param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
|
||||||
|
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
|
||||||
|
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
|
||||||
|
:param roaming: See `roaming <platformdirs.api.PlatformDirsABC.roaming>`.
|
||||||
|
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||||
|
:returns: data path tied to the user
|
||||||
|
"""
|
||||||
|
return PlatformDirs(
|
||||||
|
appname=appname,
|
||||||
|
appauthor=appauthor,
|
||||||
|
version=version,
|
||||||
|
roaming=roaming,
|
||||||
|
ensure_exists=ensure_exists,
|
||||||
|
).user_data_path
|
||||||
|
|
||||||
|
|
||||||
|
def site_data_path(
|
||||||
|
appname: str | None = None,
|
||||||
|
appauthor: str | None | Literal[False] = None,
|
||||||
|
version: str | None = None,
|
||||||
|
multipath: bool = False, # noqa: FBT001, FBT002
|
||||||
|
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||||
|
) -> Path:
|
||||||
|
"""
|
||||||
|
:param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
|
||||||
|
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
|
||||||
|
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
|
||||||
|
:param multipath: See `multipath <platformdirs.api.PlatformDirsABC.multipath>`.
|
||||||
|
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||||
|
:returns: data path shared by users
|
||||||
|
"""
|
||||||
|
return PlatformDirs(
|
||||||
|
appname=appname,
|
||||||
|
appauthor=appauthor,
|
||||||
|
version=version,
|
||||||
|
multipath=multipath,
|
||||||
|
ensure_exists=ensure_exists,
|
||||||
|
).site_data_path
|
||||||
|
|
||||||
|
|
||||||
|
def user_config_path(
|
||||||
|
appname: str | None = None,
|
||||||
|
appauthor: str | None | Literal[False] = None,
|
||||||
|
version: str | None = None,
|
||||||
|
roaming: bool = False, # noqa: FBT001, FBT002
|
||||||
|
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||||
|
) -> Path:
|
||||||
|
"""
|
||||||
|
:param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
|
||||||
|
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
|
||||||
|
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
|
||||||
|
:param roaming: See `roaming <platformdirs.api.PlatformDirsABC.roaming>`.
|
||||||
|
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||||
|
:returns: config path tied to the user
|
||||||
|
"""
|
||||||
|
return PlatformDirs(
|
||||||
|
appname=appname,
|
||||||
|
appauthor=appauthor,
|
||||||
|
version=version,
|
||||||
|
roaming=roaming,
|
||||||
|
ensure_exists=ensure_exists,
|
||||||
|
).user_config_path
|
||||||
|
|
||||||
|
|
||||||
|
def site_config_path(
|
||||||
|
appname: str | None = None,
|
||||||
|
appauthor: str | None | Literal[False] = None,
|
||||||
|
version: str | None = None,
|
||||||
|
multipath: bool = False, # noqa: FBT001, FBT002
|
||||||
|
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||||
|
) -> Path:
|
||||||
|
"""
|
||||||
|
:param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
|
||||||
|
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
|
||||||
|
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
|
||||||
|
:param multipath: See `roaming <platformdirs.api.PlatformDirsABC.multipath>`.
|
||||||
|
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||||
|
:returns: config path shared by the users
|
||||||
|
"""
|
||||||
|
return PlatformDirs(
|
||||||
|
appname=appname,
|
||||||
|
appauthor=appauthor,
|
||||||
|
version=version,
|
||||||
|
multipath=multipath,
|
||||||
|
ensure_exists=ensure_exists,
|
||||||
|
).site_config_path
|
||||||
|
|
||||||
|
|
||||||
|
def site_cache_path(
|
||||||
|
appname: str | None = None,
|
||||||
|
appauthor: str | None | Literal[False] = None,
|
||||||
|
version: str | None = None,
|
||||||
|
opinion: bool = True, # noqa: FBT001, FBT002
|
||||||
|
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||||
|
) -> Path:
|
||||||
|
"""
|
||||||
|
:param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
|
||||||
|
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
|
||||||
|
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
|
||||||
|
:param opinion: See `opinion <platformdirs.api.PlatformDirsABC.opinion>`.
|
||||||
|
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||||
|
:returns: cache directory tied to the user
|
||||||
|
"""
|
||||||
|
return PlatformDirs(
|
||||||
|
appname=appname,
|
||||||
|
appauthor=appauthor,
|
||||||
|
version=version,
|
||||||
|
opinion=opinion,
|
||||||
|
ensure_exists=ensure_exists,
|
||||||
|
).site_cache_path
|
||||||
|
|
||||||
|
|
||||||
|
def user_cache_path(
|
||||||
|
appname: str | None = None,
|
||||||
|
appauthor: str | None | Literal[False] = None,
|
||||||
|
version: str | None = None,
|
||||||
|
opinion: bool = True, # noqa: FBT001, FBT002
|
||||||
|
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||||
|
) -> Path:
|
||||||
|
"""
|
||||||
|
:param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
|
||||||
|
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
|
||||||
|
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
|
||||||
|
:param opinion: See `roaming <platformdirs.api.PlatformDirsABC.opinion>`.
|
||||||
|
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||||
|
:returns: cache path tied to the user
|
||||||
|
"""
|
||||||
|
return PlatformDirs(
|
||||||
|
appname=appname,
|
||||||
|
appauthor=appauthor,
|
||||||
|
version=version,
|
||||||
|
opinion=opinion,
|
||||||
|
ensure_exists=ensure_exists,
|
||||||
|
).user_cache_path
|
||||||
|
|
||||||
|
|
||||||
|
def user_state_path(
|
||||||
|
appname: str | None = None,
|
||||||
|
appauthor: str | None | Literal[False] = None,
|
||||||
|
version: str | None = None,
|
||||||
|
roaming: bool = False, # noqa: FBT001, FBT002
|
||||||
|
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||||
|
) -> Path:
|
||||||
|
"""
|
||||||
|
:param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
|
||||||
|
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
|
||||||
|
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
|
||||||
|
:param roaming: See `roaming <platformdirs.api.PlatformDirsABC.roaming>`.
|
||||||
|
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||||
|
:returns: state path tied to the user
|
||||||
|
"""
|
||||||
|
return PlatformDirs(
|
||||||
|
appname=appname,
|
||||||
|
appauthor=appauthor,
|
||||||
|
version=version,
|
||||||
|
roaming=roaming,
|
||||||
|
ensure_exists=ensure_exists,
|
||||||
|
).user_state_path
|
||||||
|
|
||||||
|
|
||||||
|
def user_log_path(
|
||||||
|
appname: str | None = None,
|
||||||
|
appauthor: str | None | Literal[False] = None,
|
||||||
|
version: str | None = None,
|
||||||
|
opinion: bool = True, # noqa: FBT001, FBT002
|
||||||
|
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||||
|
) -> Path:
|
||||||
|
"""
|
||||||
|
:param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
|
||||||
|
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
|
||||||
|
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
|
||||||
|
:param opinion: See `roaming <platformdirs.api.PlatformDirsABC.opinion>`.
|
||||||
|
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||||
|
:returns: log path tied to the user
|
||||||
|
"""
|
||||||
|
return PlatformDirs(
|
||||||
|
appname=appname,
|
||||||
|
appauthor=appauthor,
|
||||||
|
version=version,
|
||||||
|
opinion=opinion,
|
||||||
|
ensure_exists=ensure_exists,
|
||||||
|
).user_log_path
|
||||||
|
|
||||||
|
|
||||||
|
def user_documents_path() -> Path:
|
||||||
|
""":returns: documents a path tied to the user"""
|
||||||
|
return PlatformDirs().user_documents_path
|
||||||
|
|
||||||
|
|
||||||
|
def user_downloads_path() -> Path:
|
||||||
|
""":returns: downloads path tied to the user"""
|
||||||
|
return PlatformDirs().user_downloads_path
|
||||||
|
|
||||||
|
|
||||||
|
def user_pictures_path() -> Path:
|
||||||
|
""":returns: pictures path tied to the user"""
|
||||||
|
return PlatformDirs().user_pictures_path
|
||||||
|
|
||||||
|
|
||||||
|
def user_videos_path() -> Path:
|
||||||
|
""":returns: videos path tied to the user"""
|
||||||
|
return PlatformDirs().user_videos_path
|
||||||
|
|
||||||
|
|
||||||
|
def user_music_path() -> Path:
|
||||||
|
""":returns: music path tied to the user"""
|
||||||
|
return PlatformDirs().user_music_path
|
||||||
|
|
||||||
|
|
||||||
|
def user_desktop_path() -> Path:
|
||||||
|
""":returns: desktop path tied to the user"""
|
||||||
|
return PlatformDirs().user_desktop_path
|
||||||
|
|
||||||
|
|
||||||
|
def user_runtime_path(
|
||||||
|
appname: str | None = None,
|
||||||
|
appauthor: str | None | Literal[False] = None,
|
||||||
|
version: str | None = None,
|
||||||
|
opinion: bool = True, # noqa: FBT001, FBT002
|
||||||
|
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||||
|
) -> Path:
|
||||||
|
"""
|
||||||
|
:param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
|
||||||
|
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
|
||||||
|
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
|
||||||
|
:param opinion: See `opinion <platformdirs.api.PlatformDirsABC.opinion>`.
|
||||||
|
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||||
|
:returns: runtime path tied to the user
|
||||||
|
"""
|
||||||
|
return PlatformDirs(
|
||||||
|
appname=appname,
|
||||||
|
appauthor=appauthor,
|
||||||
|
version=version,
|
||||||
|
opinion=opinion,
|
||||||
|
ensure_exists=ensure_exists,
|
||||||
|
).user_runtime_path
|
||||||
|
|
||||||
|
|
||||||
|
def site_runtime_path(
|
||||||
|
appname: str | None = None,
|
||||||
|
appauthor: str | None | Literal[False] = None,
|
||||||
|
version: str | None = None,
|
||||||
|
opinion: bool = True, # noqa: FBT001, FBT002
|
||||||
|
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||||
|
) -> Path:
|
||||||
|
"""
|
||||||
|
:param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
|
||||||
|
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
|
||||||
|
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
|
||||||
|
:param opinion: See `opinion <platformdirs.api.PlatformDirsABC.opinion>`.
|
||||||
|
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||||
|
:returns: runtime path shared by users
|
||||||
|
"""
|
||||||
|
return PlatformDirs(
|
||||||
|
appname=appname,
|
||||||
|
appauthor=appauthor,
|
||||||
|
version=version,
|
||||||
|
opinion=opinion,
|
||||||
|
ensure_exists=ensure_exists,
|
||||||
|
).site_runtime_path
|
||||||
|
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"AppDirs",
|
||||||
|
"PlatformDirs",
|
||||||
|
"PlatformDirsABC",
|
||||||
|
"__version__",
|
||||||
|
"__version_info__",
|
||||||
|
"site_cache_dir",
|
||||||
|
"site_cache_path",
|
||||||
|
"site_config_dir",
|
||||||
|
"site_config_path",
|
||||||
|
"site_data_dir",
|
||||||
|
"site_data_path",
|
||||||
|
"site_runtime_dir",
|
||||||
|
"site_runtime_path",
|
||||||
|
"user_cache_dir",
|
||||||
|
"user_cache_path",
|
||||||
|
"user_config_dir",
|
||||||
|
"user_config_path",
|
||||||
|
"user_data_dir",
|
||||||
|
"user_data_path",
|
||||||
|
"user_desktop_dir",
|
||||||
|
"user_desktop_path",
|
||||||
|
"user_documents_dir",
|
||||||
|
"user_documents_path",
|
||||||
|
"user_downloads_dir",
|
||||||
|
"user_downloads_path",
|
||||||
|
"user_log_dir",
|
||||||
|
"user_log_path",
|
||||||
|
"user_music_dir",
|
||||||
|
"user_music_path",
|
||||||
|
"user_pictures_dir",
|
||||||
|
"user_pictures_path",
|
||||||
|
"user_runtime_dir",
|
||||||
|
"user_runtime_path",
|
||||||
|
"user_state_dir",
|
||||||
|
"user_state_path",
|
||||||
|
"user_videos_dir",
|
||||||
|
"user_videos_path",
|
||||||
|
]
|
||||||
55
third_party/python/platformdirs/platformdirs/__main__.py
vendored
Normal file
55
third_party/python/platformdirs/platformdirs/__main__.py
vendored
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
"""Main entry point."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from platformdirs import PlatformDirs, __version__
|
||||||
|
|
||||||
|
PROPS = (
|
||||||
|
"user_data_dir",
|
||||||
|
"user_config_dir",
|
||||||
|
"user_cache_dir",
|
||||||
|
"user_state_dir",
|
||||||
|
"user_log_dir",
|
||||||
|
"user_documents_dir",
|
||||||
|
"user_downloads_dir",
|
||||||
|
"user_pictures_dir",
|
||||||
|
"user_videos_dir",
|
||||||
|
"user_music_dir",
|
||||||
|
"user_runtime_dir",
|
||||||
|
"site_data_dir",
|
||||||
|
"site_config_dir",
|
||||||
|
"site_cache_dir",
|
||||||
|
"site_runtime_dir",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
"""Run the main entry point."""
|
||||||
|
app_name = "MyApp"
|
||||||
|
app_author = "MyCompany"
|
||||||
|
|
||||||
|
print(f"-- platformdirs {__version__} --") # noqa: T201
|
||||||
|
|
||||||
|
print("-- app dirs (with optional 'version')") # noqa: T201
|
||||||
|
dirs = PlatformDirs(app_name, app_author, version="1.0")
|
||||||
|
for prop in PROPS:
|
||||||
|
print(f"{prop}: {getattr(dirs, prop)}") # noqa: T201
|
||||||
|
|
||||||
|
print("\n-- app dirs (without optional 'version')") # noqa: T201
|
||||||
|
dirs = PlatformDirs(app_name, app_author)
|
||||||
|
for prop in PROPS:
|
||||||
|
print(f"{prop}: {getattr(dirs, prop)}") # noqa: T201
|
||||||
|
|
||||||
|
print("\n-- app dirs (without optional 'appauthor')") # noqa: T201
|
||||||
|
dirs = PlatformDirs(app_name)
|
||||||
|
for prop in PROPS:
|
||||||
|
print(f"{prop}: {getattr(dirs, prop)}") # noqa: T201
|
||||||
|
|
||||||
|
print("\n-- app dirs (with disabled 'appauthor')") # noqa: T201
|
||||||
|
dirs = PlatformDirs(app_name, appauthor=False)
|
||||||
|
for prop in PROPS:
|
||||||
|
print(f"{prop}: {getattr(dirs, prop)}") # noqa: T201
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
249
third_party/python/platformdirs/platformdirs/android.py
vendored
Normal file
249
third_party/python/platformdirs/platformdirs/android.py
vendored
Normal file
@@ -0,0 +1,249 @@
|
|||||||
|
"""Android."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
from functools import lru_cache
|
||||||
|
from typing import TYPE_CHECKING, cast
|
||||||
|
|
||||||
|
from .api import PlatformDirsABC
|
||||||
|
|
||||||
|
|
||||||
|
class Android(PlatformDirsABC):
|
||||||
|
"""
|
||||||
|
Follows the guidance `from here <https://android.stackexchange.com/a/216132>`_.
|
||||||
|
|
||||||
|
Makes use of the `appname <platformdirs.api.PlatformDirsABC.appname>`, `version
|
||||||
|
<platformdirs.api.PlatformDirsABC.version>`, `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_data_dir(self) -> str:
|
||||||
|
""":return: data directory tied to the user, e.g. ``/data/user/<userid>/<packagename>/files/<AppName>``"""
|
||||||
|
return self._append_app_name_and_version(cast(str, _android_folder()), "files")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def site_data_dir(self) -> str:
|
||||||
|
""":return: data directory shared by users, same as `user_data_dir`"""
|
||||||
|
return self.user_data_dir
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_config_dir(self) -> str:
|
||||||
|
"""
|
||||||
|
:return: config directory tied to the user, e.g. \
|
||||||
|
``/data/user/<userid>/<packagename>/shared_prefs/<AppName>``
|
||||||
|
"""
|
||||||
|
return self._append_app_name_and_version(cast(str, _android_folder()), "shared_prefs")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def site_config_dir(self) -> str:
|
||||||
|
""":return: config directory shared by the users, same as `user_config_dir`"""
|
||||||
|
return self.user_config_dir
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_cache_dir(self) -> str:
|
||||||
|
""":return: cache directory tied to the user, e.g.,``/data/user/<userid>/<packagename>/cache/<AppName>``"""
|
||||||
|
return self._append_app_name_and_version(cast(str, _android_folder()), "cache")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def site_cache_dir(self) -> str:
|
||||||
|
""":return: cache directory shared by users, same as `user_cache_dir`"""
|
||||||
|
return self.user_cache_dir
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_state_dir(self) -> str:
|
||||||
|
""":return: state directory tied to the user, same as `user_data_dir`"""
|
||||||
|
return self.user_data_dir
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_log_dir(self) -> str:
|
||||||
|
"""
|
||||||
|
:return: log directory tied to the user, same as `user_cache_dir` if not opinionated else ``log`` in it,
|
||||||
|
e.g. ``/data/user/<userid>/<packagename>/cache/<AppName>/log``
|
||||||
|
"""
|
||||||
|
path = self.user_cache_dir
|
||||||
|
if self.opinion:
|
||||||
|
path = os.path.join(path, "log") # noqa: PTH118
|
||||||
|
return path
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_documents_dir(self) -> str:
|
||||||
|
""":return: documents directory tied to the user e.g. ``/storage/emulated/0/Documents``"""
|
||||||
|
return _android_documents_folder()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_downloads_dir(self) -> str:
|
||||||
|
""":return: downloads directory tied to the user e.g. ``/storage/emulated/0/Downloads``"""
|
||||||
|
return _android_downloads_folder()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_pictures_dir(self) -> str:
|
||||||
|
""":return: pictures directory tied to the user e.g. ``/storage/emulated/0/Pictures``"""
|
||||||
|
return _android_pictures_folder()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_videos_dir(self) -> str:
|
||||||
|
""":return: videos directory tied to the user e.g. ``/storage/emulated/0/DCIM/Camera``"""
|
||||||
|
return _android_videos_folder()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_music_dir(self) -> str:
|
||||||
|
""":return: music directory tied to the user e.g. ``/storage/emulated/0/Music``"""
|
||||||
|
return _android_music_folder()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_desktop_dir(self) -> str:
|
||||||
|
""":return: desktop directory tied to the user e.g. ``/storage/emulated/0/Desktop``"""
|
||||||
|
return "/storage/emulated/0/Desktop"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_runtime_dir(self) -> str:
|
||||||
|
"""
|
||||||
|
:return: runtime directory tied to the user, same as `user_cache_dir` if not opinionated else ``tmp`` in it,
|
||||||
|
e.g. ``/data/user/<userid>/<packagename>/cache/<AppName>/tmp``
|
||||||
|
"""
|
||||||
|
path = self.user_cache_dir
|
||||||
|
if self.opinion:
|
||||||
|
path = os.path.join(path, "tmp") # noqa: PTH118
|
||||||
|
return path
|
||||||
|
|
||||||
|
@property
|
||||||
|
def site_runtime_dir(self) -> str:
|
||||||
|
""":return: runtime directory shared by users, same as `user_runtime_dir`"""
|
||||||
|
return self.user_runtime_dir
|
||||||
|
|
||||||
|
|
||||||
|
@lru_cache(maxsize=1)
|
||||||
|
def _android_folder() -> str | None: # noqa: C901
|
||||||
|
""":return: base folder for the Android OS or None if it cannot be found"""
|
||||||
|
result: str | None = None
|
||||||
|
# type checker isn't happy with our "import android", just don't do this when type checking see
|
||||||
|
# https://stackoverflow.com/a/61394121
|
||||||
|
if not TYPE_CHECKING:
|
||||||
|
try:
|
||||||
|
# First try to get a path to android app using python4android (if available)...
|
||||||
|
from android import mActivity # noqa: PLC0415
|
||||||
|
|
||||||
|
context = cast("android.content.Context", mActivity.getApplicationContext()) # noqa: F821
|
||||||
|
result = context.getFilesDir().getParentFile().getAbsolutePath()
|
||||||
|
except Exception: # noqa: BLE001
|
||||||
|
result = None
|
||||||
|
if result is None:
|
||||||
|
try:
|
||||||
|
# ...and fall back to using plain pyjnius, if python4android isn't available or doesn't deliver any useful
|
||||||
|
# result...
|
||||||
|
from jnius import autoclass # noqa: PLC0415
|
||||||
|
|
||||||
|
context = autoclass("android.content.Context")
|
||||||
|
result = context.getFilesDir().getParentFile().getAbsolutePath()
|
||||||
|
except Exception: # noqa: BLE001
|
||||||
|
result = None
|
||||||
|
if result is None:
|
||||||
|
# and if that fails, too, find an android folder looking at path on the sys.path
|
||||||
|
# warning: only works for apps installed under /data, not adopted storage etc.
|
||||||
|
pattern = re.compile(r"/data/(data|user/\d+)/(.+)/files")
|
||||||
|
for path in sys.path:
|
||||||
|
if pattern.match(path):
|
||||||
|
result = path.split("/files")[0]
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
result = None
|
||||||
|
if result is None:
|
||||||
|
# one last try: find an android folder looking at path on the sys.path taking adopted storage paths into
|
||||||
|
# account
|
||||||
|
pattern = re.compile(r"/mnt/expand/[a-fA-F0-9-]{36}/(data|user/\d+)/(.+)/files")
|
||||||
|
for path in sys.path:
|
||||||
|
if pattern.match(path):
|
||||||
|
result = path.split("/files")[0]
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
result = None
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
@lru_cache(maxsize=1)
|
||||||
|
def _android_documents_folder() -> str:
|
||||||
|
""":return: documents folder for the Android OS"""
|
||||||
|
# Get directories with pyjnius
|
||||||
|
try:
|
||||||
|
from jnius import autoclass # noqa: PLC0415
|
||||||
|
|
||||||
|
context = autoclass("android.content.Context")
|
||||||
|
environment = autoclass("android.os.Environment")
|
||||||
|
documents_dir: str = context.getExternalFilesDir(environment.DIRECTORY_DOCUMENTS).getAbsolutePath()
|
||||||
|
except Exception: # noqa: BLE001
|
||||||
|
documents_dir = "/storage/emulated/0/Documents"
|
||||||
|
|
||||||
|
return documents_dir
|
||||||
|
|
||||||
|
|
||||||
|
@lru_cache(maxsize=1)
|
||||||
|
def _android_downloads_folder() -> str:
|
||||||
|
""":return: downloads folder for the Android OS"""
|
||||||
|
# Get directories with pyjnius
|
||||||
|
try:
|
||||||
|
from jnius import autoclass # noqa: PLC0415
|
||||||
|
|
||||||
|
context = autoclass("android.content.Context")
|
||||||
|
environment = autoclass("android.os.Environment")
|
||||||
|
downloads_dir: str = context.getExternalFilesDir(environment.DIRECTORY_DOWNLOADS).getAbsolutePath()
|
||||||
|
except Exception: # noqa: BLE001
|
||||||
|
downloads_dir = "/storage/emulated/0/Downloads"
|
||||||
|
|
||||||
|
return downloads_dir
|
||||||
|
|
||||||
|
|
||||||
|
@lru_cache(maxsize=1)
|
||||||
|
def _android_pictures_folder() -> str:
|
||||||
|
""":return: pictures folder for the Android OS"""
|
||||||
|
# Get directories with pyjnius
|
||||||
|
try:
|
||||||
|
from jnius import autoclass # noqa: PLC0415
|
||||||
|
|
||||||
|
context = autoclass("android.content.Context")
|
||||||
|
environment = autoclass("android.os.Environment")
|
||||||
|
pictures_dir: str = context.getExternalFilesDir(environment.DIRECTORY_PICTURES).getAbsolutePath()
|
||||||
|
except Exception: # noqa: BLE001
|
||||||
|
pictures_dir = "/storage/emulated/0/Pictures"
|
||||||
|
|
||||||
|
return pictures_dir
|
||||||
|
|
||||||
|
|
||||||
|
@lru_cache(maxsize=1)
|
||||||
|
def _android_videos_folder() -> str:
|
||||||
|
""":return: videos folder for the Android OS"""
|
||||||
|
# Get directories with pyjnius
|
||||||
|
try:
|
||||||
|
from jnius import autoclass # noqa: PLC0415
|
||||||
|
|
||||||
|
context = autoclass("android.content.Context")
|
||||||
|
environment = autoclass("android.os.Environment")
|
||||||
|
videos_dir: str = context.getExternalFilesDir(environment.DIRECTORY_DCIM).getAbsolutePath()
|
||||||
|
except Exception: # noqa: BLE001
|
||||||
|
videos_dir = "/storage/emulated/0/DCIM/Camera"
|
||||||
|
|
||||||
|
return videos_dir
|
||||||
|
|
||||||
|
|
||||||
|
@lru_cache(maxsize=1)
|
||||||
|
def _android_music_folder() -> str:
|
||||||
|
""":return: music folder for the Android OS"""
|
||||||
|
# Get directories with pyjnius
|
||||||
|
try:
|
||||||
|
from jnius import autoclass # noqa: PLC0415
|
||||||
|
|
||||||
|
context = autoclass("android.content.Context")
|
||||||
|
environment = autoclass("android.os.Environment")
|
||||||
|
music_dir: str = context.getExternalFilesDir(environment.DIRECTORY_MUSIC).getAbsolutePath()
|
||||||
|
except Exception: # noqa: BLE001
|
||||||
|
music_dir = "/storage/emulated/0/Music"
|
||||||
|
|
||||||
|
return music_dir
|
||||||
|
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"Android",
|
||||||
|
]
|
||||||
298
third_party/python/platformdirs/platformdirs/api.py
vendored
Normal file
298
third_party/python/platformdirs/platformdirs/api.py
vendored
Normal file
@@ -0,0 +1,298 @@
|
|||||||
|
"""Base API."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import os
|
||||||
|
from abc import ABC, abstractmethod
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from typing import Iterator, Literal
|
||||||
|
|
||||||
|
|
||||||
|
class PlatformDirsABC(ABC): # noqa: PLR0904
|
||||||
|
"""Abstract base class for platform directories."""
|
||||||
|
|
||||||
|
def __init__( # noqa: PLR0913, PLR0917
|
||||||
|
self,
|
||||||
|
appname: str | None = None,
|
||||||
|
appauthor: str | None | Literal[False] = None,
|
||||||
|
version: str | None = None,
|
||||||
|
roaming: bool = False, # noqa: FBT001, FBT002
|
||||||
|
multipath: bool = False, # noqa: FBT001, FBT002
|
||||||
|
opinion: bool = True, # noqa: FBT001, FBT002
|
||||||
|
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||||
|
) -> None:
|
||||||
|
"""
|
||||||
|
Create a new platform directory.
|
||||||
|
|
||||||
|
:param appname: See `appname`.
|
||||||
|
:param appauthor: See `appauthor`.
|
||||||
|
:param version: See `version`.
|
||||||
|
:param roaming: See `roaming`.
|
||||||
|
:param multipath: See `multipath`.
|
||||||
|
:param opinion: See `opinion`.
|
||||||
|
:param ensure_exists: See `ensure_exists`.
|
||||||
|
|
||||||
|
"""
|
||||||
|
self.appname = appname #: The name of application.
|
||||||
|
self.appauthor = appauthor
|
||||||
|
"""
|
||||||
|
The name of the app author or distributing body for this application.
|
||||||
|
|
||||||
|
Typically, it is the owning company name. Defaults to `appname`. You may pass ``False`` to disable it.
|
||||||
|
|
||||||
|
"""
|
||||||
|
self.version = version
|
||||||
|
"""
|
||||||
|
An optional version path element to append to the path.
|
||||||
|
|
||||||
|
You might want to use this if you want multiple versions of your app to be able to run independently. If used,
|
||||||
|
this would typically be ``<major>.<minor>``.
|
||||||
|
|
||||||
|
"""
|
||||||
|
self.roaming = roaming
|
||||||
|
"""
|
||||||
|
Whether to use the roaming appdata directory on Windows.
|
||||||
|
|
||||||
|
That means that for users on a Windows network setup for roaming profiles, this user data will be synced on
|
||||||
|
login (see
|
||||||
|
`here <https://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx>`_).
|
||||||
|
|
||||||
|
"""
|
||||||
|
self.multipath = multipath
|
||||||
|
"""
|
||||||
|
An optional parameter which indicates that the entire list of data dirs should be returned.
|
||||||
|
|
||||||
|
By default, the first item would only be returned.
|
||||||
|
|
||||||
|
"""
|
||||||
|
self.opinion = opinion #: A flag to indicating to use opinionated values.
|
||||||
|
self.ensure_exists = ensure_exists
|
||||||
|
"""
|
||||||
|
Optionally create the directory (and any missing parents) upon access if it does not exist.
|
||||||
|
|
||||||
|
By default, no directories are created.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
def _append_app_name_and_version(self, *base: str) -> str:
|
||||||
|
params = list(base[1:])
|
||||||
|
if self.appname:
|
||||||
|
params.append(self.appname)
|
||||||
|
if self.version:
|
||||||
|
params.append(self.version)
|
||||||
|
path = os.path.join(base[0], *params) # noqa: PTH118
|
||||||
|
self._optionally_create_directory(path)
|
||||||
|
return path
|
||||||
|
|
||||||
|
def _optionally_create_directory(self, path: str) -> None:
|
||||||
|
if self.ensure_exists:
|
||||||
|
Path(path).mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
def _first_item_as_path_if_multipath(self, directory: str) -> Path:
|
||||||
|
if self.multipath:
|
||||||
|
# If multipath is True, the first path is returned.
|
||||||
|
directory = directory.split(os.pathsep)[0]
|
||||||
|
return Path(directory)
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def user_data_dir(self) -> str:
|
||||||
|
""":return: data directory tied to the user"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def site_data_dir(self) -> str:
|
||||||
|
""":return: data directory shared by users"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def user_config_dir(self) -> str:
|
||||||
|
""":return: config directory tied to the user"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def site_config_dir(self) -> str:
|
||||||
|
""":return: config directory shared by the users"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def user_cache_dir(self) -> str:
|
||||||
|
""":return: cache directory tied to the user"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def site_cache_dir(self) -> str:
|
||||||
|
""":return: cache directory shared by users"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def user_state_dir(self) -> str:
|
||||||
|
""":return: state directory tied to the user"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def user_log_dir(self) -> str:
|
||||||
|
""":return: log directory tied to the user"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def user_documents_dir(self) -> str:
|
||||||
|
""":return: documents directory tied to the user"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def user_downloads_dir(self) -> str:
|
||||||
|
""":return: downloads directory tied to the user"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def user_pictures_dir(self) -> str:
|
||||||
|
""":return: pictures directory tied to the user"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def user_videos_dir(self) -> str:
|
||||||
|
""":return: videos directory tied to the user"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def user_music_dir(self) -> str:
|
||||||
|
""":return: music directory tied to the user"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def user_desktop_dir(self) -> str:
|
||||||
|
""":return: desktop directory tied to the user"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def user_runtime_dir(self) -> str:
|
||||||
|
""":return: runtime directory tied to the user"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def site_runtime_dir(self) -> str:
|
||||||
|
""":return: runtime directory shared by users"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_data_path(self) -> Path:
|
||||||
|
""":return: data path tied to the user"""
|
||||||
|
return Path(self.user_data_dir)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def site_data_path(self) -> Path:
|
||||||
|
""":return: data path shared by users"""
|
||||||
|
return Path(self.site_data_dir)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_config_path(self) -> Path:
|
||||||
|
""":return: config path tied to the user"""
|
||||||
|
return Path(self.user_config_dir)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def site_config_path(self) -> Path:
|
||||||
|
""":return: config path shared by the users"""
|
||||||
|
return Path(self.site_config_dir)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_cache_path(self) -> Path:
|
||||||
|
""":return: cache path tied to the user"""
|
||||||
|
return Path(self.user_cache_dir)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def site_cache_path(self) -> Path:
|
||||||
|
""":return: cache path shared by users"""
|
||||||
|
return Path(self.site_cache_dir)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_state_path(self) -> Path:
|
||||||
|
""":return: state path tied to the user"""
|
||||||
|
return Path(self.user_state_dir)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_log_path(self) -> Path:
|
||||||
|
""":return: log path tied to the user"""
|
||||||
|
return Path(self.user_log_dir)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_documents_path(self) -> Path:
|
||||||
|
""":return: documents a path tied to the user"""
|
||||||
|
return Path(self.user_documents_dir)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_downloads_path(self) -> Path:
|
||||||
|
""":return: downloads path tied to the user"""
|
||||||
|
return Path(self.user_downloads_dir)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_pictures_path(self) -> Path:
|
||||||
|
""":return: pictures path tied to the user"""
|
||||||
|
return Path(self.user_pictures_dir)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_videos_path(self) -> Path:
|
||||||
|
""":return: videos path tied to the user"""
|
||||||
|
return Path(self.user_videos_dir)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_music_path(self) -> Path:
|
||||||
|
""":return: music path tied to the user"""
|
||||||
|
return Path(self.user_music_dir)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_desktop_path(self) -> Path:
|
||||||
|
""":return: desktop path tied to the user"""
|
||||||
|
return Path(self.user_desktop_dir)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_runtime_path(self) -> Path:
|
||||||
|
""":return: runtime path tied to the user"""
|
||||||
|
return Path(self.user_runtime_dir)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def site_runtime_path(self) -> Path:
|
||||||
|
""":return: runtime path shared by users"""
|
||||||
|
return Path(self.site_runtime_dir)
|
||||||
|
|
||||||
|
def iter_config_dirs(self) -> Iterator[str]:
|
||||||
|
""":yield: all user and site configuration directories."""
|
||||||
|
yield self.user_config_dir
|
||||||
|
yield self.site_config_dir
|
||||||
|
|
||||||
|
def iter_data_dirs(self) -> Iterator[str]:
|
||||||
|
""":yield: all user and site data directories."""
|
||||||
|
yield self.user_data_dir
|
||||||
|
yield self.site_data_dir
|
||||||
|
|
||||||
|
def iter_cache_dirs(self) -> Iterator[str]:
|
||||||
|
""":yield: all user and site cache directories."""
|
||||||
|
yield self.user_cache_dir
|
||||||
|
yield self.site_cache_dir
|
||||||
|
|
||||||
|
def iter_runtime_dirs(self) -> Iterator[str]:
|
||||||
|
""":yield: all user and site runtime directories."""
|
||||||
|
yield self.user_runtime_dir
|
||||||
|
yield self.site_runtime_dir
|
||||||
|
|
||||||
|
def iter_config_paths(self) -> Iterator[Path]:
|
||||||
|
""":yield: all user and site configuration paths."""
|
||||||
|
for path in self.iter_config_dirs():
|
||||||
|
yield Path(path)
|
||||||
|
|
||||||
|
def iter_data_paths(self) -> Iterator[Path]:
|
||||||
|
""":yield: all user and site data paths."""
|
||||||
|
for path in self.iter_data_dirs():
|
||||||
|
yield Path(path)
|
||||||
|
|
||||||
|
def iter_cache_paths(self) -> Iterator[Path]:
|
||||||
|
""":yield: all user and site cache paths."""
|
||||||
|
for path in self.iter_cache_dirs():
|
||||||
|
yield Path(path)
|
||||||
|
|
||||||
|
def iter_runtime_paths(self) -> Iterator[Path]:
|
||||||
|
""":yield: all user and site runtime paths."""
|
||||||
|
for path in self.iter_runtime_dirs():
|
||||||
|
yield Path(path)
|
||||||
144
third_party/python/platformdirs/platformdirs/macos.py
vendored
Normal file
144
third_party/python/platformdirs/platformdirs/macos.py
vendored
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
"""macOS."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import os.path
|
||||||
|
import sys
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
from .api import PlatformDirsABC
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
class MacOS(PlatformDirsABC):
|
||||||
|
"""
|
||||||
|
Platform directories for the macOS operating system.
|
||||||
|
|
||||||
|
Follows the guidance from
|
||||||
|
`Apple documentation <https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/MacOSXDirectories/MacOSXDirectories.html>`_.
|
||||||
|
Makes use of the `appname <platformdirs.api.PlatformDirsABC.appname>`,
|
||||||
|
`version <platformdirs.api.PlatformDirsABC.version>`,
|
||||||
|
`ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_data_dir(self) -> str:
|
||||||
|
""":return: data directory tied to the user, e.g. ``~/Library/Application Support/$appname/$version``"""
|
||||||
|
return self._append_app_name_and_version(os.path.expanduser("~/Library/Application Support")) # noqa: PTH111
|
||||||
|
|
||||||
|
@property
|
||||||
|
def site_data_dir(self) -> str:
|
||||||
|
"""
|
||||||
|
:return: data directory shared by users, e.g. ``/Library/Application Support/$appname/$version``.
|
||||||
|
If we're using a Python binary managed by `Homebrew <https://brew.sh>`_, the directory
|
||||||
|
will be under the Homebrew prefix, e.g. ``/opt/homebrew/share/$appname/$version``.
|
||||||
|
If `multipath <platformdirs.api.PlatformDirsABC.multipath>` is enabled, and we're in Homebrew,
|
||||||
|
the response is a multi-path string separated by ":", e.g.
|
||||||
|
``/opt/homebrew/share/$appname/$version:/Library/Application Support/$appname/$version``
|
||||||
|
"""
|
||||||
|
is_homebrew = sys.prefix.startswith("/opt/homebrew")
|
||||||
|
path_list = [self._append_app_name_and_version("/opt/homebrew/share")] if is_homebrew else []
|
||||||
|
path_list.append(self._append_app_name_and_version("/Library/Application Support"))
|
||||||
|
if self.multipath:
|
||||||
|
return os.pathsep.join(path_list)
|
||||||
|
return path_list[0]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def site_data_path(self) -> Path:
|
||||||
|
""":return: data path shared by users. Only return the first item, even if ``multipath`` is set to ``True``"""
|
||||||
|
return self._first_item_as_path_if_multipath(self.site_data_dir)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_config_dir(self) -> str:
|
||||||
|
""":return: config directory tied to the user, same as `user_data_dir`"""
|
||||||
|
return self.user_data_dir
|
||||||
|
|
||||||
|
@property
|
||||||
|
def site_config_dir(self) -> str:
|
||||||
|
""":return: config directory shared by the users, same as `site_data_dir`"""
|
||||||
|
return self.site_data_dir
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_cache_dir(self) -> str:
|
||||||
|
""":return: cache directory tied to the user, e.g. ``~/Library/Caches/$appname/$version``"""
|
||||||
|
return self._append_app_name_and_version(os.path.expanduser("~/Library/Caches")) # noqa: PTH111
|
||||||
|
|
||||||
|
@property
|
||||||
|
def site_cache_dir(self) -> str:
|
||||||
|
"""
|
||||||
|
:return: cache directory shared by users, e.g. ``/Library/Caches/$appname/$version``.
|
||||||
|
If we're using a Python binary managed by `Homebrew <https://brew.sh>`_, the directory
|
||||||
|
will be under the Homebrew prefix, e.g. ``/opt/homebrew/var/cache/$appname/$version``.
|
||||||
|
If `multipath <platformdirs.api.PlatformDirsABC.multipath>` is enabled, and we're in Homebrew,
|
||||||
|
the response is a multi-path string separated by ":", e.g.
|
||||||
|
``/opt/homebrew/var/cache/$appname/$version:/Library/Caches/$appname/$version``
|
||||||
|
"""
|
||||||
|
is_homebrew = sys.prefix.startswith("/opt/homebrew")
|
||||||
|
path_list = [self._append_app_name_and_version("/opt/homebrew/var/cache")] if is_homebrew else []
|
||||||
|
path_list.append(self._append_app_name_and_version("/Library/Caches"))
|
||||||
|
if self.multipath:
|
||||||
|
return os.pathsep.join(path_list)
|
||||||
|
return path_list[0]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def site_cache_path(self) -> Path:
|
||||||
|
""":return: cache path shared by users. Only return the first item, even if ``multipath`` is set to ``True``"""
|
||||||
|
return self._first_item_as_path_if_multipath(self.site_cache_dir)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_state_dir(self) -> str:
|
||||||
|
""":return: state directory tied to the user, same as `user_data_dir`"""
|
||||||
|
return self.user_data_dir
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_log_dir(self) -> str:
|
||||||
|
""":return: log directory tied to the user, e.g. ``~/Library/Logs/$appname/$version``"""
|
||||||
|
return self._append_app_name_and_version(os.path.expanduser("~/Library/Logs")) # noqa: PTH111
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_documents_dir(self) -> str:
|
||||||
|
""":return: documents directory tied to the user, e.g. ``~/Documents``"""
|
||||||
|
return os.path.expanduser("~/Documents") # noqa: PTH111
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_downloads_dir(self) -> str:
|
||||||
|
""":return: downloads directory tied to the user, e.g. ``~/Downloads``"""
|
||||||
|
return os.path.expanduser("~/Downloads") # noqa: PTH111
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_pictures_dir(self) -> str:
|
||||||
|
""":return: pictures directory tied to the user, e.g. ``~/Pictures``"""
|
||||||
|
return os.path.expanduser("~/Pictures") # noqa: PTH111
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_videos_dir(self) -> str:
|
||||||
|
""":return: videos directory tied to the user, e.g. ``~/Movies``"""
|
||||||
|
return os.path.expanduser("~/Movies") # noqa: PTH111
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_music_dir(self) -> str:
|
||||||
|
""":return: music directory tied to the user, e.g. ``~/Music``"""
|
||||||
|
return os.path.expanduser("~/Music") # noqa: PTH111
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_desktop_dir(self) -> str:
|
||||||
|
""":return: desktop directory tied to the user, e.g. ``~/Desktop``"""
|
||||||
|
return os.path.expanduser("~/Desktop") # noqa: PTH111
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_runtime_dir(self) -> str:
|
||||||
|
""":return: runtime directory tied to the user, e.g. ``~/Library/Caches/TemporaryItems/$appname/$version``"""
|
||||||
|
return self._append_app_name_and_version(os.path.expanduser("~/Library/Caches/TemporaryItems")) # noqa: PTH111
|
||||||
|
|
||||||
|
@property
|
||||||
|
def site_runtime_dir(self) -> str:
|
||||||
|
""":return: runtime directory shared by users, same as `user_runtime_dir`"""
|
||||||
|
return self.user_runtime_dir
|
||||||
|
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"MacOS",
|
||||||
|
]
|
||||||
0
third_party/python/platformdirs/platformdirs/py.typed
vendored
Normal file
0
third_party/python/platformdirs/platformdirs/py.typed
vendored
Normal file
269
third_party/python/platformdirs/platformdirs/unix.py
vendored
Normal file
269
third_party/python/platformdirs/platformdirs/unix.py
vendored
Normal file
@@ -0,0 +1,269 @@
|
|||||||
|
"""Unix."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from configparser import ConfigParser
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Iterator, NoReturn
|
||||||
|
|
||||||
|
from .api import PlatformDirsABC
|
||||||
|
|
||||||
|
if sys.platform == "win32":
|
||||||
|
|
||||||
|
def getuid() -> NoReturn:
|
||||||
|
msg = "should only be used on Unix"
|
||||||
|
raise RuntimeError(msg)
|
||||||
|
|
||||||
|
else:
|
||||||
|
from os import getuid
|
||||||
|
|
||||||
|
|
||||||
|
class Unix(PlatformDirsABC): # noqa: PLR0904
|
||||||
|
"""
|
||||||
|
On Unix/Linux, we follow the `XDG Basedir Spec <https://specifications.freedesktop.org/basedir-spec/basedir-spec-
|
||||||
|
latest.html>`_.
|
||||||
|
|
||||||
|
The spec allows overriding directories with environment variables. The examples shown are the default values,
|
||||||
|
alongside the name of the environment variable that overrides them. Makes use of the `appname
|
||||||
|
<platformdirs.api.PlatformDirsABC.appname>`, `version <platformdirs.api.PlatformDirsABC.version>`, `multipath
|
||||||
|
<platformdirs.api.PlatformDirsABC.multipath>`, `opinion <platformdirs.api.PlatformDirsABC.opinion>`, `ensure_exists
|
||||||
|
<platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_data_dir(self) -> str:
|
||||||
|
"""
|
||||||
|
:return: data directory tied to the user, e.g. ``~/.local/share/$appname/$version`` or
|
||||||
|
``$XDG_DATA_HOME/$appname/$version``
|
||||||
|
"""
|
||||||
|
path = os.environ.get("XDG_DATA_HOME", "")
|
||||||
|
if not path.strip():
|
||||||
|
path = os.path.expanduser("~/.local/share") # noqa: PTH111
|
||||||
|
return self._append_app_name_and_version(path)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _site_data_dirs(self) -> list[str]:
|
||||||
|
path = os.environ.get("XDG_DATA_DIRS", "")
|
||||||
|
if not path.strip():
|
||||||
|
path = f"/usr/local/share{os.pathsep}/usr/share"
|
||||||
|
return [self._append_app_name_and_version(p) for p in path.split(os.pathsep)]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def site_data_dir(self) -> str:
|
||||||
|
"""
|
||||||
|
:return: data directories shared by users (if `multipath <platformdirs.api.PlatformDirsABC.multipath>` is
|
||||||
|
enabled and ``XDG_DATA_DIRS`` is set and a multi path the response is also a multi path separated by the
|
||||||
|
OS path separator), e.g. ``/usr/local/share/$appname/$version`` or ``/usr/share/$appname/$version``
|
||||||
|
"""
|
||||||
|
# XDG default for $XDG_DATA_DIRS; only first, if multipath is False
|
||||||
|
dirs = self._site_data_dirs
|
||||||
|
if not self.multipath:
|
||||||
|
return dirs[0]
|
||||||
|
return os.pathsep.join(dirs)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_config_dir(self) -> str:
|
||||||
|
"""
|
||||||
|
:return: config directory tied to the user, e.g. ``~/.config/$appname/$version`` or
|
||||||
|
``$XDG_CONFIG_HOME/$appname/$version``
|
||||||
|
"""
|
||||||
|
path = os.environ.get("XDG_CONFIG_HOME", "")
|
||||||
|
if not path.strip():
|
||||||
|
path = os.path.expanduser("~/.config") # noqa: PTH111
|
||||||
|
return self._append_app_name_and_version(path)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _site_config_dirs(self) -> list[str]:
|
||||||
|
path = os.environ.get("XDG_CONFIG_DIRS", "")
|
||||||
|
if not path.strip():
|
||||||
|
path = "/etc/xdg"
|
||||||
|
return [self._append_app_name_and_version(p) for p in path.split(os.pathsep)]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def site_config_dir(self) -> str:
|
||||||
|
"""
|
||||||
|
:return: config directories shared by users (if `multipath <platformdirs.api.PlatformDirsABC.multipath>`
|
||||||
|
is enabled and ``XDG_CONFIG_DIRS`` is set and a multi path the response is also a multi path separated by
|
||||||
|
the OS path separator), e.g. ``/etc/xdg/$appname/$version``
|
||||||
|
"""
|
||||||
|
# XDG default for $XDG_CONFIG_DIRS only first, if multipath is False
|
||||||
|
dirs = self._site_config_dirs
|
||||||
|
if not self.multipath:
|
||||||
|
return dirs[0]
|
||||||
|
return os.pathsep.join(dirs)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_cache_dir(self) -> str:
|
||||||
|
"""
|
||||||
|
:return: cache directory tied to the user, e.g. ``~/.cache/$appname/$version`` or
|
||||||
|
``~/$XDG_CACHE_HOME/$appname/$version``
|
||||||
|
"""
|
||||||
|
path = os.environ.get("XDG_CACHE_HOME", "")
|
||||||
|
if not path.strip():
|
||||||
|
path = os.path.expanduser("~/.cache") # noqa: PTH111
|
||||||
|
return self._append_app_name_and_version(path)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def site_cache_dir(self) -> str:
|
||||||
|
""":return: cache directory shared by users, e.g. ``/var/cache/$appname/$version``"""
|
||||||
|
return self._append_app_name_and_version("/var/cache")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_state_dir(self) -> str:
|
||||||
|
"""
|
||||||
|
:return: state directory tied to the user, e.g. ``~/.local/state/$appname/$version`` or
|
||||||
|
``$XDG_STATE_HOME/$appname/$version``
|
||||||
|
"""
|
||||||
|
path = os.environ.get("XDG_STATE_HOME", "")
|
||||||
|
if not path.strip():
|
||||||
|
path = os.path.expanduser("~/.local/state") # noqa: PTH111
|
||||||
|
return self._append_app_name_and_version(path)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_log_dir(self) -> str:
|
||||||
|
""":return: log directory tied to the user, same as `user_state_dir` if not opinionated else ``log`` in it"""
|
||||||
|
path = self.user_state_dir
|
||||||
|
if self.opinion:
|
||||||
|
path = os.path.join(path, "log") # noqa: PTH118
|
||||||
|
self._optionally_create_directory(path)
|
||||||
|
return path
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_documents_dir(self) -> str:
|
||||||
|
""":return: documents directory tied to the user, e.g. ``~/Documents``"""
|
||||||
|
return _get_user_media_dir("XDG_DOCUMENTS_DIR", "~/Documents")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_downloads_dir(self) -> str:
|
||||||
|
""":return: downloads directory tied to the user, e.g. ``~/Downloads``"""
|
||||||
|
return _get_user_media_dir("XDG_DOWNLOAD_DIR", "~/Downloads")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_pictures_dir(self) -> str:
|
||||||
|
""":return: pictures directory tied to the user, e.g. ``~/Pictures``"""
|
||||||
|
return _get_user_media_dir("XDG_PICTURES_DIR", "~/Pictures")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_videos_dir(self) -> str:
|
||||||
|
""":return: videos directory tied to the user, e.g. ``~/Videos``"""
|
||||||
|
return _get_user_media_dir("XDG_VIDEOS_DIR", "~/Videos")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_music_dir(self) -> str:
|
||||||
|
""":return: music directory tied to the user, e.g. ``~/Music``"""
|
||||||
|
return _get_user_media_dir("XDG_MUSIC_DIR", "~/Music")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_desktop_dir(self) -> str:
|
||||||
|
""":return: desktop directory tied to the user, e.g. ``~/Desktop``"""
|
||||||
|
return _get_user_media_dir("XDG_DESKTOP_DIR", "~/Desktop")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_runtime_dir(self) -> str:
|
||||||
|
"""
|
||||||
|
:return: runtime directory tied to the user, e.g. ``/run/user/$(id -u)/$appname/$version`` or
|
||||||
|
``$XDG_RUNTIME_DIR/$appname/$version``.
|
||||||
|
|
||||||
|
For FreeBSD/OpenBSD/NetBSD, it would return ``/var/run/user/$(id -u)/$appname/$version`` if
|
||||||
|
exists, otherwise ``/tmp/runtime-$(id -u)/$appname/$version``, if``$XDG_RUNTIME_DIR``
|
||||||
|
is not set.
|
||||||
|
"""
|
||||||
|
path = os.environ.get("XDG_RUNTIME_DIR", "")
|
||||||
|
if not path.strip():
|
||||||
|
if sys.platform.startswith(("freebsd", "openbsd", "netbsd")):
|
||||||
|
path = f"/var/run/user/{getuid()}"
|
||||||
|
if not Path(path).exists():
|
||||||
|
path = f"/tmp/runtime-{getuid()}" # noqa: S108
|
||||||
|
else:
|
||||||
|
path = f"/run/user/{getuid()}"
|
||||||
|
return self._append_app_name_and_version(path)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def site_runtime_dir(self) -> str:
|
||||||
|
"""
|
||||||
|
:return: runtime directory shared by users, e.g. ``/run/$appname/$version`` or \
|
||||||
|
``$XDG_RUNTIME_DIR/$appname/$version``.
|
||||||
|
|
||||||
|
Note that this behaves almost exactly like `user_runtime_dir` if ``$XDG_RUNTIME_DIR`` is set, but will
|
||||||
|
fall back to paths associated to the root user instead of a regular logged-in user if it's not set.
|
||||||
|
|
||||||
|
If you wish to ensure that a logged-in root user path is returned e.g. ``/run/user/0``, use `user_runtime_dir`
|
||||||
|
instead.
|
||||||
|
|
||||||
|
For FreeBSD/OpenBSD/NetBSD, it would return ``/var/run/$appname/$version`` if ``$XDG_RUNTIME_DIR`` is not set.
|
||||||
|
"""
|
||||||
|
path = os.environ.get("XDG_RUNTIME_DIR", "")
|
||||||
|
if not path.strip():
|
||||||
|
if sys.platform.startswith(("freebsd", "openbsd", "netbsd")):
|
||||||
|
path = "/var/run"
|
||||||
|
else:
|
||||||
|
path = "/run"
|
||||||
|
return self._append_app_name_and_version(path)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def site_data_path(self) -> Path:
|
||||||
|
""":return: data path shared by users. Only return the first item, even if ``multipath`` is set to ``True``"""
|
||||||
|
return self._first_item_as_path_if_multipath(self.site_data_dir)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def site_config_path(self) -> Path:
|
||||||
|
""":return: config path shared by the users, returns the first item, even if ``multipath`` is set to ``True``"""
|
||||||
|
return self._first_item_as_path_if_multipath(self.site_config_dir)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def site_cache_path(self) -> Path:
|
||||||
|
""":return: cache path shared by users. Only return the first item, even if ``multipath`` is set to ``True``"""
|
||||||
|
return self._first_item_as_path_if_multipath(self.site_cache_dir)
|
||||||
|
|
||||||
|
def iter_config_dirs(self) -> Iterator[str]:
|
||||||
|
""":yield: all user and site configuration directories."""
|
||||||
|
yield self.user_config_dir
|
||||||
|
yield from self._site_config_dirs
|
||||||
|
|
||||||
|
def iter_data_dirs(self) -> Iterator[str]:
|
||||||
|
""":yield: all user and site data directories."""
|
||||||
|
yield self.user_data_dir
|
||||||
|
yield from self._site_data_dirs
|
||||||
|
|
||||||
|
|
||||||
|
def _get_user_media_dir(env_var: str, fallback_tilde_path: str) -> str:
|
||||||
|
media_dir = _get_user_dirs_folder(env_var)
|
||||||
|
if media_dir is None:
|
||||||
|
media_dir = os.environ.get(env_var, "").strip()
|
||||||
|
if not media_dir:
|
||||||
|
media_dir = os.path.expanduser(fallback_tilde_path) # noqa: PTH111
|
||||||
|
|
||||||
|
return media_dir
|
||||||
|
|
||||||
|
|
||||||
|
def _get_user_dirs_folder(key: str) -> str | None:
|
||||||
|
"""
|
||||||
|
Return directory from user-dirs.dirs config file.
|
||||||
|
|
||||||
|
See https://freedesktop.org/wiki/Software/xdg-user-dirs/.
|
||||||
|
|
||||||
|
"""
|
||||||
|
user_dirs_config_path = Path(Unix().user_config_dir) / "user-dirs.dirs"
|
||||||
|
if user_dirs_config_path.exists():
|
||||||
|
parser = ConfigParser()
|
||||||
|
|
||||||
|
with user_dirs_config_path.open() as stream:
|
||||||
|
# Add fake section header, so ConfigParser doesn't complain
|
||||||
|
parser.read_string(f"[top]\n{stream.read()}")
|
||||||
|
|
||||||
|
if key not in parser["top"]:
|
||||||
|
return None
|
||||||
|
|
||||||
|
path = parser["top"][key].strip('"')
|
||||||
|
# Handle relative home paths
|
||||||
|
return path.replace("$HOME", os.path.expanduser("~")) # noqa: PTH111
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"Unix",
|
||||||
|
]
|
||||||
16
third_party/python/platformdirs/platformdirs/version.py
vendored
Normal file
16
third_party/python/platformdirs/platformdirs/version.py
vendored
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# file generated by setuptools_scm
|
||||||
|
# don't change, don't track in version control
|
||||||
|
TYPE_CHECKING = False
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from typing import Tuple, Union
|
||||||
|
VERSION_TUPLE = Tuple[Union[int, str], ...]
|
||||||
|
else:
|
||||||
|
VERSION_TUPLE = object
|
||||||
|
|
||||||
|
version: str
|
||||||
|
__version__: str
|
||||||
|
__version_tuple__: VERSION_TUPLE
|
||||||
|
version_tuple: VERSION_TUPLE
|
||||||
|
|
||||||
|
__version__ = version = '4.3.6'
|
||||||
|
__version_tuple__ = version_tuple = (4, 3, 6)
|
||||||
272
third_party/python/platformdirs/platformdirs/windows.py
vendored
Normal file
272
third_party/python/platformdirs/platformdirs/windows.py
vendored
Normal file
@@ -0,0 +1,272 @@
|
|||||||
|
"""Windows."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from functools import lru_cache
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
from .api import PlatformDirsABC
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from collections.abc import Callable
|
||||||
|
|
||||||
|
|
||||||
|
class Windows(PlatformDirsABC):
|
||||||
|
"""
|
||||||
|
`MSDN on where to store app data files <https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid>`_.
|
||||||
|
|
||||||
|
Makes use of the `appname <platformdirs.api.PlatformDirsABC.appname>`, `appauthor
|
||||||
|
<platformdirs.api.PlatformDirsABC.appauthor>`, `version <platformdirs.api.PlatformDirsABC.version>`, `roaming
|
||||||
|
<platformdirs.api.PlatformDirsABC.roaming>`, `opinion <platformdirs.api.PlatformDirsABC.opinion>`, `ensure_exists
|
||||||
|
<platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_data_dir(self) -> str:
|
||||||
|
"""
|
||||||
|
:return: data directory tied to the user, e.g.
|
||||||
|
``%USERPROFILE%\\AppData\\Local\\$appauthor\\$appname`` (not roaming) or
|
||||||
|
``%USERPROFILE%\\AppData\\Roaming\\$appauthor\\$appname`` (roaming)
|
||||||
|
"""
|
||||||
|
const = "CSIDL_APPDATA" if self.roaming else "CSIDL_LOCAL_APPDATA"
|
||||||
|
path = os.path.normpath(get_win_folder(const))
|
||||||
|
return self._append_parts(path)
|
||||||
|
|
||||||
|
def _append_parts(self, path: str, *, opinion_value: str | None = None) -> str:
|
||||||
|
params = []
|
||||||
|
if self.appname:
|
||||||
|
if self.appauthor is not False:
|
||||||
|
author = self.appauthor or self.appname
|
||||||
|
params.append(author)
|
||||||
|
params.append(self.appname)
|
||||||
|
if opinion_value is not None and self.opinion:
|
||||||
|
params.append(opinion_value)
|
||||||
|
if self.version:
|
||||||
|
params.append(self.version)
|
||||||
|
path = os.path.join(path, *params) # noqa: PTH118
|
||||||
|
self._optionally_create_directory(path)
|
||||||
|
return path
|
||||||
|
|
||||||
|
@property
|
||||||
|
def site_data_dir(self) -> str:
|
||||||
|
""":return: data directory shared by users, e.g. ``C:\\ProgramData\\$appauthor\\$appname``"""
|
||||||
|
path = os.path.normpath(get_win_folder("CSIDL_COMMON_APPDATA"))
|
||||||
|
return self._append_parts(path)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_config_dir(self) -> str:
|
||||||
|
""":return: config directory tied to the user, same as `user_data_dir`"""
|
||||||
|
return self.user_data_dir
|
||||||
|
|
||||||
|
@property
|
||||||
|
def site_config_dir(self) -> str:
|
||||||
|
""":return: config directory shared by the users, same as `site_data_dir`"""
|
||||||
|
return self.site_data_dir
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_cache_dir(self) -> str:
|
||||||
|
"""
|
||||||
|
:return: cache directory tied to the user (if opinionated with ``Cache`` folder within ``$appname``) e.g.
|
||||||
|
``%USERPROFILE%\\AppData\\Local\\$appauthor\\$appname\\Cache\\$version``
|
||||||
|
"""
|
||||||
|
path = os.path.normpath(get_win_folder("CSIDL_LOCAL_APPDATA"))
|
||||||
|
return self._append_parts(path, opinion_value="Cache")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def site_cache_dir(self) -> str:
|
||||||
|
""":return: cache directory shared by users, e.g. ``C:\\ProgramData\\$appauthor\\$appname\\Cache\\$version``"""
|
||||||
|
path = os.path.normpath(get_win_folder("CSIDL_COMMON_APPDATA"))
|
||||||
|
return self._append_parts(path, opinion_value="Cache")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_state_dir(self) -> str:
|
||||||
|
""":return: state directory tied to the user, same as `user_data_dir`"""
|
||||||
|
return self.user_data_dir
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_log_dir(self) -> str:
|
||||||
|
""":return: log directory tied to the user, same as `user_data_dir` if not opinionated else ``Logs`` in it"""
|
||||||
|
path = self.user_data_dir
|
||||||
|
if self.opinion:
|
||||||
|
path = os.path.join(path, "Logs") # noqa: PTH118
|
||||||
|
self._optionally_create_directory(path)
|
||||||
|
return path
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_documents_dir(self) -> str:
|
||||||
|
""":return: documents directory tied to the user e.g. ``%USERPROFILE%\\Documents``"""
|
||||||
|
return os.path.normpath(get_win_folder("CSIDL_PERSONAL"))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_downloads_dir(self) -> str:
|
||||||
|
""":return: downloads directory tied to the user e.g. ``%USERPROFILE%\\Downloads``"""
|
||||||
|
return os.path.normpath(get_win_folder("CSIDL_DOWNLOADS"))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_pictures_dir(self) -> str:
|
||||||
|
""":return: pictures directory tied to the user e.g. ``%USERPROFILE%\\Pictures``"""
|
||||||
|
return os.path.normpath(get_win_folder("CSIDL_MYPICTURES"))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_videos_dir(self) -> str:
|
||||||
|
""":return: videos directory tied to the user e.g. ``%USERPROFILE%\\Videos``"""
|
||||||
|
return os.path.normpath(get_win_folder("CSIDL_MYVIDEO"))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_music_dir(self) -> str:
|
||||||
|
""":return: music directory tied to the user e.g. ``%USERPROFILE%\\Music``"""
|
||||||
|
return os.path.normpath(get_win_folder("CSIDL_MYMUSIC"))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_desktop_dir(self) -> str:
|
||||||
|
""":return: desktop directory tied to the user, e.g. ``%USERPROFILE%\\Desktop``"""
|
||||||
|
return os.path.normpath(get_win_folder("CSIDL_DESKTOPDIRECTORY"))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_runtime_dir(self) -> str:
|
||||||
|
"""
|
||||||
|
:return: runtime directory tied to the user, e.g.
|
||||||
|
``%USERPROFILE%\\AppData\\Local\\Temp\\$appauthor\\$appname``
|
||||||
|
"""
|
||||||
|
path = os.path.normpath(os.path.join(get_win_folder("CSIDL_LOCAL_APPDATA"), "Temp")) # noqa: PTH118
|
||||||
|
return self._append_parts(path)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def site_runtime_dir(self) -> str:
|
||||||
|
""":return: runtime directory shared by users, same as `user_runtime_dir`"""
|
||||||
|
return self.user_runtime_dir
|
||||||
|
|
||||||
|
|
||||||
|
def get_win_folder_from_env_vars(csidl_name: str) -> str:
|
||||||
|
"""Get folder from environment variables."""
|
||||||
|
result = get_win_folder_if_csidl_name_not_env_var(csidl_name)
|
||||||
|
if result is not None:
|
||||||
|
return result
|
||||||
|
|
||||||
|
env_var_name = {
|
||||||
|
"CSIDL_APPDATA": "APPDATA",
|
||||||
|
"CSIDL_COMMON_APPDATA": "ALLUSERSPROFILE",
|
||||||
|
"CSIDL_LOCAL_APPDATA": "LOCALAPPDATA",
|
||||||
|
}.get(csidl_name)
|
||||||
|
if env_var_name is None:
|
||||||
|
msg = f"Unknown CSIDL name: {csidl_name}"
|
||||||
|
raise ValueError(msg)
|
||||||
|
result = os.environ.get(env_var_name)
|
||||||
|
if result is None:
|
||||||
|
msg = f"Unset environment variable: {env_var_name}"
|
||||||
|
raise ValueError(msg)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def get_win_folder_if_csidl_name_not_env_var(csidl_name: str) -> str | None:
|
||||||
|
"""Get a folder for a CSIDL name that does not exist as an environment variable."""
|
||||||
|
if csidl_name == "CSIDL_PERSONAL":
|
||||||
|
return os.path.join(os.path.normpath(os.environ["USERPROFILE"]), "Documents") # noqa: PTH118
|
||||||
|
|
||||||
|
if csidl_name == "CSIDL_DOWNLOADS":
|
||||||
|
return os.path.join(os.path.normpath(os.environ["USERPROFILE"]), "Downloads") # noqa: PTH118
|
||||||
|
|
||||||
|
if csidl_name == "CSIDL_MYPICTURES":
|
||||||
|
return os.path.join(os.path.normpath(os.environ["USERPROFILE"]), "Pictures") # noqa: PTH118
|
||||||
|
|
||||||
|
if csidl_name == "CSIDL_MYVIDEO":
|
||||||
|
return os.path.join(os.path.normpath(os.environ["USERPROFILE"]), "Videos") # noqa: PTH118
|
||||||
|
|
||||||
|
if csidl_name == "CSIDL_MYMUSIC":
|
||||||
|
return os.path.join(os.path.normpath(os.environ["USERPROFILE"]), "Music") # noqa: PTH118
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def get_win_folder_from_registry(csidl_name: str) -> str:
|
||||||
|
"""
|
||||||
|
Get folder from the registry.
|
||||||
|
|
||||||
|
This is a fallback technique at best. I'm not sure if using the registry for these guarantees us the correct answer
|
||||||
|
for all CSIDL_* names.
|
||||||
|
|
||||||
|
"""
|
||||||
|
shell_folder_name = {
|
||||||
|
"CSIDL_APPDATA": "AppData",
|
||||||
|
"CSIDL_COMMON_APPDATA": "Common AppData",
|
||||||
|
"CSIDL_LOCAL_APPDATA": "Local AppData",
|
||||||
|
"CSIDL_PERSONAL": "Personal",
|
||||||
|
"CSIDL_DOWNLOADS": "{374DE290-123F-4565-9164-39C4925E467B}",
|
||||||
|
"CSIDL_MYPICTURES": "My Pictures",
|
||||||
|
"CSIDL_MYVIDEO": "My Video",
|
||||||
|
"CSIDL_MYMUSIC": "My Music",
|
||||||
|
}.get(csidl_name)
|
||||||
|
if shell_folder_name is None:
|
||||||
|
msg = f"Unknown CSIDL name: {csidl_name}"
|
||||||
|
raise ValueError(msg)
|
||||||
|
if sys.platform != "win32": # only needed for mypy type checker to know that this code runs only on Windows
|
||||||
|
raise NotImplementedError
|
||||||
|
import winreg # noqa: PLC0415
|
||||||
|
|
||||||
|
key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders")
|
||||||
|
directory, _ = winreg.QueryValueEx(key, shell_folder_name)
|
||||||
|
return str(directory)
|
||||||
|
|
||||||
|
|
||||||
|
def get_win_folder_via_ctypes(csidl_name: str) -> str:
|
||||||
|
"""Get folder with ctypes."""
|
||||||
|
# There is no 'CSIDL_DOWNLOADS'.
|
||||||
|
# Use 'CSIDL_PROFILE' (40) and append the default folder 'Downloads' instead.
|
||||||
|
# https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid
|
||||||
|
|
||||||
|
import ctypes # noqa: PLC0415
|
||||||
|
|
||||||
|
csidl_const = {
|
||||||
|
"CSIDL_APPDATA": 26,
|
||||||
|
"CSIDL_COMMON_APPDATA": 35,
|
||||||
|
"CSIDL_LOCAL_APPDATA": 28,
|
||||||
|
"CSIDL_PERSONAL": 5,
|
||||||
|
"CSIDL_MYPICTURES": 39,
|
||||||
|
"CSIDL_MYVIDEO": 14,
|
||||||
|
"CSIDL_MYMUSIC": 13,
|
||||||
|
"CSIDL_DOWNLOADS": 40,
|
||||||
|
"CSIDL_DESKTOPDIRECTORY": 16,
|
||||||
|
}.get(csidl_name)
|
||||||
|
if csidl_const is None:
|
||||||
|
msg = f"Unknown CSIDL name: {csidl_name}"
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
|
buf = ctypes.create_unicode_buffer(1024)
|
||||||
|
windll = getattr(ctypes, "windll") # noqa: B009 # using getattr to avoid false positive with mypy type checker
|
||||||
|
windll.shell32.SHGetFolderPathW(None, csidl_const, None, 0, buf)
|
||||||
|
|
||||||
|
# Downgrade to short path name if it has high-bit chars.
|
||||||
|
if any(ord(c) > 255 for c in buf): # noqa: PLR2004
|
||||||
|
buf2 = ctypes.create_unicode_buffer(1024)
|
||||||
|
if windll.kernel32.GetShortPathNameW(buf.value, buf2, 1024):
|
||||||
|
buf = buf2
|
||||||
|
|
||||||
|
if csidl_name == "CSIDL_DOWNLOADS":
|
||||||
|
return os.path.join(buf.value, "Downloads") # noqa: PTH118
|
||||||
|
|
||||||
|
return buf.value
|
||||||
|
|
||||||
|
|
||||||
|
def _pick_get_win_folder() -> Callable[[str], str]:
|
||||||
|
try:
|
||||||
|
import ctypes # noqa: PLC0415
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
if hasattr(ctypes, "windll"):
|
||||||
|
return get_win_folder_via_ctypes
|
||||||
|
try:
|
||||||
|
import winreg # noqa: PLC0415, F401
|
||||||
|
except ImportError:
|
||||||
|
return get_win_folder_from_env_vars
|
||||||
|
else:
|
||||||
|
return get_win_folder_from_registry
|
||||||
|
|
||||||
|
|
||||||
|
get_win_folder = lru_cache(maxsize=None)(_pick_get_win_folder())
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"Windows",
|
||||||
|
]
|
||||||
2
third_party/python/pyproject.toml
vendored
2
third_party/python/pyproject.toml
vendored
@@ -20,7 +20,7 @@ dependencies = [
|
|||||||
"esprima==4.0.1",
|
"esprima==4.0.1",
|
||||||
"fluent-migrate==0.13.0",
|
"fluent-migrate==0.13.0",
|
||||||
"fluent-syntax==0.19.0",
|
"fluent-syntax==0.19.0",
|
||||||
"glean-parser==15.0.1",
|
"glean-parser==15.2.1",
|
||||||
"importlib-metadata==6.0.0",
|
"importlib-metadata==6.0.0",
|
||||||
# Required for compatibility with Flask >= 2 in tools/tryselect/selectors/chooser
|
# Required for compatibility with Flask >= 2 in tools/tryselect/selectors/chooser
|
||||||
"jinja2==3.1.2",
|
"jinja2==3.1.2",
|
||||||
|
|||||||
9
third_party/python/requirements.txt
vendored
9
third_party/python/requirements.txt
vendored
@@ -289,9 +289,9 @@ frozenlist==1.4.1 \
|
|||||||
giturlparse==0.12.0 \
|
giturlparse==0.12.0 \
|
||||||
--hash=sha256:c0fff7c21acc435491b1779566e038757a205c1ffdcb47e4f81ea52ad8c3859a \
|
--hash=sha256:c0fff7c21acc435491b1779566e038757a205c1ffdcb47e4f81ea52ad8c3859a \
|
||||||
--hash=sha256:412b74f2855f1da2fefa89fd8dde62df48476077a72fc19b62039554d27360eb
|
--hash=sha256:412b74f2855f1da2fefa89fd8dde62df48476077a72fc19b62039554d27360eb
|
||||||
glean-parser==15.0.1 \
|
glean-parser==15.2.1 \
|
||||||
--hash=sha256:0752f21b26fef589f27d9ff633c08f8ea6b2783cc51ee3fd8cf2e2746d8423da \
|
--hash=sha256:e63d87847b2366858b457fc6336bca764898d6e560cc144c5a0ca34effd719fd \
|
||||||
--hash=sha256:01f90cb5b9fe54adf3875d2c7fda5b88a63dda7ae0cc4a23e9439feacf1df4dc
|
--hash=sha256:8f8eeba3a7624c3c5cdab9c2602abfabfce57ae66b32ba487650cd6def17a77b
|
||||||
idna==3.10 \
|
idna==3.10 \
|
||||||
--hash=sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9 \
|
--hash=sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9 \
|
||||||
--hash=sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3
|
--hash=sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3
|
||||||
@@ -486,6 +486,9 @@ pip-tools==7.4.1 \
|
|||||||
pkgutil-resolve-name==1.3.10 \
|
pkgutil-resolve-name==1.3.10 \
|
||||||
--hash=sha256:357d6c9e6a755653cfd78893817c0853af365dd51ec97f3d358a819373bbd174 \
|
--hash=sha256:357d6c9e6a755653cfd78893817c0853af365dd51ec97f3d358a819373bbd174 \
|
||||||
--hash=sha256:ca27cc078d25c5ad71a9de0a7a330146c4e014c2462d9af19c6b828280649c5e
|
--hash=sha256:ca27cc078d25c5ad71a9de0a7a330146c4e014c2462d9af19c6b828280649c5e
|
||||||
|
platformdirs==4.3.6 \
|
||||||
|
--hash=sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907 \
|
||||||
|
--hash=sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb
|
||||||
ply==3.10 \
|
ply==3.10 \
|
||||||
--hash=sha256:96e94af7dd7031d8d6dd6e2a8e0de593b511c211a86e28a9c9621c275ac8bacb
|
--hash=sha256:96e94af7dd7031d8d6dd6e2a8e0de593b511c211a86e28a9c9621c275ac8bacb
|
||||||
pyasn1==0.4.8 \
|
pyasn1==0.4.8 \
|
||||||
|
|||||||
19
third_party/python/uv.lock
generated
vendored
19
third_party/python/uv.lock
generated
vendored
@@ -511,19 +511,19 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "glean-parser"
|
name = "glean-parser"
|
||||||
version = "15.0.1"
|
version = "15.2.1"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "appdirs" },
|
|
||||||
{ name = "click" },
|
{ name = "click" },
|
||||||
{ name = "diskcache" },
|
{ name = "diskcache" },
|
||||||
{ name = "jinja2" },
|
{ name = "jinja2" },
|
||||||
{ name = "jsonschema" },
|
{ name = "jsonschema" },
|
||||||
|
{ name = "platformdirs" },
|
||||||
{ name = "pyyaml" },
|
{ name = "pyyaml" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/91/f3/678649808238ce2bb5aa54b93b51147613ffc5ce5848fa9b1a70eb13af42/glean_parser-15.0.1.tar.gz", hash = "sha256:0752f21b26fef589f27d9ff633c08f8ea6b2783cc51ee3fd8cf2e2746d8423da", size = 272790 }
|
sdist = { url = "https://files.pythonhosted.org/packages/af/a1/fca4c0ba2c90ac6a37a546c8aff6e07c9e8d2e058bb1e4dd544b4aac9f4d/glean_parser-15.2.1.tar.gz", hash = "sha256:e63d87847b2366858b457fc6336bca764898d6e560cc144c5a0ca34effd719fd", size = 275445 }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/63/d4/7cd45084155205c45e38cd4a18b2847091022054c775b514b7991f807390/glean_parser-15.0.1-py3-none-any.whl", hash = "sha256:01f90cb5b9fe54adf3875d2c7fda5b88a63dda7ae0cc4a23e9439feacf1df4dc", size = 115569 },
|
{ url = "https://files.pythonhosted.org/packages/a0/1e/e9f4a3c302b201f790a39192a26a89465e4b0a37e8b7cbac01a3a4ce7be4/glean_parser-15.2.1-py3-none-any.whl", hash = "sha256:8f8eeba3a7624c3c5cdab9c2602abfabfce57ae66b32ba487650cd6def17a77b", size = 116007 },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -807,7 +807,7 @@ requires-dist = [
|
|||||||
{ name = "esprima", specifier = "==4.0.1" },
|
{ name = "esprima", specifier = "==4.0.1" },
|
||||||
{ name = "fluent-migrate", specifier = "==0.13.0" },
|
{ name = "fluent-migrate", specifier = "==0.13.0" },
|
||||||
{ name = "fluent-syntax", specifier = "==0.19.0" },
|
{ name = "fluent-syntax", specifier = "==0.19.0" },
|
||||||
{ name = "glean-parser", specifier = "==15.0.1" },
|
{ name = "glean-parser", specifier = "==15.2.1" },
|
||||||
{ name = "importlib-metadata", specifier = "==6.0.0" },
|
{ name = "importlib-metadata", specifier = "==6.0.0" },
|
||||||
{ name = "jinja2", specifier = "==3.1.2" },
|
{ name = "jinja2", specifier = "==3.1.2" },
|
||||||
{ name = "jsmin", specifier = "==3.0.0" },
|
{ name = "jsmin", specifier = "==3.0.0" },
|
||||||
@@ -1018,6 +1018,15 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/c9/5c/3d4882ba113fd55bdba9326c1e4c62a15e674a2501de4869e6bd6301f87e/pkgutil_resolve_name-1.3.10-py3-none-any.whl", hash = "sha256:ca27cc078d25c5ad71a9de0a7a330146c4e014c2462d9af19c6b828280649c5e", size = 4734 },
|
{ url = "https://files.pythonhosted.org/packages/c9/5c/3d4882ba113fd55bdba9326c1e4c62a15e674a2501de4869e6bd6301f87e/pkgutil_resolve_name-1.3.10-py3-none-any.whl", hash = "sha256:ca27cc078d25c5ad71a9de0a7a330146c4e014c2462d9af19c6b828280649c5e", size = 4734 },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "platformdirs"
|
||||||
|
version = "4.3.6"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/13/fc/128cc9cb8f03208bdbf93d3aa862e16d376844a14f9a0ce5cf4507372de4/platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907", size = 21302 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/3c/a6/bc1012356d8ece4d66dd75c4b9fc6c1f6650ddd5991e421177d9f8f671be/platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb", size = 18439 },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ply"
|
name = "ply"
|
||||||
version = "3.10"
|
version = "3.10"
|
||||||
|
|||||||
2
third_party/python/uv.lock.hash
vendored
2
third_party/python/uv.lock.hash
vendored
@@ -1 +1 @@
|
|||||||
35232ec676dd469de7810dbc063f1a4d1831d97adc9a05236e5a7645fe148b90
|
0eecfeb2cd6b7471ac1ad212883553b4b17becf19d6e13b1b73c26d5b064deb2
|
||||||
|
|||||||
@@ -5,13 +5,19 @@ It depends on [glean-parser] from pypi.org
|
|||||||
|
|
||||||
[glean-parser]: https://pypi.org/project/glean-parser/
|
[glean-parser]: https://pypi.org/project/glean-parser/
|
||||||
|
|
||||||
To update the in-tree glean-parser change the version in `third_party/python/requirements.in`,
|
To update the in-tree glean-parser change the version in `third_party/python/pyproject.toml`,
|
||||||
then run
|
then run
|
||||||
|
|
||||||
```
|
```
|
||||||
./mach vendor python
|
./mach vendor python
|
||||||
```
|
```
|
||||||
|
|
||||||
|
We presently pin our version of glean-parser to the version in [sdk_generator.sh],
|
||||||
|
otherwise we could use some of the
|
||||||
|
[more interesting switches on ./mach vendor python][vendor-python].
|
||||||
|
|
||||||
|
[vendor-python]: /python/index
|
||||||
|
|
||||||
```{note}
|
```{note}
|
||||||
**Important**: the glean_parser and all of its dependencies must support Python 3.5, as discussed here.
|
**Important**: the glean_parser and all of its dependencies must support Python 3.5, as discussed here.
|
||||||
This is the minimum version supported by mach and installed on the CI images for running tests.
|
This is the minimum version supported by mach and installed on the CI images for running tests.
|
||||||
|
|||||||
@@ -44,5 +44,7 @@ However each Glean SDK release requires a specific `glean_parser` version.
|
|||||||
When updating one or the other ensure versions stay compatible.
|
When updating one or the other ensure versions stay compatible.
|
||||||
You can find the currently used `glean_parser` version in the Glean SDK source tree, e.g. in [sdk_generator.sh].
|
You can find the currently used `glean_parser` version in the Glean SDK source tree, e.g. in [sdk_generator.sh].
|
||||||
|
|
||||||
|
In most cases you should update `glean_parser` first before updating the SDK.
|
||||||
|
|
||||||
[sdk_generator.sh]: https://github.com/mozilla/glean/blob/main/glean-core/ios/sdk_generator.sh#L28
|
[sdk_generator.sh]: https://github.com/mozilla/glean/blob/main/glean-core/ios/sdk_generator.sh#L28
|
||||||
[glean-bug]: https://bugzilla.mozilla.org/enter_bug.cgi?product=Data+Platform+and+Tools&component=Glean%3A+SDK&priority=P3&status_whiteboard=%5Btelemetry%3Aglean-rs%3Am%3F%5D
|
[glean-bug]: https://bugzilla.mozilla.org/enter_bug.cgi?product=Data+Platform+and+Tools&component=Glean%3A+SDK&priority=P3&status_whiteboard=%5Btelemetry%3Aglean-rs%3Am%3F%5D
|
||||||
|
|||||||
Reference in New Issue
Block a user