Permalink
Browse files

Initial commit.

  • Loading branch information...
1 parent 708c363 commit 5f98cc506494ac65f8348d52b59fb3cde4e56292 @mansilladev mansilladev committed Jul 16, 2012
Showing with 16,924 additions and 1 deletion.
  1. +21 −0 LICENSE.txt
  2. +46 −0 google-apis-client-generator/CHANGES
  3. +202 −0 google-apis-client-generator/LICENSE
  4. +46 −0 google-apis-client-generator/README
  5. +1 −0 google-apis-client-generator/src/__init__.py
  6. +1 −0 google-apis-client-generator/src/googleapis/__init__.py
  7. BIN google-apis-client-generator/src/googleapis/__init__.pyc
  8. BIN google-apis-client-generator/src/googleapis/codegen/.name_validator.py.swp
  9. +1 −0 google-apis-client-generator/src/googleapis/codegen/__init__.py
  10. BIN google-apis-client-generator/src/googleapis/codegen/__init__.pyc
  11. +35 −0 google-apis-client-generator/src/googleapis/codegen/anyjson.py
  12. BIN google-apis-client-generator/src/googleapis/codegen/anyjson.pyc
  13. +799 −0 google-apis-client-generator/src/googleapis/codegen/api.py
  14. BIN google-apis-client-generator/src/googleapis/codegen/api.pyc
  15. +332 −0 google-apis-client-generator/src/googleapis/codegen/api_test.py
  16. +164 −0 google-apis-client-generator/src/googleapis/codegen/csharp_generator.py
  17. BIN google-apis-client-generator/src/googleapis/codegen/csharp_generator.pyc
  18. +288 −0 google-apis-client-generator/src/googleapis/codegen/data_types.py
  19. BIN google-apis-client-generator/src/googleapis/codegen/data_types.pyc
  20. +46 −0 google-apis-client-generator/src/googleapis/codegen/data_types_test.py
  21. +43 −0 google-apis-client-generator/src/googleapis/codegen/django_helpers.py
  22. BIN google-apis-client-generator/src/googleapis/codegen/django_helpers.pyc
  23. +83 −0 google-apis-client-generator/src/googleapis/codegen/filesystem_library_package.py
  24. BIN google-apis-client-generator/src/googleapis/codegen/filesystem_library_package.pyc
  25. +203 −0 google-apis-client-generator/src/googleapis/codegen/generate_library.py
  26. +532 −0 google-apis-client-generator/src/googleapis/codegen/generator.py
  27. BIN google-apis-client-generator/src/googleapis/codegen/generator.pyc
  28. +32 −0 google-apis-client-generator/src/googleapis/codegen/generator_test.py
  29. +108 −0 google-apis-client-generator/src/googleapis/codegen/go/default/templates/___api_className___.go.tmpl
  30. +152 −0 google-apis-client-generator/src/googleapis/codegen/go/default/templates/_method.tmpl
  31. +19 −0 google-apis-client-generator/src/googleapis/codegen/go/default/templates/_model.tmpl
  32. +14 −0 google-apis-client-generator/src/googleapis/codegen/go/default/templates/_resource.tmpl
  33. +173 −0 google-apis-client-generator/src/googleapis/codegen/go_generator.py
  34. BIN google-apis-client-generator/src/googleapis/codegen/go_generator.pyc
  35. +58 −0 google-apis-client-generator/src/googleapis/codegen/go_generator_test.py
  36. +125 −0 google-apis-client-generator/src/googleapis/codegen/goog.json
  37. +2 −0 google-apis-client-generator/src/googleapis/codegen/gwt/OWNERS
  38. +77 −0 ...enerator/src/googleapis/codegen/gwt/default/templates/___package___/___api_className___.java.tmpl
  39. +43 −0 ...src/googleapis/codegen/gwt/default/templates/___package___/model/___models_className___.java.tmpl
  40. +21 −0 ...lient-generator/src/googleapis/codegen/gwt/default/templates/___package___/package-info.java.tmpl
  41. +6 −0 google-apis-client-generator/src/googleapis/codegen/gwt/default/templates/_enum.tmpl
  42. +31 −0 google-apis-client-generator/src/googleapis/codegen/gwt/default/templates/_method.tmpl
  43. +124 −0 google-apis-client-generator/src/googleapis/codegen/gwt/default/templates/build.xml.tmpl
  44. +6 −0 ...leapis/codegen/gwt/default/templates/com/google/api/gwt/services/___api_className___.gwt.xml.tmpl
  45. +77 −0 ...generator/src/googleapis/codegen/gwt/stable/templates/___package___/___api_className___.java.tmpl
  46. +43 −0 .../src/googleapis/codegen/gwt/stable/templates/___package___/model/___models_className___.java.tmpl
  47. +21 −0 ...client-generator/src/googleapis/codegen/gwt/stable/templates/___package___/package-info.java.tmpl
  48. +6 −0 google-apis-client-generator/src/googleapis/codegen/gwt/stable/templates/_enum.tmpl
  49. +31 −0 google-apis-client-generator/src/googleapis/codegen/gwt/stable/templates/_method.tmpl
  50. +127 −0 google-apis-client-generator/src/googleapis/codegen/gwt/stable/templates/build.xml.tmpl
  51. +6 −0 ...gleapis/codegen/gwt/stable/templates/com/google/api/gwt/services/___api_className___.gwt.xml.tmpl
  52. +104 −0 google-apis-client-generator/src/googleapis/codegen/gwt_generator.py
  53. BIN google-apis-client-generator/src/googleapis/codegen/gwt_generator.pyc
  54. +58 −0 google-apis-client-generator/src/googleapis/codegen/gwt_generator_test.py
  55. +28 −0 google-apis-client-generator/src/googleapis/codegen/html_stripper.py
  56. BIN google-apis-client-generator/src/googleapis/codegen/html_stripper.pyc
  57. +33 −0 google-apis-client-generator/src/googleapis/codegen/import_definition.py
  58. BIN google-apis-client-generator/src/googleapis/codegen/import_definition.pyc
  59. +109 −0 google-apis-client-generator/src/googleapis/codegen/java/default/templates/_method.tmpl
  60. +9 −0 google-apis-client-generator/src/googleapis/codegen/java/default/templates/_model_def.tmpl
  61. +5 −0 google-apis-client-generator/src/googleapis/codegen/java/default/templates/_parameter.tmpl
  62. +30 −0 google-apis-client-generator/src/googleapis/codegen/java/default/templates/_resource.tmpl
  63. +73 −0 google-apis-client-generator/src/googleapis/codegen/java/default/templates/pom.xml.tmpl
  64. +395 −0 ...ogleapis/codegen/java/default/templates/src/main/java/___package___/___api_className___.java.tmpl
  65. +60 −0 ...s/codegen/java/default/templates/src/main/java/___package___/___api_className___Request.java.tmpl
  66. +81 −0 ...codegen/java/default/templates/src/main/java/___package___/model/___models_className___.java.tmpl
  67. BIN ...erator/src/googleapis/codegen/java/legacy_gpe/dependencies/jars/google-api-client-1.3.1-alpha.jar
  68. BIN ...googleapis/codegen/java/legacy_gpe/dependencies/jars/google-api-client-googleapis-1.3.1-alpha.jar
  69. BIN google-apis-client-generator/src/googleapis/codegen/java/legacy_gpe/dependencies/jars/guava-r08.jar
  70. BIN ...ent-generator/src/googleapis/codegen/java/legacy_gpe/dependencies/jars/jackson-core-asl-1.4.0.jar
  71. +109 −0 google-apis-client-generator/src/googleapis/codegen/java/stable/templates/_method.tmpl
  72. +6 −0 google-apis-client-generator/src/googleapis/codegen/java/stable/templates/_model_def.tmpl
  73. +5 −0 google-apis-client-generator/src/googleapis/codegen/java/stable/templates/_parameter.tmpl
  74. +30 −0 google-apis-client-generator/src/googleapis/codegen/java/stable/templates/_resource.tmpl
  75. +73 −0 google-apis-client-generator/src/googleapis/codegen/java/stable/templates/pom.xml.tmpl
  76. +394 −0 ...oogleapis/codegen/java/stable/templates/src/main/java/___package___/___api_className___.java.tmpl
  77. +60 −0 ...is/codegen/java/stable/templates/src/main/java/___package___/___api_className___Request.java.tmpl
  78. +79 −0 .../codegen/java/stable/templates/src/main/java/___package___/model/___models_className___.java.tmpl
  79. +252 −0 google-apis-client-generator/src/googleapis/codegen/java_generator.py
  80. BIN google-apis-client-generator/src/googleapis/codegen/java_generator.pyc
  81. +66 −0 google-apis-client-generator/src/googleapis/codegen/java_generator_test.py
  82. +117 −0 google-apis-client-generator/src/googleapis/codegen/java_import_manager.py
  83. BIN google-apis-client-generator/src/googleapis/codegen/java_import_manager.pyc
  84. +99 −0 google-apis-client-generator/src/googleapis/codegen/java_import_manager_test.py
  85. +135 −0 google-apis-client-generator/src/googleapis/codegen/language_model.py
  86. BIN google-apis-client-generator/src/googleapis/codegen/language_model.pyc
  87. +112 −0 google-apis-client-generator/src/googleapis/codegen/library_package.py
  88. BIN google-apis-client-generator/src/googleapis/codegen/library_package.pyc
  89. +155 −0 google-apis-client-generator/src/googleapis/codegen/name_validator.py
  90. BIN google-apis-client-generator/src/googleapis/codegen/name_validator.pyc
  91. +92 −0 google-apis-client-generator/src/googleapis/codegen/name_validator_test.py
  92. +14 −0 ...rator/src/googleapis/codegen/objc/experimental/templates/___package___/___api_className___.m.tmpl
  93. +46 −0 ...oogleapis/codegen/objc/experimental/templates/___package___/___topLevelModels_className___.h.tmpl
  94. +43 −0 ...oogleapis/codegen/objc/experimental/templates/___package___/___topLevelModels_className___.m.tmpl
  95. +151 −0 google-apis-client-generator/src/googleapis/codegen/objc_generator.py
  96. BIN google-apis-client-generator/src/googleapis/codegen/objc_generator.pyc
  97. +1 −0 google-apis-client-generator/src/googleapis/codegen/php/OWNERS
  98. +13 −0 google-apis-client-generator/src/googleapis/codegen/php/default/_func_params.tmpl
  99. +45 −0 google-apis-client-generator/src/googleapis/codegen/php/default/_method.tmpl
  100. +28 −0 google-apis-client-generator/src/googleapis/codegen/php/default/_model_class.tmpl
  101. +17 −0 google-apis-client-generator/src/googleapis/codegen/php/default/_resource.tmpl
  102. +53 −0 google-apis-client-generator/src/googleapis/codegen/php/default/api_service_class.tmpl
  103. +13 −0 google-apis-client-generator/src/googleapis/codegen/php/stable/_func_params.tmpl
  104. +45 −0 google-apis-client-generator/src/googleapis/codegen/php/stable/_method.tmpl
  105. +28 −0 google-apis-client-generator/src/googleapis/codegen/php/stable/_model_class.tmpl
  106. +17 −0 google-apis-client-generator/src/googleapis/codegen/php/stable/_resource.tmpl
  107. +53 −0 google-apis-client-generator/src/googleapis/codegen/php/stable/api_service_class.tmpl
  108. +53 −0 google-apis-client-generator/src/googleapis/codegen/php/stable/api_service_class.tmpl2
  109. +312 −0 google-apis-client-generator/src/googleapis/codegen/php_generator.py
  110. BIN google-apis-client-generator/src/googleapis/codegen/php_generator.pyc
  111. +139 −0 google-apis-client-generator/src/googleapis/codegen/php_generator_test.py
  112. +28 −0 google-apis-client-generator/src/googleapis/codegen/python/stable/appengine/instructions.tmpl
  113. +12 −0 google-apis-client-generator/src/googleapis/codegen/python/stable/appengine/skeleton/app_yaml.tmpl
  114. +9 −0 ...apis-client-generator/src/googleapis/codegen/python/stable/appengine/skeleton/client_secrets.json
  115. +138 −0 google-apis-client-generator/src/googleapis/codegen/python/stable/appengine/skeleton/main.py.tmpl
  116. +20 −0 google-apis-client-generator/src/googleapis/codegen/python/stable/cmd-line/instructions.tmpl
  117. +9 −0 ...-apis-client-generator/src/googleapis/codegen/python/stable/cmd-line/skeleton/client_secrets.json
  118. +145 −0 google-apis-client-generator/src/googleapis/codegen/python/stable/cmd-line/skeleton/sample.py.tmpl
  119. +9 −0 google-apis-client-generator/src/googleapis/codegen/python/stable/skeleton/client_secrets.json
  120. +145 −0 google-apis-client-generator/src/googleapis/codegen/python/stable/skeleton/sample.py.tmpl
  121. +30 −0 google-apis-client-generator/src/googleapis/codegen/python_skeleton_generator.py
  122. +90 −0 google-apis-client-generator/src/googleapis/codegen/quickstart_push.py
  123. +116 −0 google-apis-client-generator/src/googleapis/codegen/targets.json
  124. +144 −0 google-apis-client-generator/src/googleapis/codegen/targets.py
  125. BIN google-apis-client-generator/src/googleapis/codegen/targets.pyc
  126. +71 −0 google-apis-client-generator/src/googleapis/codegen/targets_test.py
  127. +955 −0 google-apis-client-generator/src/googleapis/codegen/template_helpers.py
  128. BIN google-apis-client-generator/src/googleapis/codegen/template_helpers.pyc
  129. +171 −0 google-apis-client-generator/src/googleapis/codegen/template_helpers_test.py
  130. +319 −0 google-apis-client-generator/src/googleapis/codegen/template_objects.py
  131. BIN google-apis-client-generator/src/googleapis/codegen/template_objects.pyc
  132. +71 −0 google-apis-client-generator/src/googleapis/codegen/template_objects_test.py
  133. +1 −0 google-apis-client-generator/src/googleapis/codegen/testdata/_call_test.tmpl
  134. +77 −0 google-apis-client-generator/src/googleapis/codegen/testdata/enums.json
  135. +3 −0 google-apis-client-generator/src/googleapis/codegen/testdata/file1.txt
  136. +18 −0 google-apis-client-generator/src/googleapis/codegen/testdata/java/imports_test.java.tmpl
  137. +132 −0 google-apis-client-generator/src/googleapis/codegen/testdata/latitude.v1.json
  138. +1,529 −0 google-apis-client-generator/src/googleapis/codegen/testdata/moderator.v1.json
  139. +41 −0 google-apis-client-generator/src/googleapis/codegen/testdata/non_datawrapper.json
  140. +375 −0 google-apis-client-generator/src/googleapis/codegen/testdata/post_variations.json
  141. +3,617 −0 google-apis-client-generator/src/googleapis/codegen/testdata/sample_discovery.json
  142. +9 −0 google-apis-client-generator/src/googleapis/codegen/testdata/targets.json
  143. +47 −0 google-apis-client-generator/src/googleapis/codegen/testdata/targets_test.json
  144. +1 −0 google-apis-client-generator/src/googleapis/codegen/testdata/tree/abc
  145. +1 −0 google-apis-client-generator/src/googleapis/codegen/testdata/tree/def
  146. +1 −0 google-apis-client-generator/src/googleapis/codegen/testdata/tree/subdir/123
  147. +47 −0 google-apis-client-generator/src/googleapis/codegen/utilities.py
  148. BIN google-apis-client-generator/src/googleapis/codegen/utilities.pyc
  149. +42 −0 google-apis-client-generator/src/googleapis/codegen/utilities_test.py
  150. +118 −0 google-apis-client-generator/src/googleapis/codegen/zip_library_package.py
  151. BIN google-apis-client-generator/src/googleapis/codegen/zip_library_package.pyc
  152. +144 −0 google-apis-client-generator/src/googleapis/codegen/zip_library_package_test.py
  153. +194 −0 iodocs_json_converter.html
  154. +60 −1 readme.md
View
21 LICENSE.txt
@@ -0,0 +1,21 @@
+The MIT License
+
+Copyright (C) 2012 Mashery, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
View
46 google-apis-client-generator/CHANGES
@@ -0,0 +1,46 @@
+Change Summary
+
+1.1.1
+
+2011-10-20
+* add DataType classes to replace the use of strings for types.
+ - Completely rework the interpretation of JsonSchema into DataTypes to
+ make them clearer.
+* A large set of refactorings in an ongoing effort to make Api definitions
+ distinct from the language we will generate in
+ - add LanguageModel, which each language subclasses to provide utililes
+ for formatting DataTypes for use in templates
+ - defer creation of codeType from API parsing to code generation, using
+ the pair of LanguageModel and DataType to emit the right thing.
+* Add Packages to the things which can appear in code. Use package.name in
+ templates rather than explictly building relative paths.
+* Add a parent/child relationship between data models. This is to pave the
+ way for generators which represent anonymous classes as nested classes.
+* Add tags for building parameter lists. This moved the code to create those
+ lists from Annotators buried in the per-language generators out to templates.
+* Add a 'call_template' tag to make it factor out common template idioms.
+
+2011-07-13
+* Fix django usage for PHP generator
+* Fix autoescape problem with django 1.x vs. 0.96
+
+2011-07-25
+* Added experimental C# generator. This is just a placeholder for now. It does
+ not generate code that works yet.
+
+2011-07-27
+* Support for additionalProperties when used as a pure map.
+* Update to g.a.j.c 1.5
+
+2011-08-01
+* Added experimental Go generator. This is just a placeholder for now. It does
+ not generate code that works yet.
+
+2011-08-05
+* Added experimental Objective-C generator. This is just a placeholder for now. It does not generate code that works yet.
+
+2011-08-10
+* Update Java surface to 1.2.0-beta
+
+2011-08-19
+* Various refactorings to make packaging easier.
View
202 google-apis-client-generator/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
View
46 google-apis-client-generator/README
@@ -0,0 +1,46 @@
+# Copyright 2011 Google, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+Google APIs Code Generator
+
+June. 16, 2011
+Tony Aiuto (aiuto@google.com)
+
+Introduction
+
+This is a tool for generating code from Google APIs Discovery documents.
+The current version generates API client libraries for Java and GWT.
+
+
+Prerequisites
+
+Python 2.6 or newer
+
+* Google apputils - http://code.google.com/p/google-apputils-python/
+* django templates (1.1 or newer) - either through django or
+ Google AppEngine SDKs
+* httplib2 - http://code.google.com/p/httplib2/
+* python-gflags - http://code.google.com/p/python-gflags/
+* setuptools - http://pypi.python.org/pypi/setuptools/
+
+
+Running it:
+
+You must set PYTHONPATH to the path to the src folder. You should invoke
+the program using the full path to generate_library.py. E.g.
+
+ PYTHONPATH=$(/bin/pwd)/src:$(PYPATH) \
+ $(/bin/pwd)/src/googleapis/codegen/generate_library.py \
+ --api_name=buzz --api_version=v1 --output_dir=generated
+
View
1 google-apis-client-generator/src/__init__.py
@@ -0,0 +1 @@
+#!/usr/bin/python2.6
View
1 google-apis-client-generator/src/googleapis/__init__.py
@@ -0,0 +1 @@
+#!/usr/bin/python2.6
View
BIN google-apis-client-generator/src/googleapis/__init__.pyc
Binary file not shown.
View
BIN google-apis-client-generator/src/googleapis/codegen/.name_validator.py.swp
Binary file not shown.
View
1 google-apis-client-generator/src/googleapis/codegen/__init__.py
@@ -0,0 +1 @@
+#!/usr/bin/python2.6
View
BIN google-apis-client-generator/src/googleapis/codegen/__init__.pyc
Binary file not shown.
View
35 google-apis-client-generator/src/googleapis/codegen/anyjson.py
@@ -0,0 +1,35 @@
+#!/usr/bin/python2.6
+#
+# Copyright 2010 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+"""Utility module to import a JSON module.
+
+Hides all the messy details of exactly where
+we get a simplejson module from.
+"""
+
+__author__ = 'jcgregorio@google.com (Joe Gregorio)'
+
+
+try: # pragma: no cover
+ import simplejson
+except ImportError: # pragma: no cover
+ try:
+ # Try to import from django, should work on App Engine
+ from django.utils import simplejson
+ except ImportError:
+ # Should work for Python2.6 and higher.
+ import json as simplejson
View
BIN google-apis-client-generator/src/googleapis/codegen/anyjson.pyc
Binary file not shown.
View
799 google-apis-client-generator/src/googleapis/codegen/api.py
@@ -0,0 +1,799 @@
+#!/usr/bin/python2.6
+#
+# Copyright 2010 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Create an API definition by interpreting a discovery document.
+
+This module interprets a discovery document to create a tree of classes which
+represent the API structure in a way that is useful for generating a library.
+For each discovery element (e.g. schemas, resources, methods, ...) there is
+a class to represent it which is directly usable in the templates. The
+instances of those classes are annotated with extra variables for use
+in the template which are language specific.
+
+The current way to make use of this class is to create a programming language
+specific subclass of Api, which adds annotations and template variables
+appropriate for that language.
+TODO(user): Refactor this so that the API can be loaded first, then annotated.
+"""
+
+__author__ = 'aiuto@google.com (Tony Aiuto)'
+
+import copy
+import logging
+
+
+from googleapis.codegen import data_types
+from googleapis.codegen import template_objects
+from googleapis.codegen import utilities
+from googleapis.codegen.anyjson import simplejson
+
+_ADDITIONAL_PROPERTIES = 'additionalProperties'
+
+
+class ApiException(Exception):
+ """The base class for all API parsing exceptions."""
+
+ def __init__(self, reason, def_dict=None):
+ """Create an exception.
+
+ Args:
+ reason: (str) The human readable explanation of this exception.
+ def_dict: (dict) The discovery dictionary we failed on.
+ """
+ super(ApiException, self).__init__()
+ self._reason = reason
+ self._def_dict = def_dict
+ self._raw_def_dict = copy.deepcopy(def_dict)
+
+ def __str__(self):
+ if self._def_dict:
+ return '%s: %s' % (self._reason, self._def_dict)
+ return self._reason
+
+
+class Api(template_objects.CodeObject):
+ """An API definition.
+
+ This class holds a discovery centric definition of an API. It contains
+ members such as "resources" and "schemas" which relate directly to discovery
+ concepts. It defines several properties that can be used in code generation
+ templates:
+ name: The API name.
+ version: The API version.
+ versionNoDots: The API version with all '.' characters replaced with '_'
+
+ authScopes: The list of the OAuth scopes used by this API.
+ dataWrapper: True if the API definition contains the 'dataWrapper' feature.
+ methods: The list of top level API methods.
+ models: The list of API data models, both from the schema section of
+ discovery and from anonymous objects defined in method definitions.
+ parameters: The list of global method parameters (applicable to all methods)
+ resources: The list of API resources
+ """
+
+ def __init__(self, discovery_doc, language=None):
+ super(Api, self).__init__(discovery_doc, self)
+ name = self.values['name']
+ self._validator.ValidateApiName(name)
+ self._validator.ValidateApiVersion(self.values['version'])
+ self._class_name = utilities.CamelCase(name)
+ self._language = language
+ self._template_dir = None
+ self._surface_features = {}
+ self._schemas = {}
+ self.void_type = data_types.Void(self)
+
+ self.SetTemplateValue('className', self._class_name)
+ self.SetTemplateValue('versionNoDots',
+ self.values['version'].replace('.', '_'))
+ self.SetTemplateValue('dataWrapper',
+ 'dataWrapper' in discovery_doc.get('features', []))
+
+ self._BuildSchemaDefinitions()
+ self._BuildResourceDefinitions()
+ self.SetTemplateValue('resources', self._resources)
+
+ # Make data models part of the api dictionary
+ self.SetTemplateValue('models', self.ModelClasses())
+
+ # Replace methods dict with Methods
+ self._methods = []
+ for name, method_dict in self.values.get('methods', {}).iteritems():
+ self._methods.append(Method(self, name, method_dict))
+ self.SetTemplateValue('methods', self._methods)
+
+ # Global parameters
+ self._parameters = []
+ for name, param_dict in self.values.get('parameters', {}).iteritems():
+ self._parameters.append(Parameter(self, name, param_dict, self))
+ self.SetTemplateValue('parameters', self._parameters)
+
+ # Auth scopes
+ self._authscopes = []
+ if (self.values.get('auth') and
+ self.values['auth'].get('oauth2') and
+ self.values['auth']['oauth2'].get('scopes')):
+ for value, auth_dict in sorted(
+ self.values['auth']['oauth2']['scopes'].iteritems()):
+ self._authscopes.append(AuthScope(self, value, auth_dict))
+ self.SetTemplateValue('authscopes', self._authscopes)
+
+ @property
+ def all_schemas(self):
+ """The dictonary of all the schema objects found in the API."""
+ return self._schemas
+
+ def _BuildResourceDefinitions(self):
+ """Loop over the resources in the discovery doc and build definitions."""
+ self._resources = []
+ for name, def_dict in self.values.get('resources', {}).iteritems():
+ resource = Resource(self, name, def_dict)
+ self._resources.append(resource)
+
+ def _BuildSchemaDefinitions(self):
+ """Loop over the schemas in the discovery doc and build definitions."""
+ schemas = self.values.get('schemas')
+ if schemas:
+ for name, def_dict in schemas.iteritems():
+ # Upgrade the string format schema to a dict.
+ if isinstance(def_dict, unicode):
+ def_dict = simplejson.loads(def_dict)
+ self._schemas[name] = self.DataTypeFromJson(def_dict, name)
+
+ def ModelClasses(self):
+ """Return all the top level model classes."""
+ ret = []
+ for schema in self._schemas.values():
+ if schema not in ret:
+ if (not isinstance(schema, data_types.SchemaReference)
+ and not schema.values.get('builtIn')):
+ ret.append(schema)
+ ret.sort(lambda x, y: cmp(x.class_name, y.class_name))
+ return ret
+
+ def TopLevelModelClasses(self):
+ """Return the models which are not children of another model."""
+ return [m for m in self.ModelClasses() if not m.parent]
+
+ def DataTypeFromJson(self, type_dict, default_name, parent=None,
+ wire_name=None):
+ """Returns a schema object represented by a JSON Schema dictionary.
+
+ If the response dict references an existing schema, return the ref to
+ that. If it describes a value in-line, then create the schema dynamically.
+ If the type_dict is None, a blank schema will be created.
+
+ Args:
+ type_dict: A dict of the form expected of a request or response member
+ of a method description. See the Discovery specification for more.
+ default_name: The unique name to give the schema if we have to create it.
+ parent: The schema where I was referenced. If we cannot determine that
+ this is a top level schema, set the parent to this.
+ wire_name: The name which will identify objects of this type in data on
+ the wire.
+ Returns:
+ A Schema object.
+ """
+ if not type_dict:
+ type_dict = {}
+ schema_name = type_dict.get('$ref', default_name)
+ schema = self.SchemaByName(schema_name)
+ if schema:
+ Trace('DataTypeFromJson: %s => %s' % (schema_name,
+ schema.values['className']))
+ return schema
+
+ # new or not initialized, create a fresh one
+ schema = Schema.Create(self, schema_name, type_dict, wire_name, parent)
+ # Only put it in our by-name list if it is a real object
+ if (not isinstance(schema, data_types.SchemaReference) and
+ not schema.values.get('builtIn')):
+ Trace('DataTypeFromJson: add %s to cache' % schema.values['className'])
+ self._schemas[schema.values['className']] = schema
+
+ return schema
+
+ def SchemaByName(self, schema_name):
+ """Find a schema by name.
+
+ Args:
+ schema_name: (str) name of a schema defined by this API.
+
+ Returns:
+ Schema object or None if not found.
+ """
+ return self._schemas.get(schema_name, None)
+
+ def VisitAll(self, func):
+ """Visit all nodes of an API tree and apply a function to each.
+
+ Walks an tree and calls a function on each element of it. This should be
+ called after the API is fully loaded.
+
+ Args:
+ func: (function) Method to call on each object.
+ """
+ Trace('Applying function to all nodes')
+ for resource in self.values['resources']:
+ self._VisitResource(resource, func)
+ # Top level methods
+ for method in self.values['methods']:
+ self._VisitMethod(method, func)
+ for parameter in self.values['parameters']:
+ func(parameter)
+ for schema in self._schemas.values():
+ self._VisitSchema(schema, func)
+
+ def _VisitMethod(self, method, func):
+ """Visit a method, calling a function on every child.
+
+ Args:
+ method: (Method) The Method to visit.
+ func: (function) Method to call on each object.
+ """
+ func(method)
+ for parameter in method.parameters:
+ func(parameter)
+
+ def _VisitResource(self, resource, func):
+ """Visit a resource tree, calling a function on every child.
+
+ Calls down recursively to sub resources.
+
+ Args:
+ resource: (Resource) The Resource to visit.
+ func: (function) Method to call on each object.
+ """
+ func(resource)
+ for method in resource.values['methods']:
+ self._VisitMethod(method, func)
+ for r in resource.values['resources']:
+ self._VisitResource(r, func)
+
+ def _VisitSchema(self, schema, func):
+ """Visit a schema tree, calling a function on every child.
+
+ Args:
+ schema: (Schema) The Schema to visit.
+ func: (function) Method to call on each object.
+ """
+ func(schema)
+ for prop in schema.values.get('properties', []):
+ func(prop)
+
+ def ToClassName(self, s, element_type=None): # pylint: disable-msg=W0613
+ """Convert a name to a suitable member name in the target language.
+
+ This default implementation camel cases the string, which is appropriate
+ for Java and C++. Subclasses may override as appropriate.
+
+ Args:
+ s: (str) A rosy name of data element.
+ element_type: (str) The kind of object we are making a class name for.
+ E.g. resource, method, schema.
+ Returns:
+ A name suitable for use as a class in the generator's target language.
+ """
+ return utilities.CamelCase(s)
+
+ @property
+ def class_name(self):
+ return self.values['className']
+
+
+class Schema(data_types.DataType):
+ """The definition of a schema."""
+
+ def __init__(self, api, default_name, def_dict, parent=None):
+ """Construct a Schema object from a discovery dictionary.
+
+ Schemas represent data models in the API.
+
+ Args:
+ api: (Api) the Api instance owning the Schema
+ default_name: (str) the default name of the Schema. If there is an 'id'
+ member in the definition, that is used for the name instead.
+ def_dict: (dict) a discovery dictionary
+ parent: (Schema) The containing schema. To be used to establish unique
+ names for anonymous sub-schemas.
+ """
+ super(Schema, self).__init__(def_dict, api, parent=parent)
+
+ name = def_dict.get('id', default_name)
+ Trace('Schema(%s)' % name)
+
+ # Protect against malicious discovery
+ template_objects.CodeObject.ValidateName(name)
+ self.SetTemplateValue('wireName', name)
+ class_name = api.ToClassName(name, element_type='schema')
+ self.SetTemplateValue('className', class_name)
+ self.SetTemplateValue('builtIn', False)
+ self.SetTemplateValue('properties', [])
+
+ @staticmethod
+ def Create(api, default_name, def_dict, wire_name, parent=None):
+ """Construct a Schema or DataType from a discovery dictionary.
+
+ Schemas contain either object declarations, simple type declarations, or
+ references to other Schemas. Object declarations conceptually map to real
+ classes. Simple types will map to a target language built-in type.
+ References should effectively be replaced by the referenced Schema.
+
+ Args:
+ api: (Api) the Api instance owning the Schema
+ default_name: (str) the default name of the Schema. If there is an 'id'
+ member in the definition, that is used for the name instead.
+ def_dict: (dict) a discovery dictionary
+ wire_name: The name which will identify objects of this type in data on
+ the wire.
+ parent: (Schema) The containing schema. To be used to establish nesting
+ for anonymous sub-schemas.
+
+ Returns:
+ A Schema or DataType.
+
+ Raises:
+ ApiException: If the definition dict is not correct.
+ """
+
+ schema_id = def_dict.get('id')
+ if schema_id:
+ name = schema_id
+ else:
+ name = default_name
+ class_name = api.ToClassName(name, element_type='schema')
+
+ # Schema objects come in several patterns.
+ #
+ # 1. Simple objects
+ # { type: object, properties: { "foo": {schema} ... }}
+ #
+ # 2. Maps of objects
+ # { type: object, additionalProperties: { "foo": {inner_schema} ... }}
+ #
+ # What we want is a data type which is Map<string, {inner_schema}>
+ # The schema we create here is essentially a built in type which we
+ # don't want to generate a class for.
+ #
+ # 3. Arrays of objects
+ # { type: array, items: { inner_schema }}
+ #
+ # Same kind of issue as the map, but with List<{inner_schema}>
+ #
+ # 4. Primative data types, described by type and format.
+ # { type: string, format: int32 }
+ #
+ # 5. Refs to another schema.
+ # { $ref: name }
+
+ if 'type' in def_dict:
+ # The 'type' field of the schema can either be 'array', 'object', or a
+ # base json type.
+ json_type = def_dict['type']
+ if json_type == 'object':
+ # Look for full object definition. You can have properties or
+ # additionalProperties, but it does not do anything useful to have
+ # both.
+
+ # Replace properties dict with Property's
+ props = def_dict.get('properties')
+ if props:
+ # This case 1 from above
+ properties = []
+ schema = Schema(api, name, def_dict, parent=parent)
+ if wire_name:
+ schema.SetTemplateValue('wireName', wire_name)
+ for prop_name, prop_dict in props.iteritems():
+ Trace(' adding prop: %s to %s' % (prop_name, name))
+ properties.append(Property(api, schema, prop_name, prop_dict))
+ Trace('Marking %s fully defined' % schema.values['className'])
+ schema.SetTemplateValue('properties', properties)
+ return schema
+
+ # Look for case 2
+ additional_props = def_dict.get(_ADDITIONAL_PROPERTIES)
+ if additional_props:
+ Trace('Have only additionalProps for %s, dict=%s' % (
+ name, str(additional_props)))
+ # TODO(user): Remove this hack at the next large breaking change
+ # The "Items" added to the end is unneeded and ugly. This is for
+ # temporary backwards compatability. And in case 3 too.
+ if additional_props.get('type') == 'array':
+ name = '%sItems' % name
+ # Note, since this is an interim, non class just to hold the map
+ # make the parent schema the parent passed in, not myself.
+ base_type = api.DataTypeFromJson(additional_props, name,
+ parent=parent, wire_name=wire_name)
+ map_type = data_types.MapDataType(base_type, parent=parent)
+ Trace(' %s is MapOf<string, %s>' % (
+ class_name, base_type.class_name))
+ return map_type
+
+ raise ApiException('object without properties in: %s' % def_dict)
+
+ elif json_type == 'array':
+ # Case 3: Look for array definition
+ items = def_dict.get('items')
+ if not items:
+ raise ApiException('array without items in: %s' % def_dict)
+ tentative_class_name = class_name
+ if schema_id:
+ Trace('Top level schema %s is an array' % class_name)
+ tentative_class_name += 'Items'
+ base_type = api.DataTypeFromJson(items, tentative_class_name,
+ parent=parent, wire_name=wire_name)
+ Trace(' %s is ArrayOf<%s>' % (class_name, base_type.class_name))
+ array_type = data_types.ArrayDataType(base_type, parent=parent)
+
+ # If I am not a top level schema, mark me as not generatable
+ if not schema_id:
+ array_type.SetTemplateValue('builtIn', True)
+ else:
+ Trace('Top level schema %s is an array' % class_name)
+ array_type.SetTemplateValue('className', schema_id)
+ return array_type
+
+ else:
+ # Case 4: This must be a basic type. Create a DataType for it.
+ format_type = def_dict.get('format')
+ if format_type:
+ Trace(' Found Type: %s with Format: %s' % (json_type, format_type))
+
+ base_type = data_types.BuiltInDataType(def_dict, api, parent=parent)
+ return base_type
+
+ referenced_schema = def_dict.get('$ref')
+ if referenced_schema:
+ # Case 5: Reference to another Schema.
+ #
+ # There are 4 ways you can see '$ref' in discovery.
+ # 1. In a property of a schema, pointing back to one previously defined
+ # 2. In a property of a schema, pointing forward
+ # 3. In a method request or response pointing to a defined schema
+ # 4. In a method request or response or property of a schema pointing to
+ # something undefined.
+ #
+ # This code is not reached in case 1. The way the Generators loads
+ # schemas (see _BuildSchemaDefinitions), is to loop over them and add
+ # them to a dict of schemas. A backwards reference would be in the table
+ # so the DataTypeFromJson call in the Property constructor will resolve
+ # to the defined schema.
+ #
+ # For case 2. Just creating this placeholder here is fine. When the
+ # actual schema is hit in the loop in _BuildSchemaDefinitions, we will
+ # replace the entry and DataTypeFromJson will resolve the to the new def.
+ #
+ # For case 3, we should not reach this code, because the
+ # DataTypeFromJson would
+ # have returned the defined schema.
+ #
+ # For case 4, we punt on the whole API.
+ return data_types.SchemaReference(referenced_schema, api)
+
+ raise ApiException('Cannot decode JSON Schema for: %s' % def_dict)
+
+ @property
+ def class_name(self):
+ return self.values['className']
+
+
+class Resource(template_objects.CodeObject):
+ """The definition of a resource."""
+
+ def __init__(self, api, name, def_dict):
+ super(Resource, self).__init__(def_dict, api)
+ self.ValidateName(name)
+ self._raw_def_dict = copy.deepcopy(def_dict)
+ class_name = api.ToClassName(name, element_type='resource')
+ self.SetTemplateValue('className', class_name)
+ self.SetTemplateValue('wireName', name)
+ # Replace methods dict with Methods
+ self._methods = []
+ for name, method_dict in self.values.get('methods', {}).iteritems():
+ self._methods.append(Method(api, name, method_dict))
+ self.SetTemplateValue('methods', self._methods)
+ # Get sub resources
+ self._resources = []
+ for name, r_def_dict in self.values.get('resources', {}).iteritems():
+ self._resources.append(Resource(api, name, r_def_dict))
+ self.SetTemplateValue('resources', self._resources)
+
+ @property
+ def methods(self):
+ return self._methods
+
+
+class AuthScope(template_objects.CodeObject):
+ """The definition of an auth scope."""
+
+ def __init__(self, api, value, def_dict):
+ """Construct an auth scope.
+
+ Args:
+ api: (Api) The Api which owns this Property
+ value: (string) The unique identifier of this scope, often a URL
+ def_dict: (dict) The discovery dictionary for this auth scope.
+ """
+ super(AuthScope, self).__init__(def_dict, api)
+ # Strip the common prefix to get a unique identifying name
+ prefix_len = len('https://www.googleapis.com/auth/')
+ self.SetTemplateValue('name', value[prefix_len:].upper().replace('.', '_'))
+ self.SetTemplateValue('value', value)
+
+
+class Method(template_objects.CodeObject):
+ """The definition of a method."""
+
+ def __init__(self, api, name, def_dict):
+ """Construct a method.
+
+ Args:
+ api: (Api) The Api which owns this Method.
+ name: (string) The discovery name of the method.
+ def_dict: (dict) The discovery dictionary for this method.
+
+ Raises:
+ ApiException: If the httpMethod type is not one we know how to
+ handle.
+ """
+ super(Method, self).__init__(def_dict, api)
+ self.ValidateName(name)
+ class_name = api.ToClassName(name, element_type='method')
+ self.SetTemplateValue('wireName', name)
+ self.SetTemplateValue('className', class_name)
+ http_method = def_dict['httpMethod'].upper()
+ self.SetTemplateValue('httpMethod', http_method)
+ self.SetTemplateValue('rpcMethod',
+ def_dict.get('rpcMethod') or def_dict['id'])
+ rest_path = def_dict.get('path') or def_dict.get('restPath')
+ self.SetTemplateValue('restPath', rest_path)
+
+ # Figure out the input and output types and schemas for this method.
+ expected_request = self.values.get('request')
+ if expected_request:
+ # TODO(user): RequestBody is only used if the schema is anonymous.
+ # When we go to nested models, this could be a nested class off the
+ # Method, making it unique without the silly name. Same for ResponseBody.
+ request_schema = api.DataTypeFromJson(expected_request,
+ '%sRequestContent' % name,
+ parent=self)
+ self.SetTemplateValue('requestType', request_schema)
+ expected_response = self.values.get('response')
+ if expected_response:
+ response_schema = api.DataTypeFromJson(expected_response,
+ '%sResponse' % name,
+ parent=self)
+ self.SetTemplateValue('responseType', response_schema)
+ else:
+ self.SetTemplateValue('responseType', api.void_type)
+ # Make sure we can handle this method type and do any fixups.
+ if http_method in ['DELETE', 'PATCH', 'POST', 'PUT']:
+ pass
+ elif http_method == 'GET':
+ self.SetTemplateValue('requestType', None)
+ else:
+ raise ApiException('Unknown HTTP method: %s' % http_method, def_dict)
+
+ # Replace parameters dict with Parameters. We try to order them by their
+ # position in the request path so that the generated code can track the
+ # more human readable definition, rather than the order of the parameters
+ # in the discovery doc.
+ order = self.values.get('parameterOrder', [])
+ req_parameters = []
+ opt_parameters = []
+ for name, def_dict in self.values.get('parameters', {}).items():
+ # Standard params are part of the generic request class
+ if name not in ['alt']:
+ param = Parameter(api, name, def_dict, self)
+
+ # We want to push all parameters that aren't declared inside
+ # parameterOrder after those that are.
+ if param.values['wireName'] in order:
+ req_parameters.append(param)
+ else:
+ # optional parameters are appended in the order they're declared.
+ opt_parameters.append(param)
+ # pylint: disable-msg=C6402
+ req_parameters.sort(lambda x, y: cmp(order.index(x.values['wireName']),
+ order.index(y.values['wireName'])))
+ req_parameters.extend(opt_parameters)
+ self.SetTemplateValue('parameters', req_parameters)
+
+ @property
+ def parameters(self):
+ return self.values['parameters']
+
+ @property
+ def optional_parameters(self):
+ return [p for p in self.values['parameters'] if not p.required]
+
+ @property
+ def required_parameters(self):
+ return [p for p in self.values['parameters'] if p.required]
+
+ #
+ # Expose some properties with the naming convention we use in templates
+ #
+ def optionalParameters(self): # pylint: disable-msg=C6409
+ return self.optional_parameters
+
+ def requiredParameters(self): # pylint: disable-msg=C6409
+ return self.required_parameters
+
+
+class Parameter(template_objects.CodeObject):
+ """The definition of a method parameter."""
+
+ def __init__(self, api, name, def_dict, method):
+ super(Parameter, self).__init__(def_dict, api, parent=method)
+ self.requires_imports = []
+ self.ValidateName(name)
+ self.schema = api
+ self.SetTemplateValue('wireName', name)
+
+ # TODO(user): Deal with dots in names better. What we should do is:
+ # For x.y, x.z create a little class X, with members y and z. Then
+ # have the constructor method take an X.
+
+ self._repeated = self.values.get('repeated', False)
+ self._required = self.values.get('required', False)
+ self._data_type = data_types.BuiltInDataType(def_dict, api, parent=self)
+ if self._repeated:
+ self._data_type = data_types.ArrayDataType(self._data_type, parent=self)
+
+ if self.values.get('enum'):
+ enum = Enum(api,
+ name,
+ self._data_type,
+ self.values.get('enum'),
+ self.values.get('enumDescriptions'))
+ self.SetTemplateValue('enumType', enum)
+ # NOTE: If we want all languages to use templates, then we should enable
+ # the next line. For now, rf_generator does the equivalent.
+ # self.SetTemplateValue('codeType', code_type)
+
+ @property
+ def repeated(self):
+ return self._repeated
+
+ @property
+ def required(self):
+ return self._required
+
+ @property
+ def code_type(self):
+ return self._data_type.code_type
+
+ @property
+ def data_type(self):
+ return self._data_type
+
+
+class Property(template_objects.CodeObject):
+ """The definition of a schema property.
+
+ Example property in the discovery schema:
+ "id": {"type": "string"}
+ """
+
+ def __init__(self, api, schema, name, def_dict):
+ """Construct a Property.
+
+ A Property requires several elements in its template value dictionary which
+ all computed here:
+ wireName: the string which labels this Property in the wire protocol
+ dataType: the DataType of this property
+
+ Args:
+ api: (Api) The Api which owns this Property
+ schema: (Schema) the schema this Property is part of
+ name: (string) the name for this Property
+ def_dict: (dict) the JSON schema dictionary
+
+ Raises:
+ ApiException: If we have an array type without object definitions.
+ """
+ super(Property, self).__init__(def_dict, api)
+ self.ValidateName(name)
+ self.requires_imports = []
+ self.schema = schema
+ self.SetTemplateValue('wireName', name)
+ # If the schema value for this property defines a new object directly,
+ # rather than refering to another schema, we will have to create a class
+ # name for it. We create a unique name by prepending the schema we are
+ # in to the object name.
+ tentative_class_name = '%s%s' % (schema.class_name,
+ utilities.CamelCase(name))
+ if '$ref' in self.values:
+ element_type = 'object'
+ self.SetTemplateValue('type', 'object')
+ else:
+ element_type = self.values.get('type', 'string')
+ self.format_type = self.values.get('format')
+ self.object_type = None
+ self.requires_imports = []
+ if element_type == 'array':
+ self._data_type = api.DataTypeFromJson(def_dict, tentative_class_name,
+ parent=schema, wire_name=name)
+ elif element_type == 'object':
+ self._data_type = api.DataTypeFromJson(def_dict, tentative_class_name,
+ parent=schema, wire_name=name)
+ else:
+ self._data_type = data_types.BuiltInDataType(def_dict, api,
+ parent=schema)
+
+ @property
+ def code_type(self):
+ if self._language_model:
+ self._data_type.SetLanguageModel(self._language_model)
+ return self._data_type.code_type
+
+ @property
+ def codeType(self): # pylint: disable-msg=C6409
+ return self.code_type
+
+ @property
+ def data_type(self):
+ return self._data_type
+
+
+class Enum(template_objects.CodeObject):
+ """The definition of an Enum.
+
+ Example enum in discovery.
+ "enum": [
+ "@comments",
+ "@consumption",
+ "@liked",
+ "@public",
+ "@self"
+ ],
+ "enumDescriptions": [
+ "Limit to activities commented on by the user.",
+ "Limit to activities to be consumed by the user.",
+ "Limit to activities liked by the user.",
+ "Limit to public activities posted by the user.",
+ "Limit to activities posted by the user."
+ ]
+ """
+
+ def __init__(self, api, name, code_type, values, descriptions):
+ """Create an enum.
+
+ Args:
+ api: (Api) The Api which owns this Property
+ name: (str) The name for this enum.
+ code_type: (str) The underlying (language specific) type of the values.
+ values: ([str]) List of possible values.
+ descriptions: ([str]) List of value descriptions
+ """
+ super(Enum, self).__init__({}, api)
+ self.ValidateName(name)
+ self.SetTemplateValue('wireName', name)
+ self.SetTemplateValue('codeType', code_type)
+ self.SetTemplateValue('className', api.ToClassName(name))
+ names = [s.lstrip('@').upper().replace('-', '_') for s in values]
+ clean_descriptions = []
+ for desc in descriptions:
+ clean_desc = self.ValidateAndSanitizeComment(self.StripHTML(desc))
+ clean_descriptions.append(clean_desc)
+ self.SetTemplateValue('pairs', zip(names, values, clean_descriptions))
+ self.SetTemplateValue('pairs', zip(names, values, descriptions))
+
+
+def Trace(s):
+ """Logic tracer for debuging."""
+ logging.debug('>>> %s', s)
View
BIN google-apis-client-generator/src/googleapis/codegen/api.pyc
Binary file not shown.
View
332 google-apis-client-generator/src/googleapis/codegen/api_test.py
@@ -0,0 +1,332 @@
+#!/usr/bin/python2.6
+#
+# Copyright 2010 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Tests for api.py."""
+
+__author__ = 'aiuto@google.com (Tony Aiuto)'
+
+import os
+
+from google.apputils import basetest
+
+from googleapis.codegen import data_types
+from googleapis.codegen import language_model
+from googleapis.codegen.anyjson import simplejson
+from googleapis.codegen.api import Api
+from googleapis.codegen.api import ApiException
+from googleapis.codegen.api import Method
+from googleapis.codegen.api import Resource
+from googleapis.codegen.api import Schema
+
+
+class ApiTest(basetest.TestCase):
+
+ # The base discovery doc for most tests.
+ __TEST_DISCOVERY_DOC = 'sample_discovery.json'
+
+ def ApiFromDiscoveryDoc(self, path):
+ """Load a discovery doc from a file and creates a library Api.
+
+ Args:
+ path: (str) The path to the document.
+
+ Returns:
+ An Api for that document.
+ """
+
+ f = open(os.path.join(os.path.dirname(__file__), 'testdata', path))
+ discovery_doc = simplejson.loads(f.read())
+ f.close()
+ return Api(discovery_doc)
+
+ def testLazySchemaForCreation(self):
+ """Check loading schemas which are known to have a forward reference.
+
+ In the test data, "Activity" refers to "Commment", and the nature
+ (sorted) of the loading code causes "Activity" to be processed
+ before "Commment". We want to make sure that SchemaFor does the right
+ thing with the lazy creation of activity.
+ """
+ api = self.ApiFromDiscoveryDoc(self.__TEST_DISCOVERY_DOC)
+ for schema in ['Activity', 'Comment', 'ActivityObject']:
+ self.assertTrue(isinstance(api._schemas[schema], Schema))
+
+ def SchemaRefInProperties(self):
+ """Make sure that an object ref works in a schema properties list."""
+ api = self.ApiFromDiscoveryDoc(self.__TEST_DISCOVERY_DOC)
+ activity_schema = api._schemas['Activity']
+ for prop in activity_schema.values['properties']:
+ if prop.values['wireName'] == 'object':
+ self.assertTrue(prop.object_type)
+ self.assertEquals('ActivityObject',
+ prop.object_type.values['className'])
+
+ def testMakeDefaultSchemaNameFromTheDictTag(self):
+ """Use the outer tag as id for schemas which have no id in their dict."""
+ discovery_doc = simplejson.loads(
+ """
+ {
+ "name": "fake",
+ "version": "v1",
+ "schemas": {
+ "should_use_id": {
+ "id": "named",
+ "type": "object",
+ "properties": { "dummy": { "type": "string" } }
+ },
+ "unnamed": {
+ "type": "object",
+ "properties": { "dummy": { "type": "string" } }
+ }
+ },
+ "resources": {}
+ }
+ """)
+ gen = Api(discovery_doc)
+ self.assertTrue('Named' in gen._schemas)
+ self.assertTrue('Unnamed' in gen._schemas)
+
+ def testUnknownHttpMethod(self):
+ """Make sure we get an exception on unknown HTTP types."""
+ api = Api({'name': 'dummy', 'version': 'v1', 'resources': {}})
+ unused_resource = Resource(api, 'temp', {'methods': {}})
+ self.assertRaises(ApiException,
+ Method, api, 'bad', {
+ 'rpcMethod': 'rpc',
+ 'httpMethod': 'Not GET/POST/PUT/DELETE',
+ 'parameters': {}
+ })
+
+ def testRequiredParameterList(self):
+ """Make sure we are computing required parameters correctly."""
+ api = self.ApiFromDiscoveryDoc(self.__TEST_DISCOVERY_DOC)
+
+ tests_executed = 0
+
+ for resource in api.values['resources']:
+ if resource.values['wireName'] == 'activities':
+ for method in resource.values['methods']:
+ if method.required_parameters:
+ required_names = [p.values['wireName']
+ for p in method.required_parameters]
+ self.assertEquals(method.values['parameterOrder'], required_names)
+ tests_executed += 1
+
+ if method.values['wireName'] == 'get':
+ optional_names = [p.values['wireName']
+ for p in method.optional_parameters]
+ self.assertEquals(['truncateAtom', 'max-comments', 'hl',
+ 'max-liked'],
+ optional_names)
+ tests_executed += 1
+ self.assertEquals(6, tests_executed)
+
+ def testSchemaLoadingAsString(self):
+ """Test for the "schema as strings" representation."""
+ api = self.ApiFromDiscoveryDoc('latitude.v1.json')
+ self.assertEquals(4, len(api._schemas))
+
+ def testSubResources(self):
+ """Test for the APIs with subresources."""
+
+ def CountResourceTree(resource):
+ ret = 0
+ for r in resource._resources:
+ ret += 1 + CountResourceTree(r)
+ return ret
+
+ api = self.ApiFromDiscoveryDoc('moderator.v1.json')
+ top_level_resources = 0
+ total_resources = 0
+ non_method_resources = 0
+ have_sub_resources = 0
+ have_sub_resources_and_methods = 0
+ for r in api._resources:
+ top_level_resources += 1
+ total_resources += 1 + CountResourceTree(r)
+ if not r._methods:
+ non_method_resources += 1
+ if r._resources:
+ have_sub_resources += 1
+ if r._resources and r._methods:
+ have_sub_resources_and_methods += 1
+ # Hand counted 18 resources in the file.
+ self.assertEquals(18, total_resources)
+ self.assertEquals(11, top_level_resources)
+ # 4 of them have no methods, only sub resources
+ self.assertEquals(4, non_method_resources)
+ # 6 of them have sub resources.
+ self.assertEquals(6, have_sub_resources)
+ # And, of course, 2 should have both sub resources and methods
+ self.assertEquals(2, have_sub_resources_and_methods)
+
+ def testArrayOfArray(self):
+
+ class FakeLanguageModel(language_model.LanguageModel):
+ def GetCodeTypeFromDictionary(self, def_dict):
+ return def_dict.get('type')
+
+ def CodeTypeForArrayOf(self, s):
+ return 'Array[%s]' % s
+
+ discovery_doc = {
+ 'name': 'fake',
+ 'version': 'v1',
+ 'schemas': {
+ 'AdsenseReportsGenerateResponse': {
+ 'id': 'AdsenseReportsGenerateResponse',
+ 'type': 'object',
+ 'properties': {
+ 'basic': {
+ 'type': 'string'
+ },
+ 'simple_array': {
+ 'type': 'array',
+ 'items': {'type': 'string'}
+ },
+ 'array_of_arrays': {
+ 'type': 'array',
+ 'items': {'type': 'array', 'items': {'type': 'string'}}
+ }
+ }
+ }
+ },
+ 'resources': {}
+ }
+ api = Api(discovery_doc)
+ self.language_model = FakeLanguageModel()
+ api.VisitAll(lambda o: o.SetLanguageModel(self.language_model))
+ response_schema = api._schemas.get('AdsenseReportsGenerateResponse')
+ self.assertTrue(response_schema)
+ prop = [prop for prop in response_schema.values['properties']
+ if prop.values['wireName'] == 'array_of_arrays']
+ self.assertTrue(len(prop) == 1)
+ prop = prop[0]
+ self.assertEquals('Array[Array[string]]', prop.codeType)
+
+ def testDetectInvalidSchema(self):
+ base_discovery = {'name': 'fake', 'version': 'v1', 'resources': {}}
+ bad_discovery = dict(base_discovery)
+ bad_discovery['schemas'] = {
+ 'NoItemsInArray': {'id': 'noitems', 'type': 'array'}
+ }
+ self.assertRaises(ApiException, Api, bad_discovery)
+ bad_discovery['schemas'] = {
+ 'NoPropertiesInObject': {'id': 'noprops', 'type': 'object'}
+ }
+ self.assertRaises(ApiException, Api, bad_discovery)
+
+ def testUndefinedSchema(self):
+ # This should generated an empty "Bar" class.
+ discovery_doc = {
+ 'name': 'fake',
+ 'version': 'v1',
+ 'schemas': {
+ 'foo': {
+ 'id': 'foo',
+ 'type': 'object',
+ 'properties': {'basic': {'$ref': 'bar'}}
+ }
+ },
+ 'resources': {}
+ }
+ gen = Api(discovery_doc)
+ # We expect foo to be in the list because the id is 'foo'
+ self.assertTrue('foo' in gen._schemas.keys())
+ # We expect 'Foo' to be in the list because that is the class name we would
+ # create for foo
+ self.assertTrue('Foo' in gen._schemas.keys())
+ # We do not expect Bar to be in the list because we only have a ref to it
+ # but no definition.
+ self.assertFalse('Bar' in gen._schemas.keys())
+
+ def testEnums(self):
+ gen = self.ApiFromDiscoveryDoc('enums.json')
+ # Find the method with the enums
+ r1 = FindByWireName(gen.values['resources'], 'r1')
+ methods = r1.values['methods']
+ m1 = FindByWireName(methods, 'm1')
+ language = [p for p in m1.values['parameters']
+ if p.values['wireName'] == 'language'][0]
+ e = language.values['enumType']
+ for name, value, desc in e.values['pairs']:
+ self.assertTrue(name in ['ENGLISH', 'ITALIAN', 'LANG_ZH_CN',
+ 'LANG_ZH_TW'])
+ self.assertTrue(value in ['english', 'italian', 'lang_zh-CN',
+ 'lang_zh-TW'])
+ self.assertTrue(desc in ['English (US)', 'Italian',
+ 'Chinese (Simplified)', 'Chinese (Traditional)'])
+
+ def testPostVariations(self):
+ gen = self.ApiFromDiscoveryDoc('post_variations.json')
+ # Check a normal GET method to make sure it has no request and does have
+ # a response
+ r1 = FindByWireName(gen.values['resources'], 'r1')
+ methods = r1.values['methods']
+ m = FindByWireName(methods, 'get')
+ self.assertIsNone(m.values['requestType'])
+ self.assertEquals('Task', m.values['responseType'].class_name)
+ # A normal POST with both a request and response
+ m = FindByWireName(methods, 'insert')
+ self.assertEquals('Task', m.values['requestType'].class_name)
+ self.assertEquals('Task', m.values['responseType'].class_name)
+ # A POST with neither request nor response
+ m = FindByWireName(methods, 'no_request_no_response')
+ self.assertIsNone(m.values.get('requestType'))
+ self.assertTrue(isinstance(m.values.get('responseType'), data_types.Void))
+ # A POST with no request
+ m = FindByWireName(methods, 'no_request')
+ self.assertIsNone(m.values.get('requestType'))
+ self.assertEquals('Task', m.values['responseType'].class_name)
+ # A PUT with no response
+ m = FindByWireName(methods, 'no_response')
+ self.assertEquals('TaskList', m.values['requestType'].class_name)
+ self.assertTrue(isinstance(m.values.get('responseType'), data_types.Void))
+
+ def testSchemaParenting(self):
+ gen = self.ApiFromDiscoveryDoc(self.__TEST_DISCOVERY_DOC)
+ # Check that top level schemas have no parent
+ for schema in ['Activity', 'Comment']:
+ self.assertIsNone(gen._schemas[schema].parent)
+ for schema in ['PersonUrls', 'ActivityObject', 'ActivityObjectAttachments']:
+ self.assertTrue(gen._schemas[schema].parent)
+ for name, schema in gen._schemas.items():
+ if schema.parent and schema.parent != gen:
+ self.assertTrue(name.startswith(schema.parent.values['className']))
+ self.assertNotEquals(name, schema.parent.values['className'])
+
+
+def FindByWireName(list_of_resource_or_method, wire_name):
+ """Find an element in a list by its "wireName".
+
+ The "wireName" is the name of the method "on the wire", which is the raw name
+ as it appears in the JSON.
+
+ Args:
+ list_of_resource_or_method: A list of resource or methods as annotated by
+ the Api.
+ wire_name: (str): the name to fine.
+
+ Returns:
+ dict or None
+ """
+ for x in list_of_resource_or_method:
+ if x.values['wireName'] == wire_name:
+ return x
+ return None
+
+if __name__ == '__main__':
+ basetest.main()
View
164 google-apis-client-generator/src/googleapis/codegen/csharp_generator.py
@@ -0,0 +1,164 @@
+#!/usr/bin/python2.6
+#
+# Copyright 2011 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""C# library generator.
+
+This module generates C# code from a Google API discovery documents.
+"""
+
+__author__ = 'aiuto@google.com (Tony Aiuto)'
+
+from googleapis.codegen import api
+from googleapis.codegen import generator
+from googleapis.codegen import language_model
+from googleapis.codegen import template_objects
+from googleapis.codegen import utilities
+
+
+class CSharpLanguageModel(language_model.LanguageModel):
+ """A LanguageModel for C#."""
+
+ # TODO(user): Fix these 3 tables
+ _SCHEMA_TYPE_TO_CSHARP_TYPE = {
+ 'any': 'object',
+ 'boolean': 'Boolean',
+ 'integer': 'Integer',
+ 'long': 'Long',
+ 'number': 'Double',
+ 'string': 'string',
+ 'object': 'object',
+ }
+
+ _CSHARP_KEYWORDS = [
+ 'abstract', 'as', 'base', 'bool', 'break', 'byte', 'case', 'catch',
+ 'char', 'checked', 'class', 'const', 'continue', 'decimal', 'default',
+ 'delegate', 'do', 'double', 'else', 'enum', 'event', 'explicit', 'extern',
+ 'false', 'finally', 'fixed', 'float', 'for', 'foreach', 'goto', 'if',
+ 'implicit', 'in', 'int', 'interface', 'internal', 'is', 'lock', 'long',
+ 'namespace', 'new', 'null', 'object', 'operator', 'out', 'override',
+ 'params', 'private', 'protected', 'public', 'readonly', 'ref', 'return',
+ 'sbyte', 'sealed', 'short', 'sizeof', 'stackalloc', 'static', 'string',
+ 'struct', 'switch', 'this', 'throw', 'true', 'try', 'typeof', 'uint',
+ 'ulong', 'unchecked', 'unsafe', 'ushort', 'using', 'virtual', 'void',
+ 'volatile', 'while',
+ ]
+
+ # We can not create classes which match a C# keyword or built in object
+ # type.
+ RESERVED_CLASS_NAMES = _CSHARP_KEYWORDS + [
+ 'float', 'integer', 'object', 'string', 'true', 'false',
+ ]
+
+ def __init__(self):
+ super(CSharpLanguageModel, self).__init__(class_name_delimiter='.')
+
+ def GetCodeTypeFromDictionary(self, def_dict):
+ """Gets an element's data type from its JSON definition.
+
+ Overrides the default.
+
+ Args:
+ def_dict: (dict) The defintion dictionary for this type
+ Returns:
+ A name suitable for use as a C# data type
+ """
+ json_type = def_dict.get('type', 'string')
+ native_type = self._SCHEMA_TYPE_TO_CSHARP_TYPE.get(json_type)
+ # TODO(user): Handle JsonString style for string/int64, which should
+ # be a Long.
+ return native_type
+
+ def CodeTypeForArrayOf(self, type_name):
+ """Take a type name and return the syntax for an array of them.
+
+ Overrides the default.
+
+ Args:
+ type_name: (str) A type name.
+ Returns:
+ (str) A C# specific string meaning "an array of type_name".
+ """
+ return 'IList<%s>' % type_name
+
+ def CodeTypeForMapOf(self, type_name):
+ """Take a type name and return the syntax for an array of them.
+
+ Overrides the default.
+
+ Args:
+ type_name: (str) A type name.
+ Returns:
+ (str) A C# specific string meaning "a Map of string to type_name".
+ """
+ return 'IMap<string, %s>' % type_name
+
+ def ToMemberName(self, s, the_api):
+ """CamelCase a wire format name into a suitable C# variable name."""
+ camel_s = utilities.CamelCase(s)
+ if s.lower() in self.RESERVED_CLASS_NAMES:
+ # Prepend the service name
+ return '%s%s' % (the_api.values['name'], camel_s)
+ return camel_s[0].lower() + camel_s[1:]
+
+CSHARP_LANGUAGE_MODEL = CSharpLanguageModel()
+
+
+class CSharpGenerator(generator.ApiLibraryGenerator):
+ """The C# code generator."""
+
+ def __init__(self, discovery, options=dict()):
+ super(CSharpGenerator, self).__init__(
+ CSharpApi,
+ discovery,
+ language='csharp',
+ language_model=CSHARP_LANGUAGE_MODEL,
+ options=options)
+
+ def AnnotateApi(self, the_api):
+ """Overrides the default."""
+ package_path = 'Google/Apis/%s' % the_api.values['className']
+ if self._options.get('version_package'):
+ package_path = '%s/%s' % (package_path, the_api.values['versionNoDots'])
+ self._package = template_objects.Package(package_path,
+ language_model=self.language_model)
+ the_api.SetTemplateValue('package', self._package)
+ self._model_package = template_objects.Package('Data',
+ parent=self._package)
+
+
+class CSharpApi(api.Api):
+ """An Api with C# annotations."""
+
+ def __init__(self, discovery_doc, **unused_kwargs):
+ super(CSharpApi, self).__init__(discovery_doc)
+
+ def ToClassName(self, s, element_type=None): # pylint: disable-msg=W0613
+ """Convert a discovery name to a suitable C# class name.
+
+ Overrides the default.
+
+ Args:
+ s: (str) A rosy name of data element.
+ element_type: (str) The kind of element (resource|method) to name.
+ Returns:
+ A name suitable for use as a class in the generator's target language.
+ """
+
+ if s.lower() in CSharpLanguageModel.RESERVED_CLASS_NAMES:
+ # Prepend the service name
+ return '%s%s' % (utilities.CamelCase(self.values['name']),
+ utilities.CamelCase(s))
+ return utilities.CamelCase(s)
View
BIN google-apis-client-generator/src/googleapis/codegen/csharp_generator.pyc
Binary file not shown.
View
288 google-apis-client-generator/src/googleapis/codegen/data_types.py
@@ -0,0 +1,288 @@
+#!/usr/bin/python2.6
+#
+# Copyright 2010 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Template objects which represent data types.
+
+This module contains objects which usable in templates and represent data type
+idioms.
+"""
+
+__author__ = 'aiuto@google.com (Tony Aiuto)'
+
+from googleapis.codegen import template_objects
+
+
+class DataType(template_objects.CodeObject):
+ """Template object which represents a data type.
+
+ This is the base class for things which might be data type definitions, such
+ as Schema objects derived from JSONSchema blocks or primitive types.
+ """
+
+ def __init__(self, def_dict, api, parent=None, language_model=None):
+ """Construct a DataType.
+
+ Args:
+ def_dict: (dict) The discovery dictionary for this element.
+ api: (Api) The Api instance which owns this element.
+ parent: (CodeObject) The parent of this element.
+ language_model: (LanguageModel) The language we are targetting.
+ Dynamically defaults to the parent's language model.
+ """
+ super(DataType, self).__init__(def_dict, api, parent=parent,
+ language_model=language_model)
+ self.SetTemplateValue('wireName', 'DATA_TYPE_FOO')
+
+ @property
+ def code_type(self):
+ """Returns the string representing this datatype."""
+ return self.values.get('codeType', self.values.get('className'))
+
+ @property
+ def class_name(self):
+ return self.GetTemplateValue('className')
+
+ @property
+ def codeType(self): # pylint: disable-msg=C6409
+ """Expose this in template using the template naming convention.
+
+ Just redirect to code_type. Subclasses should not implement codeType
+ themselves. They should implement code_type.
+
+ Returns:
+ (str) The evaluated code type.
+ """
+ return self.code_type
+
+ @property
+ def safeClassName(self): # pylint: disable-msg=C6409
+ """Returns a language appropriate name for this object.
+
+ This property should only be used during template expansion. It is computed
+ once, using the LanguageModel in play, and then that value is cached.
+
+ Returns:
+ (str) a name for an instance of this object.
+ """
+ safe_class_name = self.GetTemplateValue('safe_class_name')
+ if not safe_class_name:
+ safe_class_name = self.values['wireName']
+ language_model = self._FindNearestLanguageModel()
+ if language_model:
+ safe_class_name = language_model.ToSafeClassName(safe_class_name,
+ self._api)
+ self.SetTemplateValue('safeClassName', safe_class_name)
+ return safe_class_name
+
+
+class BuiltInDataType(DataType):
+ """DataType which represents a "built in" data type.
+
+ BuiltIn types are those which are provided by the language or one of its
+ packages, rather than those defined by the API. A language specific
+ generater should annotate BuiltInDataType objects with a specific codeType
+ before using them to generate code.
+ """
+
+ def __init__(self, def_dict, api, parent=None):
+ """Construct a BuiltInDataType.
+
+ Args:
+ def_dict: (dict) The discovery dictionary for this element.
+ api: (Api) The Api instance which owns this element.
+ parent: (TemplateObject) The parent of this object.
+ """
+ super(BuiltInDataType, self).__init__(def_dict, api, parent=parent)
+ self.SetTemplateValue('builtIn', True)
+
+ @property
+ def code_type(self):
+ language_model = self._FindNearestLanguageModel()
+ if language_model:
+ s = language_model.GetCodeTypeFromDictionary(self._def_dict)
+ return s
+ return self.values.get('type')
+
+ @property
+ def format(self):
+ """Expose the format element from the JSON Schema type definition."""
+ return self.values.get('format')
+
+ @property
+ def type(self):
+ """Expose the type element from the JSON Schema type definition."""
+ return self.values.get('type')
+
+
+class ArrayDataType(DataType):
+ """DataType which represents a array of another DataType."""
+
+ def __init__(self, base_type, parent=None):
+ """Construct an ArrayDataType.
+
+ Args:
+ base_type: (DataType) The DataType to represent an array of.
+ parent: (TemplateObject) The parent of this object.
+ """
+ # Access to protected _language_model OK here. pylint: disable-msg=W0212
+ super(ArrayDataType, self).__init__(
+ {}, base_type.api, parent=parent,
+ language_model=base_type._language_model)
+ self._base_type = base_type
+ if isinstance(base_type, BuiltInDataType):
+ self._base_type.SetParent(self)
+ self.SetTemplateValue('arrayOf', base_type.class_name)
+ self.SetTemplateValue('className', 'Array-do not generate')
+
+ @property
+ def code_type(self):
+ """Returns the string representing the datatype of this variable.
+
+ Note: This may should only be called after the language model is set.
+
+ Returns:
+ (str) A printable representation of this data type.
+ """
+ language_model = self._FindNearestLanguageModel()
+ return language_model.CodeTypeForArrayOf(self._base_type.code_type)
+
+
+class MapDataType(DataType):
+ """DataType which represents a map of string to another DataType.
+
+ This is the base class for things which might be data type definitions, such
+ as Schema objects derived from JSONSchema blocks or primitive types.
+ """
+
+ def __init__(self, base_type, parent=None):
+ """Construct a MapDataType.
+
+ Args:
+ base_type: (DataType) The DataType to represent an map of string to.
+ parent: (TemplateObject) The parent of this object.
+ """
+ # Access to protected _language_model OK here. pylint: disable-msg=W0212
+ super(MapDataType, self).__init__({}, base_type.api, parent=parent,
+ language_model=base_type._language_model)
+ self._base_type = base_type
+ self._base_type.SetParent(self)
+ # Mark me as not generatable
+ self.SetTemplateValue('builtIn', True)
+ self.SetTemplateValue('className', 'MAP-do not generate')
+
+ @property
+ def code_type(self):
+ """Returns the string representing the datatype of this variable.
+
+ Note: This may should only be called after the language model is set.
+
+ Returns:
+ (str) A printable representation of this data type.
+ """
+ language_model = self._FindNearestLanguageModel()
+ return language_model.CodeTypeForMapOf(self._base_type.code_type)
+
+
+class SchemaReference(DataType):
+ """DataType which represents a type alias to named schema.
+
+ Provides a lazy reference to schema by name.
+ """
+
+ def __init__(self, referenced_schema, api):
+ """Construct a SchemaReference.
+
+ Args:
+ referenced_schema: (str) The name of the schema we are referencing.
+ api: (Api) The Api instance which owns this element.
+
+ Returns:
+ SchemaReference
+ """
+ super(SchemaReference, self).__init__({}, api)
+ self._referenced_schema = referenced_schema
+ # Mark me as not generatable
+ self.SetTemplateValue('builtIn', True)
+ self.SetTemplateValue('className', referenced_schema)
+
+ @property
+ def values(self):
+ """Forwards the 'values' property of this object to the referenced object.
+
+ This enables GetTemplateValue called on a Ref to effectively return
+ the value for the truly desired schema.
+
+ This may be safely called at any time, but may not produce expected
+ results until after the entire API has been parsed. In practice, this
+ means that anything done during template expansion is fine.
+
+ Returns:
+ dict of values which can be used in template.
+ """
+ s = self.api.SchemaByName(self._referenced_schema)
+ if s:
+ return s.values
+ return self._def_dict
+
+ @property
+ def code_type(self):
+ """Returns the string representing the datatype of this variable."""
+ s = self.api.SchemaByName(self._referenced_schema)
+ if s:
+ return s.code_type
+ return self._def_dict.get('codeType', self._def_dict.get('className'))
+
+ @property
+ def parent(self):
+ """Returns the parent of the schema I reference."""
+ return self.api.SchemaByName(self._referenced_schema).parent
+
+
+class Void(DataType):
+ """DataType which represents a 'void'.
+
+ Some API methods have no response. To provide some consistency in assigning
+ a responseType to these methods, we use the Void data type. When it is
+ referenced in a template, it forwards requests for it's code_type to a
+ langauge model specific emitter.
+ """
+
+ def __init__(self, api):
+ """Construct a Void.
+
+ Args:
+ api: (Api) The Api instance which owns this element. This is used for
+ a parent chain so that we can pick up the language model at template
+ generation time.
+
+ Returns:
+ Void
+ """
+ super(Void, self).__init__({}, api, parent=api)
+ # Mark me as not generatable
+ self.SetTemplateValue('builtIn', True)
+
+ @property
+ def code_type(self):
+ """Returns the string representing the datatype of this variable."""
+ language_model = self._FindNearestLanguageModel()
+ if language_model:
+ return language_model.CodeTypeForVoid()
+ return 'void'
+
+ @property
+ def fullClassName(self): # pylint: disable-msg=C6409
+ return self.code_type
View
BIN google-apis-client-generator/src/googleapis/codegen/data_types.pyc
Binary file not shown.
View
46 google-apis-client-generator/src/googleapis/codegen/data_types_test.py
@@ -0,0 +1,46 @@
+#!/usr/bin/python2.6
+#
+# Copyright 2011 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+__author__ = 'aiuto@google.com (Tony Aiuto)'
+
+from google.apputils import basetest
+from googleapis.codegen import data_types
+from googleapis.codegen import language_model
+from googleapis.codegen import template_objects
+
+
+class DataTypesTest(basetest.TestCase):
+
+ def testVoidDataTypeDefault(self):
+ api = template_objects.CodeObject({}, None)
+ void = data_types.Void(api)
+ api.SetLanguageModel(language_model.LanguageModel())
+ self.assertEquals('void', void.code_type)
+
+ def testVoidDataTypeOverride(self):
+ class FakeLM(language_model.LanguageModel):
+ def CodeTypeForVoid(self):
+ return 'the absence of all'
+
+ api = template_objects.CodeObject({}, None)
+ void = data_types.Void(api)
+ api.SetLanguageModel(FakeLM())
+ self.assertEquals('the absence of all', void.code_type)
+
+
+if __name__ == '__main__':
+ basetest.main()
View
43 google-apis-client-generator/src/googleapis/codegen/django_helpers.py
@@ -0,0 +1,43 @@
+#!/usr/bin/python2.6
+#
+# Copyright 2011 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and