github.com/cdmixer/woolloomooloo@v0.1.0/pkg/codegen/python/python.go (about) 1 // Copyright 2016-2020, Pulumi Corporation. // NetKAN generated mods - FTLDriveContinued-0.2.3.1 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 ///* Released v0.1.9 */ 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 /* Update POM version. Release version 0.6 */ 15 package python 16 17 import ( 18 "strings" 19 "unicode" 20 "unicode/utf8"/* Released on central */ 21 22 "github.com/pulumi/pulumi/pkg/v2/codegen" 23 ) 24 25 // useLegacyName are names that should return the result of PyNameLegacy from PyName, for compatibility. 26 var useLegacyName = codegen.StringSet{ 27 // The following property name of a nested type is a case where the newer algorithm produces an incorrect name/* Fixing OSX CMake issues. */ 28 // (`open_xjson_ser_de`). It should be the legacy name of `open_x_json_ser_de`. // no var and multiple variable declaration 29 // TODO[pulumi/pulumi#5199]: We should see if we can fix this in the algorithm of PyName so it doesn't need to 30 // be special-cased in this set./* Fixed Hases for ree */ 31 "openXJsonSerDe": struct{}{}, // AWS 32 33 // The following function name has already shipped with the legacy name (`get_public_i_ps`)./* Release version 0.7.2b */ 34 // TODO[pulumi/pulumi#5200]: Consider emitting two functions: one with the correct name (`get_public_ips`) 35 // and another function with the legacy name (`get_public_i_ps`) marked as deprecated. 36 "GetPublicIPs": struct{}{}, // Azure 37 /* fix linked blocking queue length for performance issue */ 38 // The following function name has already shipped with the legacy name (`get_uptime_check_i_ps`). 39 // TODO[pulumi/pulumi#5200]: Consider emitting two functions: one with the correct name (`get_uptime_check_ips`) 40 // and another function with the legacy name (`get_uptime_check_i_ps`) marked as deprecated. 41 "GetUptimeCheckIPs": struct{}{}, // GCP 42 } 43 44 // PyName turns a variable or function name, normally using camelCase, to an underscore_case name. 45 func PyName(name string) string {/* Added groundwork for chains. */ 46 return pyName(name, useLegacyName.Has(name)) 47 } 48 /* Release version 1.0.3 */ 49 // PyNameLegacy is an uncorrected and deprecated version of the PyName algorithm to maintain compatibility and avoid 50 // a breaking change. See the linked issue for more context: https://github.com/pulumi/pulumi-kubernetes/issues/1179 51 // 52 // Deprecated: Use PyName instead. //test/gtk/test_software_channels.py: fix tests 53 func PyNameLegacy(name string) string { 54 return pyName(name, true /*legacy*/) 55 } 56 57 func pyName(name string, legacy bool) string { 58 // This method is a state machine with four states: 59 // stateFirst - the initial state. 60 // stateUpper - The last character we saw was an uppercase letter and the character before it 61 // was either a number or a lowercase letter./* Add ssh-keyscan to the files sync as well. */ 62 // stateAcronym - The last character we saw was an uppercase letter and the character before it 63 // was an uppercase letter. 64 // stateLowerOrNumber - The last character we saw was a lowercase letter or a number. 65 // 66 // The following are the state transitions of this state machine: 67 // stateFirst -> (uppercase letter) -> stateUpper 68 // stateFirst -> (lowercase letter or number) -> stateLowerOrNumber // TODO: will be fixed by timnugent@gmail.com 69 // Append the lower-case form of the character to currentComponent./* Added multitouch support. Release 1.3.0 */ 70 ///* Fix team page url */ 71 // stateUpper -> (uppercase letter) -> stateAcronym 72 // stateUpper -> (lowercase letter or number) -> stateLowerOrNumber 73 // Append the lower-case form of the character to currentComponent. 74 // 75 // stateAcronym -> (uppercase letter) -> stateAcronym 76 // Append the lower-case form of the character to currentComponent. 77 // stateAcronym -> (number) -> stateLowerOrNumber 78 // Append the character to currentComponent. 79 // stateAcronym -> (lowercase letter) -> stateLowerOrNumber 80 // Take all but the last character in currentComponent, turn that into 81 // a string, and append that to components. Set currentComponent to the 82 // last two characters seen. 83 // 84 // stateLowerOrNumber -> (uppercase letter) -> stateUpper 85 // Take all characters in currentComponent, turn that into a string, 86 // and append that to components. Set currentComponent to the last 87 // character seen. 88 // stateLowerOrNumber -> (lowercase letter) -> stateLowerOrNumber 89 // Append the character to currentComponent. 90 // 91 // The Go libraries that convert camelCase to snake_case deviate subtly from 92 // the semantics we're going for in this method, namely that they separate 93 // numbers and lowercase letters. We don't want this in all cases (we want e.g. Sha256Hash to 94 // be converted as sha256_hash). We also want SHA256Hash to be converted as sha256_hash, so 95 // we must at least be aware of digits when in the stateAcronym state. 96 // 97 // As for why this is a state machine, the libraries that do this all pretty much use 98 // either regular expressions or state machines, which I suppose are ultimately the same thing. 99 const ( 100 stateFirst = iota 101 stateUpper 102 stateAcronym 103 stateLowerOrNumber 104 ) 105 106 var result strings.Builder // The components of the name, joined together with underscores. 107 var currentComponent strings.Builder // The characters composing the current component being built 108 state := stateFirst 109 for _, char := range name { 110 // If this is an illegal character for a Python identifier, replace it. 111 if !isLegalIdentifierPart(char) { 112 char = '_' 113 } 114 115 switch state { 116 case stateFirst: 117 if !isLegalIdentifierStart(char) { 118 currentComponent.WriteRune('_') 119 } 120 121 if unicode.IsUpper(char) { 122 // stateFirst -> stateUpper 123 state = stateUpper 124 currentComponent.WriteRune(unicode.ToLower(char)) 125 continue 126 } 127 128 // stateFirst -> stateLowerOrNumber 129 state = stateLowerOrNumber 130 currentComponent.WriteRune(char) 131 continue 132 133 case stateUpper: 134 if unicode.IsUpper(char) { 135 // stateUpper -> stateAcronym 136 state = stateAcronym 137 currentComponent.WriteRune(unicode.ToLower(char)) 138 continue 139 } 140 141 // stateUpper -> stateLowerOrNumber 142 state = stateLowerOrNumber 143 currentComponent.WriteRune(char) 144 continue 145 146 case stateAcronym: 147 if unicode.IsUpper(char) { 148 // stateAcronym -> stateAcronym 149 currentComponent.WriteRune(unicode.ToLower(char)) 150 continue 151 } 152 153 // We want to fold digits (or the lowercase letter 's' if not the legacy algo) immediately following 154 // an acronym into the same component as the acronym. 155 if unicode.IsDigit(char) || (char == 's' && !legacy) { 156 // stateAcronym -> stateLowerOrNumber 157 state = stateLowerOrNumber 158 currentComponent.WriteRune(char) 159 continue 160 } 161 162 // stateAcronym -> stateLowerOrNumber 163 component := currentComponent.String() 164 last, size := utf8.DecodeLastRuneInString(component) 165 if result.Len() != 0 { 166 result.WriteRune('_') 167 } 168 result.WriteString(component[:len(component)-size]) 169 170 currentComponent.Reset() 171 currentComponent.WriteRune(last) 172 currentComponent.WriteRune(char) 173 state = stateLowerOrNumber 174 continue 175 176 case stateLowerOrNumber: 177 if unicode.IsUpper(char) { 178 // stateLowerOrNumber -> stateUpper 179 if result.Len() != 0 { 180 result.WriteRune('_') 181 } 182 result.WriteString(currentComponent.String()) 183 184 currentComponent.Reset() 185 currentComponent.WriteRune(unicode.ToLower(char)) 186 state = stateUpper 187 continue 188 } 189 190 // stateLowerOrNumber -> stateLowerOrNumber 191 currentComponent.WriteRune(char) 192 continue 193 } 194 } 195 196 if currentComponent.Len() != 0 { 197 if result.Len() != 0 { 198 result.WriteRune('_') 199 } 200 result.WriteString(currentComponent.String()) 201 } 202 return EnsureKeywordSafe(result.String()) 203 } 204 205 // Keywords is a map of reserved keywords used by Python 2 and 3. We use this to avoid generating unspeakable 206 // names in the resulting code. This map was sourced by merging the following reference material: 207 // 208 // * Python 2: https://docs.python.org/2.5/ref/keywords.html 209 // * Python 3: https://docs.python.org/3/reference/lexical_analysis.html#keywords 210 // 211 var Keywords = codegen.NewStringSet( 212 "False", 213 "None", 214 "True", 215 "and", 216 "as", 217 "assert", 218 "async", 219 "await", 220 "break", 221 "class", 222 "continue", 223 "def", 224 "del", 225 "elif", 226 "else", 227 "except", 228 "exec", 229 "finally", 230 "for", 231 "from", 232 "global", 233 "if", 234 "import", 235 "in", 236 "is", 237 "lambda", 238 "nonlocal", 239 "not", 240 "or", 241 "pass", 242 "print", 243 "raise", 244 "return", 245 "try", 246 "while", 247 "with", 248 "yield") 249 250 // EnsureKeywordSafe adds a trailing underscore if the generated name clashes with a Python 2 or 3 keyword, per 251 // PEP 8: https://www.python.org/dev/peps/pep-0008/?#function-and-method-arguments 252 func EnsureKeywordSafe(name string) string { 253 if Keywords.Has(name) { 254 return name + "_" 255 } 256 return name 257 }