koichi12 commited on
Commit
6853990
·
verified ·
1 Parent(s): 49d2a27

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +1 -0
  2. .venv/lib/python3.11/site-packages/google/_upb/_message.abi3.so +3 -0
  3. .venv/lib/python3.11/site-packages/google/api/__pycache__/annotations_pb2.cpython-311.pyc +0 -0
  4. .venv/lib/python3.11/site-packages/google/api/__pycache__/auth_pb2.cpython-311.pyc +0 -0
  5. .venv/lib/python3.11/site-packages/google/api/__pycache__/client_pb2.cpython-311.pyc +0 -0
  6. .venv/lib/python3.11/site-packages/google/api/__pycache__/config_change_pb2.cpython-311.pyc +0 -0
  7. .venv/lib/python3.11/site-packages/google/api/__pycache__/consumer_pb2.cpython-311.pyc +0 -0
  8. .venv/lib/python3.11/site-packages/google/api/__pycache__/context_pb2.cpython-311.pyc +0 -0
  9. .venv/lib/python3.11/site-packages/google/api/__pycache__/control_pb2.cpython-311.pyc +0 -0
  10. .venv/lib/python3.11/site-packages/google/api/__pycache__/distribution_pb2.cpython-311.pyc +0 -0
  11. .venv/lib/python3.11/site-packages/google/api/__pycache__/documentation_pb2.cpython-311.pyc +0 -0
  12. .venv/lib/python3.11/site-packages/google/api/__pycache__/endpoint_pb2.cpython-311.pyc +0 -0
  13. .venv/lib/python3.11/site-packages/google/api/__pycache__/error_reason_pb2.cpython-311.pyc +0 -0
  14. .venv/lib/python3.11/site-packages/google/api/__pycache__/field_behavior_pb2.cpython-311.pyc +0 -0
  15. .venv/lib/python3.11/site-packages/google/api/__pycache__/field_info_pb2.cpython-311.pyc +0 -0
  16. .venv/lib/python3.11/site-packages/google/api/__pycache__/http_pb2.cpython-311.pyc +0 -0
  17. .venv/lib/python3.11/site-packages/google/api/__pycache__/httpbody_pb2.cpython-311.pyc +0 -0
  18. .venv/lib/python3.11/site-packages/google/api/__pycache__/label_pb2.cpython-311.pyc +0 -0
  19. .venv/lib/python3.11/site-packages/google/api/__pycache__/launch_stage_pb2.cpython-311.pyc +0 -0
  20. .venv/lib/python3.11/site-packages/google/api/__pycache__/log_pb2.cpython-311.pyc +0 -0
  21. .venv/lib/python3.11/site-packages/google/api/__pycache__/logging_pb2.cpython-311.pyc +0 -0
  22. .venv/lib/python3.11/site-packages/google/api/__pycache__/metric_pb2.cpython-311.pyc +0 -0
  23. .venv/lib/python3.11/site-packages/google/api/__pycache__/monitored_resource_pb2.cpython-311.pyc +0 -0
  24. .venv/lib/python3.11/site-packages/google/api/__pycache__/monitoring_pb2.cpython-311.pyc +0 -0
  25. .venv/lib/python3.11/site-packages/google/api/__pycache__/policy_pb2.cpython-311.pyc +0 -0
  26. .venv/lib/python3.11/site-packages/google/api/__pycache__/quota_pb2.cpython-311.pyc +0 -0
  27. .venv/lib/python3.11/site-packages/google/api/__pycache__/source_info_pb2.cpython-311.pyc +0 -0
  28. .venv/lib/python3.11/site-packages/google/api/__pycache__/system_parameter_pb2.cpython-311.pyc +0 -0
  29. .venv/lib/python3.11/site-packages/google/api/__pycache__/usage_pb2.cpython-311.pyc +0 -0
  30. .venv/lib/python3.11/site-packages/google/api/__pycache__/visibility_pb2.cpython-311.pyc +0 -0
  31. .venv/lib/python3.11/site-packages/google/api/auth_pb2.py +52 -0
  32. .venv/lib/python3.11/site-packages/google/api/system_parameter.proto +96 -0
  33. .venv/lib/python3.11/site-packages/google/api/usage.proto +96 -0
  34. .venv/lib/python3.11/site-packages/jinja2/__pycache__/__init__.cpython-311.pyc +0 -0
  35. .venv/lib/python3.11/site-packages/jinja2/__pycache__/_identifier.cpython-311.pyc +0 -0
  36. .venv/lib/python3.11/site-packages/jinja2/__pycache__/constants.cpython-311.pyc +0 -0
  37. .venv/lib/python3.11/site-packages/jinja2/__pycache__/debug.cpython-311.pyc +0 -0
  38. .venv/lib/python3.11/site-packages/jinja2/__pycache__/ext.cpython-311.pyc +0 -0
  39. .venv/lib/python3.11/site-packages/jinja2/__pycache__/filters.cpython-311.pyc +0 -0
  40. .venv/lib/python3.11/site-packages/jinja2/__pycache__/idtracking.cpython-311.pyc +0 -0
  41. .venv/lib/python3.11/site-packages/jinja2/__pycache__/loaders.cpython-311.pyc +0 -0
  42. .venv/lib/python3.11/site-packages/jinja2/__pycache__/nodes.cpython-311.pyc +0 -0
  43. .venv/lib/python3.11/site-packages/jinja2/__pycache__/optimizer.cpython-311.pyc +0 -0
  44. .venv/lib/python3.11/site-packages/jinja2/__pycache__/runtime.cpython-311.pyc +0 -0
  45. .venv/lib/python3.11/site-packages/jinja2/__pycache__/sandbox.cpython-311.pyc +0 -0
  46. .venv/lib/python3.11/site-packages/jinja2/__pycache__/tests.cpython-311.pyc +0 -0
  47. .venv/lib/python3.11/site-packages/jinja2/__pycache__/utils.cpython-311.pyc +0 -0
  48. .venv/lib/python3.11/site-packages/jinja2/__pycache__/visitor.cpython-311.pyc +0 -0
  49. .venv/lib/python3.11/site-packages/jinja2/async_utils.py +99 -0
  50. .venv/lib/python3.11/site-packages/jinja2/compiler.py +1998 -0
.gitattributes CHANGED
@@ -196,3 +196,4 @@ tuning-competition-baseline/.venv/lib/python3.11/site-packages/torch/_inductor/_
196
  .venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1alpha/services/retriever_service/transports/__pycache__/rest.cpython-311.pyc filter=lfs diff=lfs merge=lfs -text
197
  .venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1beta/services/retriever_service/transports/__pycache__/rest.cpython-311.pyc filter=lfs diff=lfs merge=lfs -text
198
  .venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1beta/services/retriever_service/__pycache__/client.cpython-311.pyc filter=lfs diff=lfs merge=lfs -text
 
 
196
  .venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1alpha/services/retriever_service/transports/__pycache__/rest.cpython-311.pyc filter=lfs diff=lfs merge=lfs -text
197
  .venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1beta/services/retriever_service/transports/__pycache__/rest.cpython-311.pyc filter=lfs diff=lfs merge=lfs -text
198
  .venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1beta/services/retriever_service/__pycache__/client.cpython-311.pyc filter=lfs diff=lfs merge=lfs -text
199
+ .venv/lib/python3.11/site-packages/google/_upb/_message.abi3.so filter=lfs diff=lfs merge=lfs -text
.venv/lib/python3.11/site-packages/google/_upb/_message.abi3.so ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:34d5e690ce9cc9436d760939742d6df1a0afb258df8a839fe7ff48c498095f30
3
+ size 390920
.venv/lib/python3.11/site-packages/google/api/__pycache__/annotations_pb2.cpython-311.pyc ADDED
Binary file (1.77 kB). View file
 
.venv/lib/python3.11/site-packages/google/api/__pycache__/auth_pb2.cpython-311.pyc ADDED
Binary file (2.73 kB). View file
 
.venv/lib/python3.11/site-packages/google/api/__pycache__/client_pb2.cpython-311.pyc ADDED
Binary file (7.65 kB). View file
 
.venv/lib/python3.11/site-packages/google/api/__pycache__/config_change_pb2.cpython-311.pyc ADDED
Binary file (2.07 kB). View file
 
.venv/lib/python3.11/site-packages/google/api/__pycache__/consumer_pb2.cpython-311.pyc ADDED
Binary file (2.01 kB). View file
 
.venv/lib/python3.11/site-packages/google/api/__pycache__/context_pb2.cpython-311.pyc ADDED
Binary file (1.86 kB). View file
 
.venv/lib/python3.11/site-packages/google/api/__pycache__/control_pb2.cpython-311.pyc ADDED
Binary file (1.77 kB). View file
 
.venv/lib/python3.11/site-packages/google/api/__pycache__/distribution_pb2.cpython-311.pyc ADDED
Binary file (3.42 kB). View file
 
.venv/lib/python3.11/site-packages/google/api/__pycache__/documentation_pb2.cpython-311.pyc ADDED
Binary file (2.17 kB). View file
 
.venv/lib/python3.11/site-packages/google/api/__pycache__/endpoint_pb2.cpython-311.pyc ADDED
Binary file (1.65 kB). View file
 
.venv/lib/python3.11/site-packages/google/api/__pycache__/error_reason_pb2.cpython-311.pyc ADDED
Binary file (2.55 kB). View file
 
.venv/lib/python3.11/site-packages/google/api/__pycache__/field_behavior_pb2.cpython-311.pyc ADDED
Binary file (2.08 kB). View file
 
.venv/lib/python3.11/site-packages/google/api/__pycache__/field_info_pb2.cpython-311.pyc ADDED
Binary file (2.23 kB). View file
 
.venv/lib/python3.11/site-packages/google/api/__pycache__/http_pb2.cpython-311.pyc ADDED
Binary file (2.15 kB). View file
 
.venv/lib/python3.11/site-packages/google/api/__pycache__/httpbody_pb2.cpython-311.pyc ADDED
Binary file (1.75 kB). View file
 
.venv/lib/python3.11/site-packages/google/api/__pycache__/label_pb2.cpython-311.pyc ADDED
Binary file (1.81 kB). View file
 
.venv/lib/python3.11/site-packages/google/api/__pycache__/launch_stage_pb2.cpython-311.pyc ADDED
Binary file (1.7 kB). View file
 
.venv/lib/python3.11/site-packages/google/api/__pycache__/log_pb2.cpython-311.pyc ADDED
Binary file (1.79 kB). View file
 
.venv/lib/python3.11/site-packages/google/api/__pycache__/logging_pb2.cpython-311.pyc ADDED
Binary file (1.9 kB). View file
 
.venv/lib/python3.11/site-packages/google/api/__pycache__/metric_pb2.cpython-311.pyc ADDED
Binary file (4.06 kB). View file
 
.venv/lib/python3.11/site-packages/google/api/__pycache__/monitored_resource_pb2.cpython-311.pyc ADDED
Binary file (3.13 kB). View file
 
.venv/lib/python3.11/site-packages/google/api/__pycache__/monitoring_pb2.cpython-311.pyc ADDED
Binary file (1.95 kB). View file
 
.venv/lib/python3.11/site-packages/google/api/__pycache__/policy_pb2.cpython-311.pyc ADDED
Binary file (2.14 kB). View file
 
.venv/lib/python3.11/site-packages/google/api/__pycache__/quota_pb2.cpython-311.pyc ADDED
Binary file (2.61 kB). View file
 
.venv/lib/python3.11/site-packages/google/api/__pycache__/source_info_pb2.cpython-311.pyc ADDED
Binary file (1.76 kB). View file
 
.venv/lib/python3.11/site-packages/google/api/__pycache__/system_parameter_pb2.cpython-311.pyc ADDED
Binary file (2.09 kB). View file
 
.venv/lib/python3.11/site-packages/google/api/__pycache__/usage_pb2.cpython-311.pyc ADDED
Binary file (1.86 kB). View file
 
.venv/lib/python3.11/site-packages/google/api/__pycache__/visibility_pb2.cpython-311.pyc ADDED
Binary file (2.47 kB). View file
 
.venv/lib/python3.11/site-packages/google/api/auth_pb2.py ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # Copyright 2024 Google LLC
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
18
+ # source: google/api/auth.proto
19
+ """Generated protocol buffer code."""
20
+ from google.protobuf import descriptor as _descriptor
21
+ from google.protobuf import descriptor_pool as _descriptor_pool
22
+ from google.protobuf import symbol_database as _symbol_database
23
+ from google.protobuf.internal import builder as _builder
24
+
25
+ # @@protoc_insertion_point(imports)
26
+
27
+ _sym_db = _symbol_database.Default()
28
+
29
+
30
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(
31
+ b'\n\x15google/api/auth.proto\x12\ngoogle.api"l\n\x0e\x41uthentication\x12-\n\x05rules\x18\x03 \x03(\x0b\x32\x1e.google.api.AuthenticationRule\x12+\n\tproviders\x18\x04 \x03(\x0b\x32\x18.google.api.AuthProvider"\xa9\x01\n\x12\x41uthenticationRule\x12\x10\n\x08selector\x18\x01 \x01(\t\x12,\n\x05oauth\x18\x02 \x01(\x0b\x32\x1d.google.api.OAuthRequirements\x12 \n\x18\x61llow_without_credential\x18\x05 \x01(\x08\x12\x31\n\x0crequirements\x18\x07 \x03(\x0b\x32\x1b.google.api.AuthRequirement"^\n\x0bJwtLocation\x12\x10\n\x06header\x18\x01 \x01(\tH\x00\x12\x0f\n\x05query\x18\x02 \x01(\tH\x00\x12\x10\n\x06\x63ookie\x18\x04 \x01(\tH\x00\x12\x14\n\x0cvalue_prefix\x18\x03 \x01(\tB\x04\n\x02in"\x9a\x01\n\x0c\x41uthProvider\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0e\n\x06issuer\x18\x02 \x01(\t\x12\x10\n\x08jwks_uri\x18\x03 \x01(\t\x12\x11\n\taudiences\x18\x04 \x01(\t\x12\x19\n\x11\x61uthorization_url\x18\x05 \x01(\t\x12.\n\rjwt_locations\x18\x06 \x03(\x0b\x32\x17.google.api.JwtLocation"-\n\x11OAuthRequirements\x12\x18\n\x10\x63\x61nonical_scopes\x18\x01 \x01(\t"9\n\x0f\x41uthRequirement\x12\x13\n\x0bprovider_id\x18\x01 \x01(\t\x12\x11\n\taudiences\x18\x02 \x01(\tBk\n\x0e\x63om.google.apiB\tAuthProtoP\x01ZEgoogle.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig\xa2\x02\x04GAPIb\x06proto3'
32
+ )
33
+
34
+ _globals = globals()
35
+ _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
36
+ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, "google.api.auth_pb2", _globals)
37
+ if _descriptor._USE_C_DESCRIPTORS == False:
38
+ DESCRIPTOR._options = None
39
+ DESCRIPTOR._serialized_options = b"\n\016com.google.apiB\tAuthProtoP\001ZEgoogle.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig\242\002\004GAPI"
40
+ _globals["_AUTHENTICATION"]._serialized_start = 37
41
+ _globals["_AUTHENTICATION"]._serialized_end = 145
42
+ _globals["_AUTHENTICATIONRULE"]._serialized_start = 148
43
+ _globals["_AUTHENTICATIONRULE"]._serialized_end = 317
44
+ _globals["_JWTLOCATION"]._serialized_start = 319
45
+ _globals["_JWTLOCATION"]._serialized_end = 413
46
+ _globals["_AUTHPROVIDER"]._serialized_start = 416
47
+ _globals["_AUTHPROVIDER"]._serialized_end = 570
48
+ _globals["_OAUTHREQUIREMENTS"]._serialized_start = 572
49
+ _globals["_OAUTHREQUIREMENTS"]._serialized_end = 617
50
+ _globals["_AUTHREQUIREMENT"]._serialized_start = 619
51
+ _globals["_AUTHREQUIREMENT"]._serialized_end = 676
52
+ # @@protoc_insertion_point(module_scope)
.venv/lib/python3.11/site-packages/google/api/system_parameter.proto ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright 2024 Google LLC
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ syntax = "proto3";
16
+
17
+ package google.api;
18
+
19
+ option go_package = "google.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig";
20
+ option java_multiple_files = true;
21
+ option java_outer_classname = "SystemParameterProto";
22
+ option java_package = "com.google.api";
23
+ option objc_class_prefix = "GAPI";
24
+
25
+ // ### System parameter configuration
26
+ //
27
+ // A system parameter is a special kind of parameter defined by the API
28
+ // system, not by an individual API. It is typically mapped to an HTTP header
29
+ // and/or a URL query parameter. This configuration specifies which methods
30
+ // change the names of the system parameters.
31
+ message SystemParameters {
32
+ // Define system parameters.
33
+ //
34
+ // The parameters defined here will override the default parameters
35
+ // implemented by the system. If this field is missing from the service
36
+ // config, default system parameters will be used. Default system parameters
37
+ // and names is implementation-dependent.
38
+ //
39
+ // Example: define api key for all methods
40
+ //
41
+ // system_parameters
42
+ // rules:
43
+ // - selector: "*"
44
+ // parameters:
45
+ // - name: api_key
46
+ // url_query_parameter: api_key
47
+ //
48
+ //
49
+ // Example: define 2 api key names for a specific method.
50
+ //
51
+ // system_parameters
52
+ // rules:
53
+ // - selector: "/ListShelves"
54
+ // parameters:
55
+ // - name: api_key
56
+ // http_header: Api-Key1
57
+ // - name: api_key
58
+ // http_header: Api-Key2
59
+ //
60
+ // **NOTE:** All service configuration rules follow "last one wins" order.
61
+ repeated SystemParameterRule rules = 1;
62
+ }
63
+
64
+ // Define a system parameter rule mapping system parameter definitions to
65
+ // methods.
66
+ message SystemParameterRule {
67
+ // Selects the methods to which this rule applies. Use '*' to indicate all
68
+ // methods in all APIs.
69
+ //
70
+ // Refer to [selector][google.api.DocumentationRule.selector] for syntax
71
+ // details.
72
+ string selector = 1;
73
+
74
+ // Define parameters. Multiple names may be defined for a parameter.
75
+ // For a given method call, only one of them should be used. If multiple
76
+ // names are used the behavior is implementation-dependent.
77
+ // If none of the specified names are present the behavior is
78
+ // parameter-dependent.
79
+ repeated SystemParameter parameters = 2;
80
+ }
81
+
82
+ // Define a parameter's name and location. The parameter may be passed as either
83
+ // an HTTP header or a URL query parameter, and if both are passed the behavior
84
+ // is implementation-dependent.
85
+ message SystemParameter {
86
+ // Define the name of the parameter, such as "api_key" . It is case sensitive.
87
+ string name = 1;
88
+
89
+ // Define the HTTP header name to use for the parameter. It is case
90
+ // insensitive.
91
+ string http_header = 2;
92
+
93
+ // Define the URL query parameter name to use for the parameter. It is case
94
+ // sensitive.
95
+ string url_query_parameter = 3;
96
+ }
.venv/lib/python3.11/site-packages/google/api/usage.proto ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright 2024 Google LLC
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ syntax = "proto3";
16
+
17
+ package google.api;
18
+
19
+ option go_package = "google.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig";
20
+ option java_multiple_files = true;
21
+ option java_outer_classname = "UsageProto";
22
+ option java_package = "com.google.api";
23
+ option objc_class_prefix = "GAPI";
24
+
25
+ // Configuration controlling usage of a service.
26
+ message Usage {
27
+ // Requirements that must be satisfied before a consumer project can use the
28
+ // service. Each requirement is of the form <service.name>/<requirement-id>;
29
+ // for example 'serviceusage.googleapis.com/billing-enabled'.
30
+ //
31
+ // For Google APIs, a Terms of Service requirement must be included here.
32
+ // Google Cloud APIs must include "serviceusage.googleapis.com/tos/cloud".
33
+ // Other Google APIs should include
34
+ // "serviceusage.googleapis.com/tos/universal". Additional ToS can be
35
+ // included based on the business needs.
36
+ repeated string requirements = 1;
37
+
38
+ // A list of usage rules that apply to individual API methods.
39
+ //
40
+ // **NOTE:** All service configuration rules follow "last one wins" order.
41
+ repeated UsageRule rules = 6;
42
+
43
+ // The full resource name of a channel used for sending notifications to the
44
+ // service producer.
45
+ //
46
+ // Google Service Management currently only supports
47
+ // [Google Cloud Pub/Sub](https://cloud.google.com/pubsub) as a notification
48
+ // channel. To use Google Cloud Pub/Sub as the channel, this must be the name
49
+ // of a Cloud Pub/Sub topic that uses the Cloud Pub/Sub topic name format
50
+ // documented in https://cloud.google.com/pubsub/docs/overview.
51
+ string producer_notification_channel = 7;
52
+ }
53
+
54
+ // Usage configuration rules for the service.
55
+ //
56
+ // NOTE: Under development.
57
+ //
58
+ //
59
+ // Use this rule to configure unregistered calls for the service. Unregistered
60
+ // calls are calls that do not contain consumer project identity.
61
+ // (Example: calls that do not contain an API key).
62
+ // By default, API methods do not allow unregistered calls, and each method call
63
+ // must be identified by a consumer project identity. Use this rule to
64
+ // allow/disallow unregistered calls.
65
+ //
66
+ // Example of an API that wants to allow unregistered calls for entire service.
67
+ //
68
+ // usage:
69
+ // rules:
70
+ // - selector: "*"
71
+ // allow_unregistered_calls: true
72
+ //
73
+ // Example of a method that wants to allow unregistered calls.
74
+ //
75
+ // usage:
76
+ // rules:
77
+ // - selector: "google.example.library.v1.LibraryService.CreateBook"
78
+ // allow_unregistered_calls: true
79
+ message UsageRule {
80
+ // Selects the methods to which this rule applies. Use '*' to indicate all
81
+ // methods in all APIs.
82
+ //
83
+ // Refer to [selector][google.api.DocumentationRule.selector] for syntax
84
+ // details.
85
+ string selector = 1;
86
+
87
+ // If true, the selected method allows unregistered calls, e.g. calls
88
+ // that don't identify any user or application.
89
+ bool allow_unregistered_calls = 2;
90
+
91
+ // If true, the selected method should skip service control and the control
92
+ // plane features, such as quota and billing, will not be available.
93
+ // This flag is used by Google Cloud Endpoints to bypass checks for internal
94
+ // methods, such as service health check methods.
95
+ bool skip_service_control = 3;
96
+ }
.venv/lib/python3.11/site-packages/jinja2/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (2.11 kB). View file
 
.venv/lib/python3.11/site-packages/jinja2/__pycache__/_identifier.cpython-311.pyc ADDED
Binary file (2.13 kB). View file
 
.venv/lib/python3.11/site-packages/jinja2/__pycache__/constants.cpython-311.pyc ADDED
Binary file (1.55 kB). View file
 
.venv/lib/python3.11/site-packages/jinja2/__pycache__/debug.cpython-311.pyc ADDED
Binary file (6.71 kB). View file
 
.venv/lib/python3.11/site-packages/jinja2/__pycache__/ext.cpython-311.pyc ADDED
Binary file (43.4 kB). View file
 
.venv/lib/python3.11/site-packages/jinja2/__pycache__/filters.cpython-311.pyc ADDED
Binary file (77.9 kB). View file
 
.venv/lib/python3.11/site-packages/jinja2/__pycache__/idtracking.cpython-311.pyc ADDED
Binary file (19.5 kB). View file
 
.venv/lib/python3.11/site-packages/jinja2/__pycache__/loaders.cpython-311.pyc ADDED
Binary file (34.4 kB). View file
 
.venv/lib/python3.11/site-packages/jinja2/__pycache__/nodes.cpython-311.pyc ADDED
Binary file (64.5 kB). View file
 
.venv/lib/python3.11/site-packages/jinja2/__pycache__/optimizer.cpython-311.pyc ADDED
Binary file (2.84 kB). View file
 
.venv/lib/python3.11/site-packages/jinja2/__pycache__/runtime.cpython-311.pyc ADDED
Binary file (51.1 kB). View file
 
.venv/lib/python3.11/site-packages/jinja2/__pycache__/sandbox.cpython-311.pyc ADDED
Binary file (19.2 kB). View file
 
.venv/lib/python3.11/site-packages/jinja2/__pycache__/tests.cpython-311.pyc ADDED
Binary file (9.26 kB). View file
 
.venv/lib/python3.11/site-packages/jinja2/__pycache__/utils.cpython-311.pyc ADDED
Binary file (37.6 kB). View file
 
.venv/lib/python3.11/site-packages/jinja2/__pycache__/visitor.cpython-311.pyc ADDED
Binary file (5.69 kB). View file
 
.venv/lib/python3.11/site-packages/jinja2/async_utils.py ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import inspect
2
+ import typing as t
3
+ from functools import WRAPPER_ASSIGNMENTS
4
+ from functools import wraps
5
+
6
+ from .utils import _PassArg
7
+ from .utils import pass_eval_context
8
+
9
+ if t.TYPE_CHECKING:
10
+ import typing_extensions as te
11
+
12
+ V = t.TypeVar("V")
13
+
14
+
15
+ def async_variant(normal_func): # type: ignore
16
+ def decorator(async_func): # type: ignore
17
+ pass_arg = _PassArg.from_obj(normal_func)
18
+ need_eval_context = pass_arg is None
19
+
20
+ if pass_arg is _PassArg.environment:
21
+
22
+ def is_async(args: t.Any) -> bool:
23
+ return t.cast(bool, args[0].is_async)
24
+
25
+ else:
26
+
27
+ def is_async(args: t.Any) -> bool:
28
+ return t.cast(bool, args[0].environment.is_async)
29
+
30
+ # Take the doc and annotations from the sync function, but the
31
+ # name from the async function. Pallets-Sphinx-Themes
32
+ # build_function_directive expects __wrapped__ to point to the
33
+ # sync function.
34
+ async_func_attrs = ("__module__", "__name__", "__qualname__")
35
+ normal_func_attrs = tuple(set(WRAPPER_ASSIGNMENTS).difference(async_func_attrs))
36
+
37
+ @wraps(normal_func, assigned=normal_func_attrs)
38
+ @wraps(async_func, assigned=async_func_attrs, updated=())
39
+ def wrapper(*args, **kwargs): # type: ignore
40
+ b = is_async(args)
41
+
42
+ if need_eval_context:
43
+ args = args[1:]
44
+
45
+ if b:
46
+ return async_func(*args, **kwargs)
47
+
48
+ return normal_func(*args, **kwargs)
49
+
50
+ if need_eval_context:
51
+ wrapper = pass_eval_context(wrapper)
52
+
53
+ wrapper.jinja_async_variant = True # type: ignore[attr-defined]
54
+ return wrapper
55
+
56
+ return decorator
57
+
58
+
59
+ _common_primitives = {int, float, bool, str, list, dict, tuple, type(None)}
60
+
61
+
62
+ async def auto_await(value: t.Union[t.Awaitable["V"], "V"]) -> "V":
63
+ # Avoid a costly call to isawaitable
64
+ if type(value) in _common_primitives:
65
+ return t.cast("V", value)
66
+
67
+ if inspect.isawaitable(value):
68
+ return await t.cast("t.Awaitable[V]", value)
69
+
70
+ return value
71
+
72
+
73
+ class _IteratorToAsyncIterator(t.Generic[V]):
74
+ def __init__(self, iterator: "t.Iterator[V]"):
75
+ self._iterator = iterator
76
+
77
+ def __aiter__(self) -> "te.Self":
78
+ return self
79
+
80
+ async def __anext__(self) -> V:
81
+ try:
82
+ return next(self._iterator)
83
+ except StopIteration as e:
84
+ raise StopAsyncIteration(e.value) from e
85
+
86
+
87
+ def auto_aiter(
88
+ iterable: "t.Union[t.AsyncIterable[V], t.Iterable[V]]",
89
+ ) -> "t.AsyncIterator[V]":
90
+ if hasattr(iterable, "__aiter__"):
91
+ return iterable.__aiter__()
92
+ else:
93
+ return _IteratorToAsyncIterator(iter(iterable))
94
+
95
+
96
+ async def auto_to_list(
97
+ value: "t.Union[t.AsyncIterable[V], t.Iterable[V]]",
98
+ ) -> t.List["V"]:
99
+ return [x async for x in auto_aiter(value)]
.venv/lib/python3.11/site-packages/jinja2/compiler.py ADDED
@@ -0,0 +1,1998 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Compiles nodes from the parser into Python code."""
2
+
3
+ import typing as t
4
+ from contextlib import contextmanager
5
+ from functools import update_wrapper
6
+ from io import StringIO
7
+ from itertools import chain
8
+ from keyword import iskeyword as is_python_keyword
9
+
10
+ from markupsafe import escape
11
+ from markupsafe import Markup
12
+
13
+ from . import nodes
14
+ from .exceptions import TemplateAssertionError
15
+ from .idtracking import Symbols
16
+ from .idtracking import VAR_LOAD_ALIAS
17
+ from .idtracking import VAR_LOAD_PARAMETER
18
+ from .idtracking import VAR_LOAD_RESOLVE
19
+ from .idtracking import VAR_LOAD_UNDEFINED
20
+ from .nodes import EvalContext
21
+ from .optimizer import Optimizer
22
+ from .utils import _PassArg
23
+ from .utils import concat
24
+ from .visitor import NodeVisitor
25
+
26
+ if t.TYPE_CHECKING:
27
+ import typing_extensions as te
28
+
29
+ from .environment import Environment
30
+
31
+ F = t.TypeVar("F", bound=t.Callable[..., t.Any])
32
+
33
+ operators = {
34
+ "eq": "==",
35
+ "ne": "!=",
36
+ "gt": ">",
37
+ "gteq": ">=",
38
+ "lt": "<",
39
+ "lteq": "<=",
40
+ "in": "in",
41
+ "notin": "not in",
42
+ }
43
+
44
+
45
+ def optimizeconst(f: F) -> F:
46
+ def new_func(
47
+ self: "CodeGenerator", node: nodes.Expr, frame: "Frame", **kwargs: t.Any
48
+ ) -> t.Any:
49
+ # Only optimize if the frame is not volatile
50
+ if self.optimizer is not None and not frame.eval_ctx.volatile:
51
+ new_node = self.optimizer.visit(node, frame.eval_ctx)
52
+
53
+ if new_node != node:
54
+ return self.visit(new_node, frame)
55
+
56
+ return f(self, node, frame, **kwargs)
57
+
58
+ return update_wrapper(new_func, f) # type: ignore[return-value]
59
+
60
+
61
+ def _make_binop(op: str) -> t.Callable[["CodeGenerator", nodes.BinExpr, "Frame"], None]:
62
+ @optimizeconst
63
+ def visitor(self: "CodeGenerator", node: nodes.BinExpr, frame: Frame) -> None:
64
+ if (
65
+ self.environment.sandboxed and op in self.environment.intercepted_binops # type: ignore
66
+ ):
67
+ self.write(f"environment.call_binop(context, {op!r}, ")
68
+ self.visit(node.left, frame)
69
+ self.write(", ")
70
+ self.visit(node.right, frame)
71
+ else:
72
+ self.write("(")
73
+ self.visit(node.left, frame)
74
+ self.write(f" {op} ")
75
+ self.visit(node.right, frame)
76
+
77
+ self.write(")")
78
+
79
+ return visitor
80
+
81
+
82
+ def _make_unop(
83
+ op: str,
84
+ ) -> t.Callable[["CodeGenerator", nodes.UnaryExpr, "Frame"], None]:
85
+ @optimizeconst
86
+ def visitor(self: "CodeGenerator", node: nodes.UnaryExpr, frame: Frame) -> None:
87
+ if (
88
+ self.environment.sandboxed and op in self.environment.intercepted_unops # type: ignore
89
+ ):
90
+ self.write(f"environment.call_unop(context, {op!r}, ")
91
+ self.visit(node.node, frame)
92
+ else:
93
+ self.write("(" + op)
94
+ self.visit(node.node, frame)
95
+
96
+ self.write(")")
97
+
98
+ return visitor
99
+
100
+
101
+ def generate(
102
+ node: nodes.Template,
103
+ environment: "Environment",
104
+ name: t.Optional[str],
105
+ filename: t.Optional[str],
106
+ stream: t.Optional[t.TextIO] = None,
107
+ defer_init: bool = False,
108
+ optimized: bool = True,
109
+ ) -> t.Optional[str]:
110
+ """Generate the python source for a node tree."""
111
+ if not isinstance(node, nodes.Template):
112
+ raise TypeError("Can't compile non template nodes")
113
+
114
+ generator = environment.code_generator_class(
115
+ environment, name, filename, stream, defer_init, optimized
116
+ )
117
+ generator.visit(node)
118
+
119
+ if stream is None:
120
+ return generator.stream.getvalue() # type: ignore
121
+
122
+ return None
123
+
124
+
125
+ def has_safe_repr(value: t.Any) -> bool:
126
+ """Does the node have a safe representation?"""
127
+ if value is None or value is NotImplemented or value is Ellipsis:
128
+ return True
129
+
130
+ if type(value) in {bool, int, float, complex, range, str, Markup}:
131
+ return True
132
+
133
+ if type(value) in {tuple, list, set, frozenset}:
134
+ return all(has_safe_repr(v) for v in value)
135
+
136
+ if type(value) is dict: # noqa E721
137
+ return all(has_safe_repr(k) and has_safe_repr(v) for k, v in value.items())
138
+
139
+ return False
140
+
141
+
142
+ def find_undeclared(
143
+ nodes: t.Iterable[nodes.Node], names: t.Iterable[str]
144
+ ) -> t.Set[str]:
145
+ """Check if the names passed are accessed undeclared. The return value
146
+ is a set of all the undeclared names from the sequence of names found.
147
+ """
148
+ visitor = UndeclaredNameVisitor(names)
149
+ try:
150
+ for node in nodes:
151
+ visitor.visit(node)
152
+ except VisitorExit:
153
+ pass
154
+ return visitor.undeclared
155
+
156
+
157
+ class MacroRef:
158
+ def __init__(self, node: t.Union[nodes.Macro, nodes.CallBlock]) -> None:
159
+ self.node = node
160
+ self.accesses_caller = False
161
+ self.accesses_kwargs = False
162
+ self.accesses_varargs = False
163
+
164
+
165
+ class Frame:
166
+ """Holds compile time information for us."""
167
+
168
+ def __init__(
169
+ self,
170
+ eval_ctx: EvalContext,
171
+ parent: t.Optional["Frame"] = None,
172
+ level: t.Optional[int] = None,
173
+ ) -> None:
174
+ self.eval_ctx = eval_ctx
175
+
176
+ # the parent of this frame
177
+ self.parent = parent
178
+
179
+ if parent is None:
180
+ self.symbols = Symbols(level=level)
181
+
182
+ # in some dynamic inheritance situations the compiler needs to add
183
+ # write tests around output statements.
184
+ self.require_output_check = False
185
+
186
+ # inside some tags we are using a buffer rather than yield statements.
187
+ # this for example affects {% filter %} or {% macro %}. If a frame
188
+ # is buffered this variable points to the name of the list used as
189
+ # buffer.
190
+ self.buffer: t.Optional[str] = None
191
+
192
+ # the name of the block we're in, otherwise None.
193
+ self.block: t.Optional[str] = None
194
+
195
+ else:
196
+ self.symbols = Symbols(parent.symbols, level=level)
197
+ self.require_output_check = parent.require_output_check
198
+ self.buffer = parent.buffer
199
+ self.block = parent.block
200
+
201
+ # a toplevel frame is the root + soft frames such as if conditions.
202
+ self.toplevel = False
203
+
204
+ # the root frame is basically just the outermost frame, so no if
205
+ # conditions. This information is used to optimize inheritance
206
+ # situations.
207
+ self.rootlevel = False
208
+
209
+ # variables set inside of loops and blocks should not affect outer frames,
210
+ # but they still needs to be kept track of as part of the active context.
211
+ self.loop_frame = False
212
+ self.block_frame = False
213
+
214
+ # track whether the frame is being used in an if-statement or conditional
215
+ # expression as it determines which errors should be raised during runtime
216
+ # or compile time.
217
+ self.soft_frame = False
218
+
219
+ def copy(self) -> "te.Self":
220
+ """Create a copy of the current one."""
221
+ rv = object.__new__(self.__class__)
222
+ rv.__dict__.update(self.__dict__)
223
+ rv.symbols = self.symbols.copy()
224
+ return rv
225
+
226
+ def inner(self, isolated: bool = False) -> "Frame":
227
+ """Return an inner frame."""
228
+ if isolated:
229
+ return Frame(self.eval_ctx, level=self.symbols.level + 1)
230
+ return Frame(self.eval_ctx, self)
231
+
232
+ def soft(self) -> "te.Self":
233
+ """Return a soft frame. A soft frame may not be modified as
234
+ standalone thing as it shares the resources with the frame it
235
+ was created of, but it's not a rootlevel frame any longer.
236
+
237
+ This is only used to implement if-statements and conditional
238
+ expressions.
239
+ """
240
+ rv = self.copy()
241
+ rv.rootlevel = False
242
+ rv.soft_frame = True
243
+ return rv
244
+
245
+ __copy__ = copy
246
+
247
+
248
+ class VisitorExit(RuntimeError):
249
+ """Exception used by the `UndeclaredNameVisitor` to signal a stop."""
250
+
251
+
252
+ class DependencyFinderVisitor(NodeVisitor):
253
+ """A visitor that collects filter and test calls."""
254
+
255
+ def __init__(self) -> None:
256
+ self.filters: t.Set[str] = set()
257
+ self.tests: t.Set[str] = set()
258
+
259
+ def visit_Filter(self, node: nodes.Filter) -> None:
260
+ self.generic_visit(node)
261
+ self.filters.add(node.name)
262
+
263
+ def visit_Test(self, node: nodes.Test) -> None:
264
+ self.generic_visit(node)
265
+ self.tests.add(node.name)
266
+
267
+ def visit_Block(self, node: nodes.Block) -> None:
268
+ """Stop visiting at blocks."""
269
+
270
+
271
+ class UndeclaredNameVisitor(NodeVisitor):
272
+ """A visitor that checks if a name is accessed without being
273
+ declared. This is different from the frame visitor as it will
274
+ not stop at closure frames.
275
+ """
276
+
277
+ def __init__(self, names: t.Iterable[str]) -> None:
278
+ self.names = set(names)
279
+ self.undeclared: t.Set[str] = set()
280
+
281
+ def visit_Name(self, node: nodes.Name) -> None:
282
+ if node.ctx == "load" and node.name in self.names:
283
+ self.undeclared.add(node.name)
284
+ if self.undeclared == self.names:
285
+ raise VisitorExit()
286
+ else:
287
+ self.names.discard(node.name)
288
+
289
+ def visit_Block(self, node: nodes.Block) -> None:
290
+ """Stop visiting a blocks."""
291
+
292
+
293
+ class CompilerExit(Exception):
294
+ """Raised if the compiler encountered a situation where it just
295
+ doesn't make sense to further process the code. Any block that
296
+ raises such an exception is not further processed.
297
+ """
298
+
299
+
300
+ class CodeGenerator(NodeVisitor):
301
+ def __init__(
302
+ self,
303
+ environment: "Environment",
304
+ name: t.Optional[str],
305
+ filename: t.Optional[str],
306
+ stream: t.Optional[t.TextIO] = None,
307
+ defer_init: bool = False,
308
+ optimized: bool = True,
309
+ ) -> None:
310
+ if stream is None:
311
+ stream = StringIO()
312
+ self.environment = environment
313
+ self.name = name
314
+ self.filename = filename
315
+ self.stream = stream
316
+ self.created_block_context = False
317
+ self.defer_init = defer_init
318
+ self.optimizer: t.Optional[Optimizer] = None
319
+
320
+ if optimized:
321
+ self.optimizer = Optimizer(environment)
322
+
323
+ # aliases for imports
324
+ self.import_aliases: t.Dict[str, str] = {}
325
+
326
+ # a registry for all blocks. Because blocks are moved out
327
+ # into the global python scope they are registered here
328
+ self.blocks: t.Dict[str, nodes.Block] = {}
329
+
330
+ # the number of extends statements so far
331
+ self.extends_so_far = 0
332
+
333
+ # some templates have a rootlevel extends. In this case we
334
+ # can safely assume that we're a child template and do some
335
+ # more optimizations.
336
+ self.has_known_extends = False
337
+
338
+ # the current line number
339
+ self.code_lineno = 1
340
+
341
+ # registry of all filters and tests (global, not block local)
342
+ self.tests: t.Dict[str, str] = {}
343
+ self.filters: t.Dict[str, str] = {}
344
+
345
+ # the debug information
346
+ self.debug_info: t.List[t.Tuple[int, int]] = []
347
+ self._write_debug_info: t.Optional[int] = None
348
+
349
+ # the number of new lines before the next write()
350
+ self._new_lines = 0
351
+
352
+ # the line number of the last written statement
353
+ self._last_line = 0
354
+
355
+ # true if nothing was written so far.
356
+ self._first_write = True
357
+
358
+ # used by the `temporary_identifier` method to get new
359
+ # unique, temporary identifier
360
+ self._last_identifier = 0
361
+
362
+ # the current indentation
363
+ self._indentation = 0
364
+
365
+ # Tracks toplevel assignments
366
+ self._assign_stack: t.List[t.Set[str]] = []
367
+
368
+ # Tracks parameter definition blocks
369
+ self._param_def_block: t.List[t.Set[str]] = []
370
+
371
+ # Tracks the current context.
372
+ self._context_reference_stack = ["context"]
373
+
374
+ @property
375
+ def optimized(self) -> bool:
376
+ return self.optimizer is not None
377
+
378
+ # -- Various compilation helpers
379
+
380
+ def fail(self, msg: str, lineno: int) -> "te.NoReturn":
381
+ """Fail with a :exc:`TemplateAssertionError`."""
382
+ raise TemplateAssertionError(msg, lineno, self.name, self.filename)
383
+
384
+ def temporary_identifier(self) -> str:
385
+ """Get a new unique identifier."""
386
+ self._last_identifier += 1
387
+ return f"t_{self._last_identifier}"
388
+
389
+ def buffer(self, frame: Frame) -> None:
390
+ """Enable buffering for the frame from that point onwards."""
391
+ frame.buffer = self.temporary_identifier()
392
+ self.writeline(f"{frame.buffer} = []")
393
+
394
+ def return_buffer_contents(
395
+ self, frame: Frame, force_unescaped: bool = False
396
+ ) -> None:
397
+ """Return the buffer contents of the frame."""
398
+ if not force_unescaped:
399
+ if frame.eval_ctx.volatile:
400
+ self.writeline("if context.eval_ctx.autoescape:")
401
+ self.indent()
402
+ self.writeline(f"return Markup(concat({frame.buffer}))")
403
+ self.outdent()
404
+ self.writeline("else:")
405
+ self.indent()
406
+ self.writeline(f"return concat({frame.buffer})")
407
+ self.outdent()
408
+ return
409
+ elif frame.eval_ctx.autoescape:
410
+ self.writeline(f"return Markup(concat({frame.buffer}))")
411
+ return
412
+ self.writeline(f"return concat({frame.buffer})")
413
+
414
+ def indent(self) -> None:
415
+ """Indent by one."""
416
+ self._indentation += 1
417
+
418
+ def outdent(self, step: int = 1) -> None:
419
+ """Outdent by step."""
420
+ self._indentation -= step
421
+
422
+ def start_write(self, frame: Frame, node: t.Optional[nodes.Node] = None) -> None:
423
+ """Yield or write into the frame buffer."""
424
+ if frame.buffer is None:
425
+ self.writeline("yield ", node)
426
+ else:
427
+ self.writeline(f"{frame.buffer}.append(", node)
428
+
429
+ def end_write(self, frame: Frame) -> None:
430
+ """End the writing process started by `start_write`."""
431
+ if frame.buffer is not None:
432
+ self.write(")")
433
+
434
+ def simple_write(
435
+ self, s: str, frame: Frame, node: t.Optional[nodes.Node] = None
436
+ ) -> None:
437
+ """Simple shortcut for start_write + write + end_write."""
438
+ self.start_write(frame, node)
439
+ self.write(s)
440
+ self.end_write(frame)
441
+
442
+ def blockvisit(self, nodes: t.Iterable[nodes.Node], frame: Frame) -> None:
443
+ """Visit a list of nodes as block in a frame. If the current frame
444
+ is no buffer a dummy ``if 0: yield None`` is written automatically.
445
+ """
446
+ try:
447
+ self.writeline("pass")
448
+ for node in nodes:
449
+ self.visit(node, frame)
450
+ except CompilerExit:
451
+ pass
452
+
453
+ def write(self, x: str) -> None:
454
+ """Write a string into the output stream."""
455
+ if self._new_lines:
456
+ if not self._first_write:
457
+ self.stream.write("\n" * self._new_lines)
458
+ self.code_lineno += self._new_lines
459
+ if self._write_debug_info is not None:
460
+ self.debug_info.append((self._write_debug_info, self.code_lineno))
461
+ self._write_debug_info = None
462
+ self._first_write = False
463
+ self.stream.write(" " * self._indentation)
464
+ self._new_lines = 0
465
+ self.stream.write(x)
466
+
467
+ def writeline(
468
+ self, x: str, node: t.Optional[nodes.Node] = None, extra: int = 0
469
+ ) -> None:
470
+ """Combination of newline and write."""
471
+ self.newline(node, extra)
472
+ self.write(x)
473
+
474
+ def newline(self, node: t.Optional[nodes.Node] = None, extra: int = 0) -> None:
475
+ """Add one or more newlines before the next write."""
476
+ self._new_lines = max(self._new_lines, 1 + extra)
477
+ if node is not None and node.lineno != self._last_line:
478
+ self._write_debug_info = node.lineno
479
+ self._last_line = node.lineno
480
+
481
+ def signature(
482
+ self,
483
+ node: t.Union[nodes.Call, nodes.Filter, nodes.Test],
484
+ frame: Frame,
485
+ extra_kwargs: t.Optional[t.Mapping[str, t.Any]] = None,
486
+ ) -> None:
487
+ """Writes a function call to the stream for the current node.
488
+ A leading comma is added automatically. The extra keyword
489
+ arguments may not include python keywords otherwise a syntax
490
+ error could occur. The extra keyword arguments should be given
491
+ as python dict.
492
+ """
493
+ # if any of the given keyword arguments is a python keyword
494
+ # we have to make sure that no invalid call is created.
495
+ kwarg_workaround = any(
496
+ is_python_keyword(t.cast(str, k))
497
+ for k in chain((x.key for x in node.kwargs), extra_kwargs or ())
498
+ )
499
+
500
+ for arg in node.args:
501
+ self.write(", ")
502
+ self.visit(arg, frame)
503
+
504
+ if not kwarg_workaround:
505
+ for kwarg in node.kwargs:
506
+ self.write(", ")
507
+ self.visit(kwarg, frame)
508
+ if extra_kwargs is not None:
509
+ for key, value in extra_kwargs.items():
510
+ self.write(f", {key}={value}")
511
+ if node.dyn_args:
512
+ self.write(", *")
513
+ self.visit(node.dyn_args, frame)
514
+
515
+ if kwarg_workaround:
516
+ if node.dyn_kwargs is not None:
517
+ self.write(", **dict({")
518
+ else:
519
+ self.write(", **{")
520
+ for kwarg in node.kwargs:
521
+ self.write(f"{kwarg.key!r}: ")
522
+ self.visit(kwarg.value, frame)
523
+ self.write(", ")
524
+ if extra_kwargs is not None:
525
+ for key, value in extra_kwargs.items():
526
+ self.write(f"{key!r}: {value}, ")
527
+ if node.dyn_kwargs is not None:
528
+ self.write("}, **")
529
+ self.visit(node.dyn_kwargs, frame)
530
+ self.write(")")
531
+ else:
532
+ self.write("}")
533
+
534
+ elif node.dyn_kwargs is not None:
535
+ self.write(", **")
536
+ self.visit(node.dyn_kwargs, frame)
537
+
538
+ def pull_dependencies(self, nodes: t.Iterable[nodes.Node]) -> None:
539
+ """Find all filter and test names used in the template and
540
+ assign them to variables in the compiled namespace. Checking
541
+ that the names are registered with the environment is done when
542
+ compiling the Filter and Test nodes. If the node is in an If or
543
+ CondExpr node, the check is done at runtime instead.
544
+
545
+ .. versionchanged:: 3.0
546
+ Filters and tests in If and CondExpr nodes are checked at
547
+ runtime instead of compile time.
548
+ """
549
+ visitor = DependencyFinderVisitor()
550
+
551
+ for node in nodes:
552
+ visitor.visit(node)
553
+
554
+ for id_map, names, dependency in (
555
+ (self.filters, visitor.filters, "filters"),
556
+ (
557
+ self.tests,
558
+ visitor.tests,
559
+ "tests",
560
+ ),
561
+ ):
562
+ for name in sorted(names):
563
+ if name not in id_map:
564
+ id_map[name] = self.temporary_identifier()
565
+
566
+ # add check during runtime that dependencies used inside of executed
567
+ # blocks are defined, as this step may be skipped during compile time
568
+ self.writeline("try:")
569
+ self.indent()
570
+ self.writeline(f"{id_map[name]} = environment.{dependency}[{name!r}]")
571
+ self.outdent()
572
+ self.writeline("except KeyError:")
573
+ self.indent()
574
+ self.writeline("@internalcode")
575
+ self.writeline(f"def {id_map[name]}(*unused):")
576
+ self.indent()
577
+ self.writeline(
578
+ f'raise TemplateRuntimeError("No {dependency[:-1]}'
579
+ f' named {name!r} found.")'
580
+ )
581
+ self.outdent()
582
+ self.outdent()
583
+
584
+ def enter_frame(self, frame: Frame) -> None:
585
+ undefs = []
586
+ for target, (action, param) in frame.symbols.loads.items():
587
+ if action == VAR_LOAD_PARAMETER:
588
+ pass
589
+ elif action == VAR_LOAD_RESOLVE:
590
+ self.writeline(f"{target} = {self.get_resolve_func()}({param!r})")
591
+ elif action == VAR_LOAD_ALIAS:
592
+ self.writeline(f"{target} = {param}")
593
+ elif action == VAR_LOAD_UNDEFINED:
594
+ undefs.append(target)
595
+ else:
596
+ raise NotImplementedError("unknown load instruction")
597
+ if undefs:
598
+ self.writeline(f"{' = '.join(undefs)} = missing")
599
+
600
+ def leave_frame(self, frame: Frame, with_python_scope: bool = False) -> None:
601
+ if not with_python_scope:
602
+ undefs = []
603
+ for target in frame.symbols.loads:
604
+ undefs.append(target)
605
+ if undefs:
606
+ self.writeline(f"{' = '.join(undefs)} = missing")
607
+
608
+ def choose_async(self, async_value: str = "async ", sync_value: str = "") -> str:
609
+ return async_value if self.environment.is_async else sync_value
610
+
611
+ def func(self, name: str) -> str:
612
+ return f"{self.choose_async()}def {name}"
613
+
614
+ def macro_body(
615
+ self, node: t.Union[nodes.Macro, nodes.CallBlock], frame: Frame
616
+ ) -> t.Tuple[Frame, MacroRef]:
617
+ """Dump the function def of a macro or call block."""
618
+ frame = frame.inner()
619
+ frame.symbols.analyze_node(node)
620
+ macro_ref = MacroRef(node)
621
+
622
+ explicit_caller = None
623
+ skip_special_params = set()
624
+ args = []
625
+
626
+ for idx, arg in enumerate(node.args):
627
+ if arg.name == "caller":
628
+ explicit_caller = idx
629
+ if arg.name in ("kwargs", "varargs"):
630
+ skip_special_params.add(arg.name)
631
+ args.append(frame.symbols.ref(arg.name))
632
+
633
+ undeclared = find_undeclared(node.body, ("caller", "kwargs", "varargs"))
634
+
635
+ if "caller" in undeclared:
636
+ # In older Jinja versions there was a bug that allowed caller
637
+ # to retain the special behavior even if it was mentioned in
638
+ # the argument list. However thankfully this was only really
639
+ # working if it was the last argument. So we are explicitly
640
+ # checking this now and error out if it is anywhere else in
641
+ # the argument list.
642
+ if explicit_caller is not None:
643
+ try:
644
+ node.defaults[explicit_caller - len(node.args)]
645
+ except IndexError:
646
+ self.fail(
647
+ "When defining macros or call blocks the "
648
+ 'special "caller" argument must be omitted '
649
+ "or be given a default.",
650
+ node.lineno,
651
+ )
652
+ else:
653
+ args.append(frame.symbols.declare_parameter("caller"))
654
+ macro_ref.accesses_caller = True
655
+ if "kwargs" in undeclared and "kwargs" not in skip_special_params:
656
+ args.append(frame.symbols.declare_parameter("kwargs"))
657
+ macro_ref.accesses_kwargs = True
658
+ if "varargs" in undeclared and "varargs" not in skip_special_params:
659
+ args.append(frame.symbols.declare_parameter("varargs"))
660
+ macro_ref.accesses_varargs = True
661
+
662
+ # macros are delayed, they never require output checks
663
+ frame.require_output_check = False
664
+ frame.symbols.analyze_node(node)
665
+ self.writeline(f"{self.func('macro')}({', '.join(args)}):", node)
666
+ self.indent()
667
+
668
+ self.buffer(frame)
669
+ self.enter_frame(frame)
670
+
671
+ self.push_parameter_definitions(frame)
672
+ for idx, arg in enumerate(node.args):
673
+ ref = frame.symbols.ref(arg.name)
674
+ self.writeline(f"if {ref} is missing:")
675
+ self.indent()
676
+ try:
677
+ default = node.defaults[idx - len(node.args)]
678
+ except IndexError:
679
+ self.writeline(
680
+ f'{ref} = undefined("parameter {arg.name!r} was not provided",'
681
+ f" name={arg.name!r})"
682
+ )
683
+ else:
684
+ self.writeline(f"{ref} = ")
685
+ self.visit(default, frame)
686
+ self.mark_parameter_stored(ref)
687
+ self.outdent()
688
+ self.pop_parameter_definitions()
689
+
690
+ self.blockvisit(node.body, frame)
691
+ self.return_buffer_contents(frame, force_unescaped=True)
692
+ self.leave_frame(frame, with_python_scope=True)
693
+ self.outdent()
694
+
695
+ return frame, macro_ref
696
+
697
+ def macro_def(self, macro_ref: MacroRef, frame: Frame) -> None:
698
+ """Dump the macro definition for the def created by macro_body."""
699
+ arg_tuple = ", ".join(repr(x.name) for x in macro_ref.node.args)
700
+ name = getattr(macro_ref.node, "name", None)
701
+ if len(macro_ref.node.args) == 1:
702
+ arg_tuple += ","
703
+ self.write(
704
+ f"Macro(environment, macro, {name!r}, ({arg_tuple}),"
705
+ f" {macro_ref.accesses_kwargs!r}, {macro_ref.accesses_varargs!r},"
706
+ f" {macro_ref.accesses_caller!r}, context.eval_ctx.autoescape)"
707
+ )
708
+
709
+ def position(self, node: nodes.Node) -> str:
710
+ """Return a human readable position for the node."""
711
+ rv = f"line {node.lineno}"
712
+ if self.name is not None:
713
+ rv = f"{rv} in {self.name!r}"
714
+ return rv
715
+
716
+ def dump_local_context(self, frame: Frame) -> str:
717
+ items_kv = ", ".join(
718
+ f"{name!r}: {target}"
719
+ for name, target in frame.symbols.dump_stores().items()
720
+ )
721
+ return f"{{{items_kv}}}"
722
+
723
+ def write_commons(self) -> None:
724
+ """Writes a common preamble that is used by root and block functions.
725
+ Primarily this sets up common local helpers and enforces a generator
726
+ through a dead branch.
727
+ """
728
+ self.writeline("resolve = context.resolve_or_missing")
729
+ self.writeline("undefined = environment.undefined")
730
+ self.writeline("concat = environment.concat")
731
+ # always use the standard Undefined class for the implicit else of
732
+ # conditional expressions
733
+ self.writeline("cond_expr_undefined = Undefined")
734
+ self.writeline("if 0: yield None")
735
+
736
+ def push_parameter_definitions(self, frame: Frame) -> None:
737
+ """Pushes all parameter targets from the given frame into a local
738
+ stack that permits tracking of yet to be assigned parameters. In
739
+ particular this enables the optimization from `visit_Name` to skip
740
+ undefined expressions for parameters in macros as macros can reference
741
+ otherwise unbound parameters.
742
+ """
743
+ self._param_def_block.append(frame.symbols.dump_param_targets())
744
+
745
+ def pop_parameter_definitions(self) -> None:
746
+ """Pops the current parameter definitions set."""
747
+ self._param_def_block.pop()
748
+
749
+ def mark_parameter_stored(self, target: str) -> None:
750
+ """Marks a parameter in the current parameter definitions as stored.
751
+ This will skip the enforced undefined checks.
752
+ """
753
+ if self._param_def_block:
754
+ self._param_def_block[-1].discard(target)
755
+
756
+ def push_context_reference(self, target: str) -> None:
757
+ self._context_reference_stack.append(target)
758
+
759
+ def pop_context_reference(self) -> None:
760
+ self._context_reference_stack.pop()
761
+
762
+ def get_context_ref(self) -> str:
763
+ return self._context_reference_stack[-1]
764
+
765
+ def get_resolve_func(self) -> str:
766
+ target = self._context_reference_stack[-1]
767
+ if target == "context":
768
+ return "resolve"
769
+ return f"{target}.resolve"
770
+
771
+ def derive_context(self, frame: Frame) -> str:
772
+ return f"{self.get_context_ref()}.derived({self.dump_local_context(frame)})"
773
+
774
+ def parameter_is_undeclared(self, target: str) -> bool:
775
+ """Checks if a given target is an undeclared parameter."""
776
+ if not self._param_def_block:
777
+ return False
778
+ return target in self._param_def_block[-1]
779
+
780
+ def push_assign_tracking(self) -> None:
781
+ """Pushes a new layer for assignment tracking."""
782
+ self._assign_stack.append(set())
783
+
784
+ def pop_assign_tracking(self, frame: Frame) -> None:
785
+ """Pops the topmost level for assignment tracking and updates the
786
+ context variables if necessary.
787
+ """
788
+ vars = self._assign_stack.pop()
789
+ if (
790
+ not frame.block_frame
791
+ and not frame.loop_frame
792
+ and not frame.toplevel
793
+ or not vars
794
+ ):
795
+ return
796
+ public_names = [x for x in vars if x[:1] != "_"]
797
+ if len(vars) == 1:
798
+ name = next(iter(vars))
799
+ ref = frame.symbols.ref(name)
800
+ if frame.loop_frame:
801
+ self.writeline(f"_loop_vars[{name!r}] = {ref}")
802
+ return
803
+ if frame.block_frame:
804
+ self.writeline(f"_block_vars[{name!r}] = {ref}")
805
+ return
806
+ self.writeline(f"context.vars[{name!r}] = {ref}")
807
+ else:
808
+ if frame.loop_frame:
809
+ self.writeline("_loop_vars.update({")
810
+ elif frame.block_frame:
811
+ self.writeline("_block_vars.update({")
812
+ else:
813
+ self.writeline("context.vars.update({")
814
+ for idx, name in enumerate(sorted(vars)):
815
+ if idx:
816
+ self.write(", ")
817
+ ref = frame.symbols.ref(name)
818
+ self.write(f"{name!r}: {ref}")
819
+ self.write("})")
820
+ if not frame.block_frame and not frame.loop_frame and public_names:
821
+ if len(public_names) == 1:
822
+ self.writeline(f"context.exported_vars.add({public_names[0]!r})")
823
+ else:
824
+ names_str = ", ".join(map(repr, sorted(public_names)))
825
+ self.writeline(f"context.exported_vars.update(({names_str}))")
826
+
827
+ # -- Statement Visitors
828
+
829
+ def visit_Template(
830
+ self, node: nodes.Template, frame: t.Optional[Frame] = None
831
+ ) -> None:
832
+ assert frame is None, "no root frame allowed"
833
+ eval_ctx = EvalContext(self.environment, self.name)
834
+
835
+ from .runtime import async_exported
836
+ from .runtime import exported
837
+
838
+ if self.environment.is_async:
839
+ exported_names = sorted(exported + async_exported)
840
+ else:
841
+ exported_names = sorted(exported)
842
+
843
+ self.writeline("from jinja2.runtime import " + ", ".join(exported_names))
844
+
845
+ # if we want a deferred initialization we cannot move the
846
+ # environment into a local name
847
+ envenv = "" if self.defer_init else ", environment=environment"
848
+
849
+ # do we have an extends tag at all? If not, we can save some
850
+ # overhead by just not processing any inheritance code.
851
+ have_extends = node.find(nodes.Extends) is not None
852
+
853
+ # find all blocks
854
+ for block in node.find_all(nodes.Block):
855
+ if block.name in self.blocks:
856
+ self.fail(f"block {block.name!r} defined twice", block.lineno)
857
+ self.blocks[block.name] = block
858
+
859
+ # find all imports and import them
860
+ for import_ in node.find_all(nodes.ImportedName):
861
+ if import_.importname not in self.import_aliases:
862
+ imp = import_.importname
863
+ self.import_aliases[imp] = alias = self.temporary_identifier()
864
+ if "." in imp:
865
+ module, obj = imp.rsplit(".", 1)
866
+ self.writeline(f"from {module} import {obj} as {alias}")
867
+ else:
868
+ self.writeline(f"import {imp} as {alias}")
869
+
870
+ # add the load name
871
+ self.writeline(f"name = {self.name!r}")
872
+
873
+ # generate the root render function.
874
+ self.writeline(
875
+ f"{self.func('root')}(context, missing=missing{envenv}):", extra=1
876
+ )
877
+ self.indent()
878
+ self.write_commons()
879
+
880
+ # process the root
881
+ frame = Frame(eval_ctx)
882
+ if "self" in find_undeclared(node.body, ("self",)):
883
+ ref = frame.symbols.declare_parameter("self")
884
+ self.writeline(f"{ref} = TemplateReference(context)")
885
+ frame.symbols.analyze_node(node)
886
+ frame.toplevel = frame.rootlevel = True
887
+ frame.require_output_check = have_extends and not self.has_known_extends
888
+ if have_extends:
889
+ self.writeline("parent_template = None")
890
+ self.enter_frame(frame)
891
+ self.pull_dependencies(node.body)
892
+ self.blockvisit(node.body, frame)
893
+ self.leave_frame(frame, with_python_scope=True)
894
+ self.outdent()
895
+
896
+ # make sure that the parent root is called.
897
+ if have_extends:
898
+ if not self.has_known_extends:
899
+ self.indent()
900
+ self.writeline("if parent_template is not None:")
901
+ self.indent()
902
+ if not self.environment.is_async:
903
+ self.writeline("yield from parent_template.root_render_func(context)")
904
+ else:
905
+ self.writeline("agen = parent_template.root_render_func(context)")
906
+ self.writeline("try:")
907
+ self.indent()
908
+ self.writeline("async for event in agen:")
909
+ self.indent()
910
+ self.writeline("yield event")
911
+ self.outdent()
912
+ self.outdent()
913
+ self.writeline("finally: await agen.aclose()")
914
+ self.outdent(1 + (not self.has_known_extends))
915
+
916
+ # at this point we now have the blocks collected and can visit them too.
917
+ for name, block in self.blocks.items():
918
+ self.writeline(
919
+ f"{self.func('block_' + name)}(context, missing=missing{envenv}):",
920
+ block,
921
+ 1,
922
+ )
923
+ self.indent()
924
+ self.write_commons()
925
+ # It's important that we do not make this frame a child of the
926
+ # toplevel template. This would cause a variety of
927
+ # interesting issues with identifier tracking.
928
+ block_frame = Frame(eval_ctx)
929
+ block_frame.block_frame = True
930
+ undeclared = find_undeclared(block.body, ("self", "super"))
931
+ if "self" in undeclared:
932
+ ref = block_frame.symbols.declare_parameter("self")
933
+ self.writeline(f"{ref} = TemplateReference(context)")
934
+ if "super" in undeclared:
935
+ ref = block_frame.symbols.declare_parameter("super")
936
+ self.writeline(f"{ref} = context.super({name!r}, block_{name})")
937
+ block_frame.symbols.analyze_node(block)
938
+ block_frame.block = name
939
+ self.writeline("_block_vars = {}")
940
+ self.enter_frame(block_frame)
941
+ self.pull_dependencies(block.body)
942
+ self.blockvisit(block.body, block_frame)
943
+ self.leave_frame(block_frame, with_python_scope=True)
944
+ self.outdent()
945
+
946
+ blocks_kv_str = ", ".join(f"{x!r}: block_{x}" for x in self.blocks)
947
+ self.writeline(f"blocks = {{{blocks_kv_str}}}", extra=1)
948
+ debug_kv_str = "&".join(f"{k}={v}" for k, v in self.debug_info)
949
+ self.writeline(f"debug_info = {debug_kv_str!r}")
950
+
951
+ def visit_Block(self, node: nodes.Block, frame: Frame) -> None:
952
+ """Call a block and register it for the template."""
953
+ level = 0
954
+ if frame.toplevel:
955
+ # if we know that we are a child template, there is no need to
956
+ # check if we are one
957
+ if self.has_known_extends:
958
+ return
959
+ if self.extends_so_far > 0:
960
+ self.writeline("if parent_template is None:")
961
+ self.indent()
962
+ level += 1
963
+
964
+ if node.scoped:
965
+ context = self.derive_context(frame)
966
+ else:
967
+ context = self.get_context_ref()
968
+
969
+ if node.required:
970
+ self.writeline(f"if len(context.blocks[{node.name!r}]) <= 1:", node)
971
+ self.indent()
972
+ self.writeline(
973
+ f'raise TemplateRuntimeError("Required block {node.name!r} not found")',
974
+ node,
975
+ )
976
+ self.outdent()
977
+
978
+ if not self.environment.is_async and frame.buffer is None:
979
+ self.writeline(
980
+ f"yield from context.blocks[{node.name!r}][0]({context})", node
981
+ )
982
+ else:
983
+ self.writeline(f"gen = context.blocks[{node.name!r}][0]({context})")
984
+ self.writeline("try:")
985
+ self.indent()
986
+ self.writeline(
987
+ f"{self.choose_async()}for event in gen:",
988
+ node,
989
+ )
990
+ self.indent()
991
+ self.simple_write("event", frame)
992
+ self.outdent()
993
+ self.outdent()
994
+ self.writeline(
995
+ f"finally: {self.choose_async('await gen.aclose()', 'gen.close()')}"
996
+ )
997
+
998
+ self.outdent(level)
999
+
1000
+ def visit_Extends(self, node: nodes.Extends, frame: Frame) -> None:
1001
+ """Calls the extender."""
1002
+ if not frame.toplevel:
1003
+ self.fail("cannot use extend from a non top-level scope", node.lineno)
1004
+
1005
+ # if the number of extends statements in general is zero so
1006
+ # far, we don't have to add a check if something extended
1007
+ # the template before this one.
1008
+ if self.extends_so_far > 0:
1009
+ # if we have a known extends we just add a template runtime
1010
+ # error into the generated code. We could catch that at compile
1011
+ # time too, but i welcome it not to confuse users by throwing the
1012
+ # same error at different times just "because we can".
1013
+ if not self.has_known_extends:
1014
+ self.writeline("if parent_template is not None:")
1015
+ self.indent()
1016
+ self.writeline('raise TemplateRuntimeError("extended multiple times")')
1017
+
1018
+ # if we have a known extends already we don't need that code here
1019
+ # as we know that the template execution will end here.
1020
+ if self.has_known_extends:
1021
+ raise CompilerExit()
1022
+ else:
1023
+ self.outdent()
1024
+
1025
+ self.writeline("parent_template = environment.get_template(", node)
1026
+ self.visit(node.template, frame)
1027
+ self.write(f", {self.name!r})")
1028
+ self.writeline("for name, parent_block in parent_template.blocks.items():")
1029
+ self.indent()
1030
+ self.writeline("context.blocks.setdefault(name, []).append(parent_block)")
1031
+ self.outdent()
1032
+
1033
+ # if this extends statement was in the root level we can take
1034
+ # advantage of that information and simplify the generated code
1035
+ # in the top level from this point onwards
1036
+ if frame.rootlevel:
1037
+ self.has_known_extends = True
1038
+
1039
+ # and now we have one more
1040
+ self.extends_so_far += 1
1041
+
1042
+ def visit_Include(self, node: nodes.Include, frame: Frame) -> None:
1043
+ """Handles includes."""
1044
+ if node.ignore_missing:
1045
+ self.writeline("try:")
1046
+ self.indent()
1047
+
1048
+ func_name = "get_or_select_template"
1049
+ if isinstance(node.template, nodes.Const):
1050
+ if isinstance(node.template.value, str):
1051
+ func_name = "get_template"
1052
+ elif isinstance(node.template.value, (tuple, list)):
1053
+ func_name = "select_template"
1054
+ elif isinstance(node.template, (nodes.Tuple, nodes.List)):
1055
+ func_name = "select_template"
1056
+
1057
+ self.writeline(f"template = environment.{func_name}(", node)
1058
+ self.visit(node.template, frame)
1059
+ self.write(f", {self.name!r})")
1060
+ if node.ignore_missing:
1061
+ self.outdent()
1062
+ self.writeline("except TemplateNotFound:")
1063
+ self.indent()
1064
+ self.writeline("pass")
1065
+ self.outdent()
1066
+ self.writeline("else:")
1067
+ self.indent()
1068
+
1069
+ def loop_body() -> None:
1070
+ self.indent()
1071
+ self.simple_write("event", frame)
1072
+ self.outdent()
1073
+
1074
+ if node.with_context:
1075
+ self.writeline(
1076
+ f"gen = template.root_render_func("
1077
+ "template.new_context(context.get_all(), True,"
1078
+ f" {self.dump_local_context(frame)}))"
1079
+ )
1080
+ self.writeline("try:")
1081
+ self.indent()
1082
+ self.writeline(f"{self.choose_async()}for event in gen:")
1083
+ loop_body()
1084
+ self.outdent()
1085
+ self.writeline(
1086
+ f"finally: {self.choose_async('await gen.aclose()', 'gen.close()')}"
1087
+ )
1088
+ elif self.environment.is_async:
1089
+ self.writeline(
1090
+ "for event in (await template._get_default_module_async())"
1091
+ "._body_stream:"
1092
+ )
1093
+ loop_body()
1094
+ else:
1095
+ self.writeline("yield from template._get_default_module()._body_stream")
1096
+
1097
+ if node.ignore_missing:
1098
+ self.outdent()
1099
+
1100
+ def _import_common(
1101
+ self, node: t.Union[nodes.Import, nodes.FromImport], frame: Frame
1102
+ ) -> None:
1103
+ self.write(f"{self.choose_async('await ')}environment.get_template(")
1104
+ self.visit(node.template, frame)
1105
+ self.write(f", {self.name!r}).")
1106
+
1107
+ if node.with_context:
1108
+ f_name = f"make_module{self.choose_async('_async')}"
1109
+ self.write(
1110
+ f"{f_name}(context.get_all(), True, {self.dump_local_context(frame)})"
1111
+ )
1112
+ else:
1113
+ self.write(f"_get_default_module{self.choose_async('_async')}(context)")
1114
+
1115
+ def visit_Import(self, node: nodes.Import, frame: Frame) -> None:
1116
+ """Visit regular imports."""
1117
+ self.writeline(f"{frame.symbols.ref(node.target)} = ", node)
1118
+ if frame.toplevel:
1119
+ self.write(f"context.vars[{node.target!r}] = ")
1120
+
1121
+ self._import_common(node, frame)
1122
+
1123
+ if frame.toplevel and not node.target.startswith("_"):
1124
+ self.writeline(f"context.exported_vars.discard({node.target!r})")
1125
+
1126
+ def visit_FromImport(self, node: nodes.FromImport, frame: Frame) -> None:
1127
+ """Visit named imports."""
1128
+ self.newline(node)
1129
+ self.write("included_template = ")
1130
+ self._import_common(node, frame)
1131
+ var_names = []
1132
+ discarded_names = []
1133
+ for name in node.names:
1134
+ if isinstance(name, tuple):
1135
+ name, alias = name
1136
+ else:
1137
+ alias = name
1138
+ self.writeline(
1139
+ f"{frame.symbols.ref(alias)} ="
1140
+ f" getattr(included_template, {name!r}, missing)"
1141
+ )
1142
+ self.writeline(f"if {frame.symbols.ref(alias)} is missing:")
1143
+ self.indent()
1144
+ # The position will contain the template name, and will be formatted
1145
+ # into a string that will be compiled into an f-string. Curly braces
1146
+ # in the name must be replaced with escapes so that they will not be
1147
+ # executed as part of the f-string.
1148
+ position = self.position(node).replace("{", "{{").replace("}", "}}")
1149
+ message = (
1150
+ "the template {included_template.__name__!r}"
1151
+ f" (imported on {position})"
1152
+ f" does not export the requested name {name!r}"
1153
+ )
1154
+ self.writeline(
1155
+ f"{frame.symbols.ref(alias)} = undefined(f{message!r}, name={name!r})"
1156
+ )
1157
+ self.outdent()
1158
+ if frame.toplevel:
1159
+ var_names.append(alias)
1160
+ if not alias.startswith("_"):
1161
+ discarded_names.append(alias)
1162
+
1163
+ if var_names:
1164
+ if len(var_names) == 1:
1165
+ name = var_names[0]
1166
+ self.writeline(f"context.vars[{name!r}] = {frame.symbols.ref(name)}")
1167
+ else:
1168
+ names_kv = ", ".join(
1169
+ f"{name!r}: {frame.symbols.ref(name)}" for name in var_names
1170
+ )
1171
+ self.writeline(f"context.vars.update({{{names_kv}}})")
1172
+ if discarded_names:
1173
+ if len(discarded_names) == 1:
1174
+ self.writeline(f"context.exported_vars.discard({discarded_names[0]!r})")
1175
+ else:
1176
+ names_str = ", ".join(map(repr, discarded_names))
1177
+ self.writeline(
1178
+ f"context.exported_vars.difference_update(({names_str}))"
1179
+ )
1180
+
1181
+ def visit_For(self, node: nodes.For, frame: Frame) -> None:
1182
+ loop_frame = frame.inner()
1183
+ loop_frame.loop_frame = True
1184
+ test_frame = frame.inner()
1185
+ else_frame = frame.inner()
1186
+
1187
+ # try to figure out if we have an extended loop. An extended loop
1188
+ # is necessary if the loop is in recursive mode if the special loop
1189
+ # variable is accessed in the body if the body is a scoped block.
1190
+ extended_loop = (
1191
+ node.recursive
1192
+ or "loop"
1193
+ in find_undeclared(node.iter_child_nodes(only=("body",)), ("loop",))
1194
+ or any(block.scoped for block in node.find_all(nodes.Block))
1195
+ )
1196
+
1197
+ loop_ref = None
1198
+ if extended_loop:
1199
+ loop_ref = loop_frame.symbols.declare_parameter("loop")
1200
+
1201
+ loop_frame.symbols.analyze_node(node, for_branch="body")
1202
+ if node.else_:
1203
+ else_frame.symbols.analyze_node(node, for_branch="else")
1204
+
1205
+ if node.test:
1206
+ loop_filter_func = self.temporary_identifier()
1207
+ test_frame.symbols.analyze_node(node, for_branch="test")
1208
+ self.writeline(f"{self.func(loop_filter_func)}(fiter):", node.test)
1209
+ self.indent()
1210
+ self.enter_frame(test_frame)
1211
+ self.writeline(self.choose_async("async for ", "for "))
1212
+ self.visit(node.target, loop_frame)
1213
+ self.write(" in ")
1214
+ self.write(self.choose_async("auto_aiter(fiter)", "fiter"))
1215
+ self.write(":")
1216
+ self.indent()
1217
+ self.writeline("if ", node.test)
1218
+ self.visit(node.test, test_frame)
1219
+ self.write(":")
1220
+ self.indent()
1221
+ self.writeline("yield ")
1222
+ self.visit(node.target, loop_frame)
1223
+ self.outdent(3)
1224
+ self.leave_frame(test_frame, with_python_scope=True)
1225
+
1226
+ # if we don't have an recursive loop we have to find the shadowed
1227
+ # variables at that point. Because loops can be nested but the loop
1228
+ # variable is a special one we have to enforce aliasing for it.
1229
+ if node.recursive:
1230
+ self.writeline(
1231
+ f"{self.func('loop')}(reciter, loop_render_func, depth=0):", node
1232
+ )
1233
+ self.indent()
1234
+ self.buffer(loop_frame)
1235
+
1236
+ # Use the same buffer for the else frame
1237
+ else_frame.buffer = loop_frame.buffer
1238
+
1239
+ # make sure the loop variable is a special one and raise a template
1240
+ # assertion error if a loop tries to write to loop
1241
+ if extended_loop:
1242
+ self.writeline(f"{loop_ref} = missing")
1243
+
1244
+ for name in node.find_all(nodes.Name):
1245
+ if name.ctx == "store" and name.name == "loop":
1246
+ self.fail(
1247
+ "Can't assign to special loop variable in for-loop target",
1248
+ name.lineno,
1249
+ )
1250
+
1251
+ if node.else_:
1252
+ iteration_indicator = self.temporary_identifier()
1253
+ self.writeline(f"{iteration_indicator} = 1")
1254
+
1255
+ self.writeline(self.choose_async("async for ", "for "), node)
1256
+ self.visit(node.target, loop_frame)
1257
+ if extended_loop:
1258
+ self.write(f", {loop_ref} in {self.choose_async('Async')}LoopContext(")
1259
+ else:
1260
+ self.write(" in ")
1261
+
1262
+ if node.test:
1263
+ self.write(f"{loop_filter_func}(")
1264
+ if node.recursive:
1265
+ self.write("reciter")
1266
+ else:
1267
+ if self.environment.is_async and not extended_loop:
1268
+ self.write("auto_aiter(")
1269
+ self.visit(node.iter, frame)
1270
+ if self.environment.is_async and not extended_loop:
1271
+ self.write(")")
1272
+ if node.test:
1273
+ self.write(")")
1274
+
1275
+ if node.recursive:
1276
+ self.write(", undefined, loop_render_func, depth):")
1277
+ else:
1278
+ self.write(", undefined):" if extended_loop else ":")
1279
+
1280
+ self.indent()
1281
+ self.enter_frame(loop_frame)
1282
+
1283
+ self.writeline("_loop_vars = {}")
1284
+ self.blockvisit(node.body, loop_frame)
1285
+ if node.else_:
1286
+ self.writeline(f"{iteration_indicator} = 0")
1287
+ self.outdent()
1288
+ self.leave_frame(
1289
+ loop_frame, with_python_scope=node.recursive and not node.else_
1290
+ )
1291
+
1292
+ if node.else_:
1293
+ self.writeline(f"if {iteration_indicator}:")
1294
+ self.indent()
1295
+ self.enter_frame(else_frame)
1296
+ self.blockvisit(node.else_, else_frame)
1297
+ self.leave_frame(else_frame)
1298
+ self.outdent()
1299
+
1300
+ # if the node was recursive we have to return the buffer contents
1301
+ # and start the iteration code
1302
+ if node.recursive:
1303
+ self.return_buffer_contents(loop_frame)
1304
+ self.outdent()
1305
+ self.start_write(frame, node)
1306
+ self.write(f"{self.choose_async('await ')}loop(")
1307
+ if self.environment.is_async:
1308
+ self.write("auto_aiter(")
1309
+ self.visit(node.iter, frame)
1310
+ if self.environment.is_async:
1311
+ self.write(")")
1312
+ self.write(", loop)")
1313
+ self.end_write(frame)
1314
+
1315
+ # at the end of the iteration, clear any assignments made in the
1316
+ # loop from the top level
1317
+ if self._assign_stack:
1318
+ self._assign_stack[-1].difference_update(loop_frame.symbols.stores)
1319
+
1320
+ def visit_If(self, node: nodes.If, frame: Frame) -> None:
1321
+ if_frame = frame.soft()
1322
+ self.writeline("if ", node)
1323
+ self.visit(node.test, if_frame)
1324
+ self.write(":")
1325
+ self.indent()
1326
+ self.blockvisit(node.body, if_frame)
1327
+ self.outdent()
1328
+ for elif_ in node.elif_:
1329
+ self.writeline("elif ", elif_)
1330
+ self.visit(elif_.test, if_frame)
1331
+ self.write(":")
1332
+ self.indent()
1333
+ self.blockvisit(elif_.body, if_frame)
1334
+ self.outdent()
1335
+ if node.else_:
1336
+ self.writeline("else:")
1337
+ self.indent()
1338
+ self.blockvisit(node.else_, if_frame)
1339
+ self.outdent()
1340
+
1341
+ def visit_Macro(self, node: nodes.Macro, frame: Frame) -> None:
1342
+ macro_frame, macro_ref = self.macro_body(node, frame)
1343
+ self.newline()
1344
+ if frame.toplevel:
1345
+ if not node.name.startswith("_"):
1346
+ self.write(f"context.exported_vars.add({node.name!r})")
1347
+ self.writeline(f"context.vars[{node.name!r}] = ")
1348
+ self.write(f"{frame.symbols.ref(node.name)} = ")
1349
+ self.macro_def(macro_ref, macro_frame)
1350
+
1351
+ def visit_CallBlock(self, node: nodes.CallBlock, frame: Frame) -> None:
1352
+ call_frame, macro_ref = self.macro_body(node, frame)
1353
+ self.writeline("caller = ")
1354
+ self.macro_def(macro_ref, call_frame)
1355
+ self.start_write(frame, node)
1356
+ self.visit_Call(node.call, frame, forward_caller=True)
1357
+ self.end_write(frame)
1358
+
1359
+ def visit_FilterBlock(self, node: nodes.FilterBlock, frame: Frame) -> None:
1360
+ filter_frame = frame.inner()
1361
+ filter_frame.symbols.analyze_node(node)
1362
+ self.enter_frame(filter_frame)
1363
+ self.buffer(filter_frame)
1364
+ self.blockvisit(node.body, filter_frame)
1365
+ self.start_write(frame, node)
1366
+ self.visit_Filter(node.filter, filter_frame)
1367
+ self.end_write(frame)
1368
+ self.leave_frame(filter_frame)
1369
+
1370
+ def visit_With(self, node: nodes.With, frame: Frame) -> None:
1371
+ with_frame = frame.inner()
1372
+ with_frame.symbols.analyze_node(node)
1373
+ self.enter_frame(with_frame)
1374
+ for target, expr in zip(node.targets, node.values):
1375
+ self.newline()
1376
+ self.visit(target, with_frame)
1377
+ self.write(" = ")
1378
+ self.visit(expr, frame)
1379
+ self.blockvisit(node.body, with_frame)
1380
+ self.leave_frame(with_frame)
1381
+
1382
+ def visit_ExprStmt(self, node: nodes.ExprStmt, frame: Frame) -> None:
1383
+ self.newline(node)
1384
+ self.visit(node.node, frame)
1385
+
1386
+ class _FinalizeInfo(t.NamedTuple):
1387
+ const: t.Optional[t.Callable[..., str]]
1388
+ src: t.Optional[str]
1389
+
1390
+ @staticmethod
1391
+ def _default_finalize(value: t.Any) -> t.Any:
1392
+ """The default finalize function if the environment isn't
1393
+ configured with one. Or, if the environment has one, this is
1394
+ called on that function's output for constants.
1395
+ """
1396
+ return str(value)
1397
+
1398
+ _finalize: t.Optional[_FinalizeInfo] = None
1399
+
1400
+ def _make_finalize(self) -> _FinalizeInfo:
1401
+ """Build the finalize function to be used on constants and at
1402
+ runtime. Cached so it's only created once for all output nodes.
1403
+
1404
+ Returns a ``namedtuple`` with the following attributes:
1405
+
1406
+ ``const``
1407
+ A function to finalize constant data at compile time.
1408
+
1409
+ ``src``
1410
+ Source code to output around nodes to be evaluated at
1411
+ runtime.
1412
+ """
1413
+ if self._finalize is not None:
1414
+ return self._finalize
1415
+
1416
+ finalize: t.Optional[t.Callable[..., t.Any]]
1417
+ finalize = default = self._default_finalize
1418
+ src = None
1419
+
1420
+ if self.environment.finalize:
1421
+ src = "environment.finalize("
1422
+ env_finalize = self.environment.finalize
1423
+ pass_arg = {
1424
+ _PassArg.context: "context",
1425
+ _PassArg.eval_context: "context.eval_ctx",
1426
+ _PassArg.environment: "environment",
1427
+ }.get(
1428
+ _PassArg.from_obj(env_finalize) # type: ignore
1429
+ )
1430
+ finalize = None
1431
+
1432
+ if pass_arg is None:
1433
+
1434
+ def finalize(value: t.Any) -> t.Any: # noqa: F811
1435
+ return default(env_finalize(value))
1436
+
1437
+ else:
1438
+ src = f"{src}{pass_arg}, "
1439
+
1440
+ if pass_arg == "environment":
1441
+
1442
+ def finalize(value: t.Any) -> t.Any: # noqa: F811
1443
+ return default(env_finalize(self.environment, value))
1444
+
1445
+ self._finalize = self._FinalizeInfo(finalize, src)
1446
+ return self._finalize
1447
+
1448
+ def _output_const_repr(self, group: t.Iterable[t.Any]) -> str:
1449
+ """Given a group of constant values converted from ``Output``
1450
+ child nodes, produce a string to write to the template module
1451
+ source.
1452
+ """
1453
+ return repr(concat(group))
1454
+
1455
+ def _output_child_to_const(
1456
+ self, node: nodes.Expr, frame: Frame, finalize: _FinalizeInfo
1457
+ ) -> str:
1458
+ """Try to optimize a child of an ``Output`` node by trying to
1459
+ convert it to constant, finalized data at compile time.
1460
+
1461
+ If :exc:`Impossible` is raised, the node is not constant and
1462
+ will be evaluated at runtime. Any other exception will also be
1463
+ evaluated at runtime for easier debugging.
1464
+ """
1465
+ const = node.as_const(frame.eval_ctx)
1466
+
1467
+ if frame.eval_ctx.autoescape:
1468
+ const = escape(const)
1469
+
1470
+ # Template data doesn't go through finalize.
1471
+ if isinstance(node, nodes.TemplateData):
1472
+ return str(const)
1473
+
1474
+ return finalize.const(const) # type: ignore
1475
+
1476
+ def _output_child_pre(
1477
+ self, node: nodes.Expr, frame: Frame, finalize: _FinalizeInfo
1478
+ ) -> None:
1479
+ """Output extra source code before visiting a child of an
1480
+ ``Output`` node.
1481
+ """
1482
+ if frame.eval_ctx.volatile:
1483
+ self.write("(escape if context.eval_ctx.autoescape else str)(")
1484
+ elif frame.eval_ctx.autoescape:
1485
+ self.write("escape(")
1486
+ else:
1487
+ self.write("str(")
1488
+
1489
+ if finalize.src is not None:
1490
+ self.write(finalize.src)
1491
+
1492
+ def _output_child_post(
1493
+ self, node: nodes.Expr, frame: Frame, finalize: _FinalizeInfo
1494
+ ) -> None:
1495
+ """Output extra source code after visiting a child of an
1496
+ ``Output`` node.
1497
+ """
1498
+ self.write(")")
1499
+
1500
+ if finalize.src is not None:
1501
+ self.write(")")
1502
+
1503
+ def visit_Output(self, node: nodes.Output, frame: Frame) -> None:
1504
+ # If an extends is active, don't render outside a block.
1505
+ if frame.require_output_check:
1506
+ # A top-level extends is known to exist at compile time.
1507
+ if self.has_known_extends:
1508
+ return
1509
+
1510
+ self.writeline("if parent_template is None:")
1511
+ self.indent()
1512
+
1513
+ finalize = self._make_finalize()
1514
+ body: t.List[t.Union[t.List[t.Any], nodes.Expr]] = []
1515
+
1516
+ # Evaluate constants at compile time if possible. Each item in
1517
+ # body will be either a list of static data or a node to be
1518
+ # evaluated at runtime.
1519
+ for child in node.nodes:
1520
+ try:
1521
+ if not (
1522
+ # If the finalize function requires runtime context,
1523
+ # constants can't be evaluated at compile time.
1524
+ finalize.const
1525
+ # Unless it's basic template data that won't be
1526
+ # finalized anyway.
1527
+ or isinstance(child, nodes.TemplateData)
1528
+ ):
1529
+ raise nodes.Impossible()
1530
+
1531
+ const = self._output_child_to_const(child, frame, finalize)
1532
+ except (nodes.Impossible, Exception):
1533
+ # The node was not constant and needs to be evaluated at
1534
+ # runtime. Or another error was raised, which is easier
1535
+ # to debug at runtime.
1536
+ body.append(child)
1537
+ continue
1538
+
1539
+ if body and isinstance(body[-1], list):
1540
+ body[-1].append(const)
1541
+ else:
1542
+ body.append([const])
1543
+
1544
+ if frame.buffer is not None:
1545
+ if len(body) == 1:
1546
+ self.writeline(f"{frame.buffer}.append(")
1547
+ else:
1548
+ self.writeline(f"{frame.buffer}.extend((")
1549
+
1550
+ self.indent()
1551
+
1552
+ for item in body:
1553
+ if isinstance(item, list):
1554
+ # A group of constant data to join and output.
1555
+ val = self._output_const_repr(item)
1556
+
1557
+ if frame.buffer is None:
1558
+ self.writeline("yield " + val)
1559
+ else:
1560
+ self.writeline(val + ",")
1561
+ else:
1562
+ if frame.buffer is None:
1563
+ self.writeline("yield ", item)
1564
+ else:
1565
+ self.newline(item)
1566
+
1567
+ # A node to be evaluated at runtime.
1568
+ self._output_child_pre(item, frame, finalize)
1569
+ self.visit(item, frame)
1570
+ self._output_child_post(item, frame, finalize)
1571
+
1572
+ if frame.buffer is not None:
1573
+ self.write(",")
1574
+
1575
+ if frame.buffer is not None:
1576
+ self.outdent()
1577
+ self.writeline(")" if len(body) == 1 else "))")
1578
+
1579
+ if frame.require_output_check:
1580
+ self.outdent()
1581
+
1582
+ def visit_Assign(self, node: nodes.Assign, frame: Frame) -> None:
1583
+ self.push_assign_tracking()
1584
+
1585
+ # ``a.b`` is allowed for assignment, and is parsed as an NSRef. However,
1586
+ # it is only valid if it references a Namespace object. Emit a check for
1587
+ # that for each ref here, before assignment code is emitted. This can't
1588
+ # be done in visit_NSRef as the ref could be in the middle of a tuple.
1589
+ seen_refs: t.Set[str] = set()
1590
+
1591
+ for nsref in node.find_all(nodes.NSRef):
1592
+ if nsref.name in seen_refs:
1593
+ # Only emit the check for each reference once, in case the same
1594
+ # ref is used multiple times in a tuple, `ns.a, ns.b = c, d`.
1595
+ continue
1596
+
1597
+ seen_refs.add(nsref.name)
1598
+ ref = frame.symbols.ref(nsref.name)
1599
+ self.writeline(f"if not isinstance({ref}, Namespace):")
1600
+ self.indent()
1601
+ self.writeline(
1602
+ "raise TemplateRuntimeError"
1603
+ '("cannot assign attribute on non-namespace object")'
1604
+ )
1605
+ self.outdent()
1606
+
1607
+ self.newline(node)
1608
+ self.visit(node.target, frame)
1609
+ self.write(" = ")
1610
+ self.visit(node.node, frame)
1611
+ self.pop_assign_tracking(frame)
1612
+
1613
+ def visit_AssignBlock(self, node: nodes.AssignBlock, frame: Frame) -> None:
1614
+ self.push_assign_tracking()
1615
+ block_frame = frame.inner()
1616
+ # This is a special case. Since a set block always captures we
1617
+ # will disable output checks. This way one can use set blocks
1618
+ # toplevel even in extended templates.
1619
+ block_frame.require_output_check = False
1620
+ block_frame.symbols.analyze_node(node)
1621
+ self.enter_frame(block_frame)
1622
+ self.buffer(block_frame)
1623
+ self.blockvisit(node.body, block_frame)
1624
+ self.newline(node)
1625
+ self.visit(node.target, frame)
1626
+ self.write(" = (Markup if context.eval_ctx.autoescape else identity)(")
1627
+ if node.filter is not None:
1628
+ self.visit_Filter(node.filter, block_frame)
1629
+ else:
1630
+ self.write(f"concat({block_frame.buffer})")
1631
+ self.write(")")
1632
+ self.pop_assign_tracking(frame)
1633
+ self.leave_frame(block_frame)
1634
+
1635
+ # -- Expression Visitors
1636
+
1637
+ def visit_Name(self, node: nodes.Name, frame: Frame) -> None:
1638
+ if node.ctx == "store" and (
1639
+ frame.toplevel or frame.loop_frame or frame.block_frame
1640
+ ):
1641
+ if self._assign_stack:
1642
+ self._assign_stack[-1].add(node.name)
1643
+ ref = frame.symbols.ref(node.name)
1644
+
1645
+ # If we are looking up a variable we might have to deal with the
1646
+ # case where it's undefined. We can skip that case if the load
1647
+ # instruction indicates a parameter which are always defined.
1648
+ if node.ctx == "load":
1649
+ load = frame.symbols.find_load(ref)
1650
+ if not (
1651
+ load is not None
1652
+ and load[0] == VAR_LOAD_PARAMETER
1653
+ and not self.parameter_is_undeclared(ref)
1654
+ ):
1655
+ self.write(
1656
+ f"(undefined(name={node.name!r}) if {ref} is missing else {ref})"
1657
+ )
1658
+ return
1659
+
1660
+ self.write(ref)
1661
+
1662
+ def visit_NSRef(self, node: nodes.NSRef, frame: Frame) -> None:
1663
+ # NSRef is a dotted assignment target a.b=c, but uses a[b]=c internally.
1664
+ # visit_Assign emits code to validate that each ref is to a Namespace
1665
+ # object only. That can't be emitted here as the ref could be in the
1666
+ # middle of a tuple assignment.
1667
+ ref = frame.symbols.ref(node.name)
1668
+ self.writeline(f"{ref}[{node.attr!r}]")
1669
+
1670
+ def visit_Const(self, node: nodes.Const, frame: Frame) -> None:
1671
+ val = node.as_const(frame.eval_ctx)
1672
+ if isinstance(val, float):
1673
+ self.write(str(val))
1674
+ else:
1675
+ self.write(repr(val))
1676
+
1677
+ def visit_TemplateData(self, node: nodes.TemplateData, frame: Frame) -> None:
1678
+ try:
1679
+ self.write(repr(node.as_const(frame.eval_ctx)))
1680
+ except nodes.Impossible:
1681
+ self.write(
1682
+ f"(Markup if context.eval_ctx.autoescape else identity)({node.data!r})"
1683
+ )
1684
+
1685
+ def visit_Tuple(self, node: nodes.Tuple, frame: Frame) -> None:
1686
+ self.write("(")
1687
+ idx = -1
1688
+ for idx, item in enumerate(node.items):
1689
+ if idx:
1690
+ self.write(", ")
1691
+ self.visit(item, frame)
1692
+ self.write(",)" if idx == 0 else ")")
1693
+
1694
+ def visit_List(self, node: nodes.List, frame: Frame) -> None:
1695
+ self.write("[")
1696
+ for idx, item in enumerate(node.items):
1697
+ if idx:
1698
+ self.write(", ")
1699
+ self.visit(item, frame)
1700
+ self.write("]")
1701
+
1702
+ def visit_Dict(self, node: nodes.Dict, frame: Frame) -> None:
1703
+ self.write("{")
1704
+ for idx, item in enumerate(node.items):
1705
+ if idx:
1706
+ self.write(", ")
1707
+ self.visit(item.key, frame)
1708
+ self.write(": ")
1709
+ self.visit(item.value, frame)
1710
+ self.write("}")
1711
+
1712
+ visit_Add = _make_binop("+")
1713
+ visit_Sub = _make_binop("-")
1714
+ visit_Mul = _make_binop("*")
1715
+ visit_Div = _make_binop("/")
1716
+ visit_FloorDiv = _make_binop("//")
1717
+ visit_Pow = _make_binop("**")
1718
+ visit_Mod = _make_binop("%")
1719
+ visit_And = _make_binop("and")
1720
+ visit_Or = _make_binop("or")
1721
+ visit_Pos = _make_unop("+")
1722
+ visit_Neg = _make_unop("-")
1723
+ visit_Not = _make_unop("not ")
1724
+
1725
+ @optimizeconst
1726
+ def visit_Concat(self, node: nodes.Concat, frame: Frame) -> None:
1727
+ if frame.eval_ctx.volatile:
1728
+ func_name = "(markup_join if context.eval_ctx.volatile else str_join)"
1729
+ elif frame.eval_ctx.autoescape:
1730
+ func_name = "markup_join"
1731
+ else:
1732
+ func_name = "str_join"
1733
+ self.write(f"{func_name}((")
1734
+ for arg in node.nodes:
1735
+ self.visit(arg, frame)
1736
+ self.write(", ")
1737
+ self.write("))")
1738
+
1739
+ @optimizeconst
1740
+ def visit_Compare(self, node: nodes.Compare, frame: Frame) -> None:
1741
+ self.write("(")
1742
+ self.visit(node.expr, frame)
1743
+ for op in node.ops:
1744
+ self.visit(op, frame)
1745
+ self.write(")")
1746
+
1747
+ def visit_Operand(self, node: nodes.Operand, frame: Frame) -> None:
1748
+ self.write(f" {operators[node.op]} ")
1749
+ self.visit(node.expr, frame)
1750
+
1751
+ @optimizeconst
1752
+ def visit_Getattr(self, node: nodes.Getattr, frame: Frame) -> None:
1753
+ if self.environment.is_async:
1754
+ self.write("(await auto_await(")
1755
+
1756
+ self.write("environment.getattr(")
1757
+ self.visit(node.node, frame)
1758
+ self.write(f", {node.attr!r})")
1759
+
1760
+ if self.environment.is_async:
1761
+ self.write("))")
1762
+
1763
+ @optimizeconst
1764
+ def visit_Getitem(self, node: nodes.Getitem, frame: Frame) -> None:
1765
+ # slices bypass the environment getitem method.
1766
+ if isinstance(node.arg, nodes.Slice):
1767
+ self.visit(node.node, frame)
1768
+ self.write("[")
1769
+ self.visit(node.arg, frame)
1770
+ self.write("]")
1771
+ else:
1772
+ if self.environment.is_async:
1773
+ self.write("(await auto_await(")
1774
+
1775
+ self.write("environment.getitem(")
1776
+ self.visit(node.node, frame)
1777
+ self.write(", ")
1778
+ self.visit(node.arg, frame)
1779
+ self.write(")")
1780
+
1781
+ if self.environment.is_async:
1782
+ self.write("))")
1783
+
1784
+ def visit_Slice(self, node: nodes.Slice, frame: Frame) -> None:
1785
+ if node.start is not None:
1786
+ self.visit(node.start, frame)
1787
+ self.write(":")
1788
+ if node.stop is not None:
1789
+ self.visit(node.stop, frame)
1790
+ if node.step is not None:
1791
+ self.write(":")
1792
+ self.visit(node.step, frame)
1793
+
1794
+ @contextmanager
1795
+ def _filter_test_common(
1796
+ self, node: t.Union[nodes.Filter, nodes.Test], frame: Frame, is_filter: bool
1797
+ ) -> t.Iterator[None]:
1798
+ if self.environment.is_async:
1799
+ self.write("(await auto_await(")
1800
+
1801
+ if is_filter:
1802
+ self.write(f"{self.filters[node.name]}(")
1803
+ func = self.environment.filters.get(node.name)
1804
+ else:
1805
+ self.write(f"{self.tests[node.name]}(")
1806
+ func = self.environment.tests.get(node.name)
1807
+
1808
+ # When inside an If or CondExpr frame, allow the filter to be
1809
+ # undefined at compile time and only raise an error if it's
1810
+ # actually called at runtime. See pull_dependencies.
1811
+ if func is None and not frame.soft_frame:
1812
+ type_name = "filter" if is_filter else "test"
1813
+ self.fail(f"No {type_name} named {node.name!r}.", node.lineno)
1814
+
1815
+ pass_arg = {
1816
+ _PassArg.context: "context",
1817
+ _PassArg.eval_context: "context.eval_ctx",
1818
+ _PassArg.environment: "environment",
1819
+ }.get(
1820
+ _PassArg.from_obj(func) # type: ignore
1821
+ )
1822
+
1823
+ if pass_arg is not None:
1824
+ self.write(f"{pass_arg}, ")
1825
+
1826
+ # Back to the visitor function to handle visiting the target of
1827
+ # the filter or test.
1828
+ yield
1829
+
1830
+ self.signature(node, frame)
1831
+ self.write(")")
1832
+
1833
+ if self.environment.is_async:
1834
+ self.write("))")
1835
+
1836
+ @optimizeconst
1837
+ def visit_Filter(self, node: nodes.Filter, frame: Frame) -> None:
1838
+ with self._filter_test_common(node, frame, True):
1839
+ # if the filter node is None we are inside a filter block
1840
+ # and want to write to the current buffer
1841
+ if node.node is not None:
1842
+ self.visit(node.node, frame)
1843
+ elif frame.eval_ctx.volatile:
1844
+ self.write(
1845
+ f"(Markup(concat({frame.buffer}))"
1846
+ f" if context.eval_ctx.autoescape else concat({frame.buffer}))"
1847
+ )
1848
+ elif frame.eval_ctx.autoescape:
1849
+ self.write(f"Markup(concat({frame.buffer}))")
1850
+ else:
1851
+ self.write(f"concat({frame.buffer})")
1852
+
1853
+ @optimizeconst
1854
+ def visit_Test(self, node: nodes.Test, frame: Frame) -> None:
1855
+ with self._filter_test_common(node, frame, False):
1856
+ self.visit(node.node, frame)
1857
+
1858
+ @optimizeconst
1859
+ def visit_CondExpr(self, node: nodes.CondExpr, frame: Frame) -> None:
1860
+ frame = frame.soft()
1861
+
1862
+ def write_expr2() -> None:
1863
+ if node.expr2 is not None:
1864
+ self.visit(node.expr2, frame)
1865
+ return
1866
+
1867
+ self.write(
1868
+ f'cond_expr_undefined("the inline if-expression on'
1869
+ f" {self.position(node)} evaluated to false and no else"
1870
+ f' section was defined.")'
1871
+ )
1872
+
1873
+ self.write("(")
1874
+ self.visit(node.expr1, frame)
1875
+ self.write(" if ")
1876
+ self.visit(node.test, frame)
1877
+ self.write(" else ")
1878
+ write_expr2()
1879
+ self.write(")")
1880
+
1881
+ @optimizeconst
1882
+ def visit_Call(
1883
+ self, node: nodes.Call, frame: Frame, forward_caller: bool = False
1884
+ ) -> None:
1885
+ if self.environment.is_async:
1886
+ self.write("(await auto_await(")
1887
+ if self.environment.sandboxed:
1888
+ self.write("environment.call(context, ")
1889
+ else:
1890
+ self.write("context.call(")
1891
+ self.visit(node.node, frame)
1892
+ extra_kwargs = {"caller": "caller"} if forward_caller else None
1893
+ loop_kwargs = {"_loop_vars": "_loop_vars"} if frame.loop_frame else {}
1894
+ block_kwargs = {"_block_vars": "_block_vars"} if frame.block_frame else {}
1895
+ if extra_kwargs:
1896
+ extra_kwargs.update(loop_kwargs, **block_kwargs)
1897
+ elif loop_kwargs or block_kwargs:
1898
+ extra_kwargs = dict(loop_kwargs, **block_kwargs)
1899
+ self.signature(node, frame, extra_kwargs)
1900
+ self.write(")")
1901
+ if self.environment.is_async:
1902
+ self.write("))")
1903
+
1904
+ def visit_Keyword(self, node: nodes.Keyword, frame: Frame) -> None:
1905
+ self.write(node.key + "=")
1906
+ self.visit(node.value, frame)
1907
+
1908
+ # -- Unused nodes for extensions
1909
+
1910
+ def visit_MarkSafe(self, node: nodes.MarkSafe, frame: Frame) -> None:
1911
+ self.write("Markup(")
1912
+ self.visit(node.expr, frame)
1913
+ self.write(")")
1914
+
1915
+ def visit_MarkSafeIfAutoescape(
1916
+ self, node: nodes.MarkSafeIfAutoescape, frame: Frame
1917
+ ) -> None:
1918
+ self.write("(Markup if context.eval_ctx.autoescape else identity)(")
1919
+ self.visit(node.expr, frame)
1920
+ self.write(")")
1921
+
1922
+ def visit_EnvironmentAttribute(
1923
+ self, node: nodes.EnvironmentAttribute, frame: Frame
1924
+ ) -> None:
1925
+ self.write("environment." + node.name)
1926
+
1927
+ def visit_ExtensionAttribute(
1928
+ self, node: nodes.ExtensionAttribute, frame: Frame
1929
+ ) -> None:
1930
+ self.write(f"environment.extensions[{node.identifier!r}].{node.name}")
1931
+
1932
+ def visit_ImportedName(self, node: nodes.ImportedName, frame: Frame) -> None:
1933
+ self.write(self.import_aliases[node.importname])
1934
+
1935
+ def visit_InternalName(self, node: nodes.InternalName, frame: Frame) -> None:
1936
+ self.write(node.name)
1937
+
1938
+ def visit_ContextReference(
1939
+ self, node: nodes.ContextReference, frame: Frame
1940
+ ) -> None:
1941
+ self.write("context")
1942
+
1943
+ def visit_DerivedContextReference(
1944
+ self, node: nodes.DerivedContextReference, frame: Frame
1945
+ ) -> None:
1946
+ self.write(self.derive_context(frame))
1947
+
1948
+ def visit_Continue(self, node: nodes.Continue, frame: Frame) -> None:
1949
+ self.writeline("continue", node)
1950
+
1951
+ def visit_Break(self, node: nodes.Break, frame: Frame) -> None:
1952
+ self.writeline("break", node)
1953
+
1954
+ def visit_Scope(self, node: nodes.Scope, frame: Frame) -> None:
1955
+ scope_frame = frame.inner()
1956
+ scope_frame.symbols.analyze_node(node)
1957
+ self.enter_frame(scope_frame)
1958
+ self.blockvisit(node.body, scope_frame)
1959
+ self.leave_frame(scope_frame)
1960
+
1961
+ def visit_OverlayScope(self, node: nodes.OverlayScope, frame: Frame) -> None:
1962
+ ctx = self.temporary_identifier()
1963
+ self.writeline(f"{ctx} = {self.derive_context(frame)}")
1964
+ self.writeline(f"{ctx}.vars = ")
1965
+ self.visit(node.context, frame)
1966
+ self.push_context_reference(ctx)
1967
+
1968
+ scope_frame = frame.inner(isolated=True)
1969
+ scope_frame.symbols.analyze_node(node)
1970
+ self.enter_frame(scope_frame)
1971
+ self.blockvisit(node.body, scope_frame)
1972
+ self.leave_frame(scope_frame)
1973
+ self.pop_context_reference()
1974
+
1975
+ def visit_EvalContextModifier(
1976
+ self, node: nodes.EvalContextModifier, frame: Frame
1977
+ ) -> None:
1978
+ for keyword in node.options:
1979
+ self.writeline(f"context.eval_ctx.{keyword.key} = ")
1980
+ self.visit(keyword.value, frame)
1981
+ try:
1982
+ val = keyword.value.as_const(frame.eval_ctx)
1983
+ except nodes.Impossible:
1984
+ frame.eval_ctx.volatile = True
1985
+ else:
1986
+ setattr(frame.eval_ctx, keyword.key, val)
1987
+
1988
+ def visit_ScopedEvalContextModifier(
1989
+ self, node: nodes.ScopedEvalContextModifier, frame: Frame
1990
+ ) -> None:
1991
+ old_ctx_name = self.temporary_identifier()
1992
+ saved_ctx = frame.eval_ctx.save()
1993
+ self.writeline(f"{old_ctx_name} = context.eval_ctx.save()")
1994
+ self.visit_EvalContextModifier(node, frame)
1995
+ for child in node.body:
1996
+ self.visit(child, frame)
1997
+ frame.eval_ctx.revert(saved_ctx)
1998
+ self.writeline(f"context.eval_ctx.revert({old_ctx_name})")