mirror of
https://github.com/OMGeeky/google-apis-rs.git
synced 2026-02-23 15:49:49 +01:00
feat(pyratemp): successfully generating make deps
After minor modifications to pyratemp, it certainly does the job. What it **does NOT** do: * multiple outputs per template/command invocation * NICE embedding of code (like GSL can) It will do the job nonetheless, but mako might be worth a look
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,4 +1,5 @@
|
|||||||
target
|
target
|
||||||
|
.api.deps
|
||||||
Cargo.lock
|
Cargo.lock
|
||||||
*.sublime-workspace
|
*.sublime-workspace
|
||||||
*.xml
|
*.xml
|
||||||
|
|||||||
16
Makefile
16
Makefile
@@ -5,27 +5,29 @@ include Makefile.helpers
|
|||||||
PYTHON = python2.7
|
PYTHON = python2.7
|
||||||
TPL = etc/bin/pyratemp.py
|
TPL = etc/bin/pyratemp.py
|
||||||
|
|
||||||
|
API_DEPS_TPL = src/pyra/deps.pyra
|
||||||
|
API_MAIN_TPL = src/pyra/main.pyra
|
||||||
API_DEPS = .api.deps
|
API_DEPS = .api.deps
|
||||||
API_SHARED_INFO = ./etc/api/shared.yml
|
API_SHARED_INFO = ./etc/api/shared.yaml
|
||||||
API_JSON_FILES = $(shell find ./etc -type f -name '*-api.json')
|
API_JSON_FILES = $(shell find ./etc -type f -name '*-api.json')
|
||||||
|
|
||||||
help:
|
help:
|
||||||
$(info Programs)
|
$(info Programs)
|
||||||
$(info ----> GSL: '$(GSL)')
|
|
||||||
$(info ----> templat engine: '$(TPL)')
|
$(info ----> templat engine: '$(TPL)')
|
||||||
$(info )
|
$(info )
|
||||||
$(info Targets)
|
$(info Targets)
|
||||||
$(info help - print this help)
|
$(info help - print this help)
|
||||||
$(info api-deps - generate a file to tell make what API file dependencies will be)
|
$(info api-deps - generate a file to tell make what API file dependencies will be)
|
||||||
|
$(info help-api - show all api targets to build individually)
|
||||||
|
|
||||||
json-to-xml: $(API_XML_FILES)
|
$(API_DEPS): $(API_SHARED_INFO) $(API_DEPS_TPL)
|
||||||
$(API_DEPS): $(API_SHARED_INFO)
|
$(TPL) -f $(API_SHARED_INFO) $(API_DEPS_TPL) > $@
|
||||||
$(TPL) -f $(API_SHARED_INFO) -d DEP_FILE=$@
|
|
||||||
|
|
||||||
api-deps: $(API_DEPS)
|
api-deps: $(API_DEPS)
|
||||||
|
|
||||||
clean:
|
include $(API_DEPS)
|
||||||
|
|
||||||
|
clean: clean-api
|
||||||
-rm $(API_DEPS)
|
-rm $(API_DEPS)
|
||||||
-rm $(API_XML_FILES)
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ The license of everything not explicitly under a different license are licensed
|
|||||||
|
|
||||||
What follows is a list of other material that is licensed differently.
|
What follows is a list of other material that is licensed differently.
|
||||||
|
|
||||||
* **./etc/bin/pyratemp.py** is licensed under MIT, as shown in [the header][pyratemp-header] of the file.
|
* **./etc/bin/pyratemp.py** is licensed under MIT-like, as shown in [the header][pyratemp-header] of the file.
|
||||||
* **./etc/api/\*\*/*.json** are licensed under a [MIT-like google license][google-lic].
|
* **./etc/api/\*\*/*.json** are licensed under a [MIT-like google license][google-lic].
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
20
etc/api/shared.yaml
Normal file
20
etc/api/shared.yaml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# Contains values shared among all API implementations
|
||||||
|
directories:
|
||||||
|
# directory under which all generated sources should reside
|
||||||
|
output: ./generated
|
||||||
|
# how to get from `output` back to common library
|
||||||
|
common: ../
|
||||||
|
# where are all the API meta files
|
||||||
|
api_base: ./etc/api
|
||||||
|
api:
|
||||||
|
list:
|
||||||
|
- name: youtube
|
||||||
|
version: v3
|
||||||
|
base_path: "etc/api"
|
||||||
|
cargo:
|
||||||
|
build_version: "0.0.1"
|
||||||
|
authors:
|
||||||
|
- Sebastian Thiel <byronimo@gmail>
|
||||||
|
keywords: [google, protocol]
|
||||||
|
# All APIs should live in the same repository
|
||||||
|
repository_url: https://github.com/Byron/youtube-rs
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
# Contains values shared among all API implementations
|
|
||||||
apis:
|
|
||||||
base_path: "etc/api"
|
|
||||||
- name: youtube
|
|
||||||
version: v3
|
|
||||||
cargo:
|
|
||||||
build_version: "0.0.1"
|
|
||||||
authors:
|
|
||||||
- Sebastian Thiel <byronimo@gmail>
|
|
||||||
keywords: [google, protocol]
|
|
||||||
# All APIs should live in the same repository
|
|
||||||
repository_url: https://github.com/Byron/youtube-rs
|
|
||||||
@@ -1162,20 +1162,25 @@ class Renderer(object):
|
|||||||
output = []
|
output = []
|
||||||
do_else = False # use else/elif-branch?
|
do_else = False # use else/elif-branch?
|
||||||
|
|
||||||
|
def to_str(v):
|
||||||
|
if v is None:
|
||||||
|
return unicode()
|
||||||
|
return unicode(v)
|
||||||
|
|
||||||
if parsetree is None:
|
if parsetree is None:
|
||||||
return ""
|
return ""
|
||||||
for elem in parsetree:
|
for elem in parsetree:
|
||||||
if "str" == elem[0]:
|
if "str" == elem[0]:
|
||||||
output.append(elem[1])
|
output.append(elem[1])
|
||||||
elif "sub" == elem[0]:
|
elif "sub" == elem[0]:
|
||||||
output.append(unicode(_eval(elem[1], data)))
|
output.append(to_str(_eval(elem[1], data)))
|
||||||
elif "esc" == elem[0]:
|
elif "esc" == elem[0]:
|
||||||
obj = _eval(elem[2], data)
|
obj = _eval(elem[2], data)
|
||||||
#prevent double-escape
|
#prevent double-escape
|
||||||
if isinstance(obj, _dontescape) or isinstance(obj, TemplateBase):
|
if isinstance(obj, _dontescape) or isinstance(obj, TemplateBase):
|
||||||
output.append(unicode(obj))
|
output.append(to_str(obj))
|
||||||
else:
|
else:
|
||||||
output.append(self.escapefunc(unicode(obj), elem[1]))
|
output.append(self.escapefunc(to_str(obj), elem[1]))
|
||||||
elif "for" == elem[0]:
|
elif "for" == elem[0]:
|
||||||
do_else = True
|
do_else = True
|
||||||
(names, iterable) = elem[1:3]
|
(names, iterable) = elem[1:3]
|
||||||
@@ -1279,6 +1284,201 @@ class Template(TemplateBase):
|
|||||||
#=========================================
|
#=========================================
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class DictObject(object):
|
||||||
|
|
||||||
|
"""An object which wraps a dictionary to allow object.key access.
|
||||||
|
If the source dictionary doesn't contain any sub-dictionaries, the input
|
||||||
|
dict will be referenced. Otherwise it will be copied.
|
||||||
|
|
||||||
|
An attribute error is raised if a value is not accessible.
|
||||||
|
|
||||||
|
Please note that you cannot access dict keys which are not valid attribute names.
|
||||||
|
"""
|
||||||
|
|
||||||
|
_default_dict = dict()
|
||||||
|
_unpackable_types = (dict, tuple, list)
|
||||||
|
|
||||||
|
def __init__(self, indict=_default_dict):
|
||||||
|
"""Initialize this instance from an input dictionary. If it contains other dictionaries, those will
|
||||||
|
trigger their parent dictionaries to be copied, as they will be used as DictObject themselves and
|
||||||
|
placed in the copy accordingly.
|
||||||
|
NOTE: other DictObjects are used by reference. Generally, this type tries to perform the least
|
||||||
|
amount of copying possible."""
|
||||||
|
if indict is self._default_dict:
|
||||||
|
return
|
||||||
|
# end handle default instantiation, which makes us empty
|
||||||
|
if isinstance(indict, DictObject):
|
||||||
|
self.__dict__ = indict.__dict__
|
||||||
|
return
|
||||||
|
# END handle special case, be a reference
|
||||||
|
dct = indict
|
||||||
|
for key, val in dct.items():
|
||||||
|
if isinstance(val, self._unpackable_types):
|
||||||
|
dct = None
|
||||||
|
break
|
||||||
|
# END for each key-value pair
|
||||||
|
|
||||||
|
if dct is None:
|
||||||
|
dct = dict(indict)
|
||||||
|
|
||||||
|
def unpack(val):
|
||||||
|
"""unpack helper"""
|
||||||
|
if isinstance(val, dict):
|
||||||
|
val = DictObject(val)
|
||||||
|
elif isinstance(val, (tuple, list)):
|
||||||
|
val = type(val)(unpack(item) for item in val)
|
||||||
|
return val
|
||||||
|
# END unpack
|
||||||
|
for key, val in dct.items():
|
||||||
|
dct[key] = unpack(val)
|
||||||
|
# END for each k,v pair
|
||||||
|
# END handle recursive copy
|
||||||
|
self.__dict__ = dct
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return str(self.__dict__)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return repr(self.__dict__)
|
||||||
|
|
||||||
|
def __getattr__(self, name):
|
||||||
|
return object.__getattribute__(self, name)
|
||||||
|
|
||||||
|
def __getitem__(self, name):
|
||||||
|
try:
|
||||||
|
return getattr(self, name)
|
||||||
|
except AttributeError:
|
||||||
|
raise KeyError(name)
|
||||||
|
# end convert exception
|
||||||
|
|
||||||
|
def __setitem__(self, name, value):
|
||||||
|
setattr(self, name, value)
|
||||||
|
|
||||||
|
def __contains__(self, name):
|
||||||
|
return name in self.__dict__
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self.__dict__)
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return iter(self.__dict__)
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
"""Compares a possibly expensive comparison"""
|
||||||
|
if isinstance(other, DictObject):
|
||||||
|
# EXPENSIVE !
|
||||||
|
return self.to_dict() == other.to_dict()
|
||||||
|
elif isinstance(other, dict):
|
||||||
|
return self.to_dict() == other
|
||||||
|
# end handle type of other
|
||||||
|
return self is other
|
||||||
|
|
||||||
|
def update(self, other, **kwargs):
|
||||||
|
"""Similar to dict.update"""
|
||||||
|
items = other
|
||||||
|
if hasattr(other, 'keys'):
|
||||||
|
items = other.items()
|
||||||
|
for item_list in (items, kwargs.items()):
|
||||||
|
for k, v in item_list:
|
||||||
|
setattr(self, k, v)
|
||||||
|
# end for each item list
|
||||||
|
|
||||||
|
def to_dict(self, recursive=False):
|
||||||
|
"""@return ourselves as normal dict
|
||||||
|
@param recursive if True, a recursive copy will be returned if required."""
|
||||||
|
if recursive:
|
||||||
|
def obtain_needs_copy(value):
|
||||||
|
"""figure out if a copy is required"""
|
||||||
|
if isinstance(value, DictObject):
|
||||||
|
return True
|
||||||
|
if isinstance(value, (tuple, list, set)):
|
||||||
|
for item in value:
|
||||||
|
if obtain_needs_copy(item):
|
||||||
|
return True
|
||||||
|
# end check needs copy
|
||||||
|
# end for each item in value
|
||||||
|
# end if instance is iterable
|
||||||
|
return False
|
||||||
|
# end check needs copy
|
||||||
|
|
||||||
|
def unpack(val):
|
||||||
|
"""unpack val recursively and copy it gently"""
|
||||||
|
if isinstance(val, DictObject):
|
||||||
|
val = val.to_dict(recursive)
|
||||||
|
elif isinstance(val, (tuple, list, set)):
|
||||||
|
val = type(val)(unpack(item) for item in val)
|
||||||
|
# end handle type resolution
|
||||||
|
return val
|
||||||
|
# end unpack
|
||||||
|
|
||||||
|
needs_copy = False
|
||||||
|
for value in self.__dict__.values():
|
||||||
|
if obtain_needs_copy(value):
|
||||||
|
needs_copy = True
|
||||||
|
break
|
||||||
|
# end check value
|
||||||
|
# END for each value
|
||||||
|
|
||||||
|
if needs_copy:
|
||||||
|
new_dict = dict()
|
||||||
|
for key, val in self.__dict__.items():
|
||||||
|
new_dict[key] = unpack(val)
|
||||||
|
# END for each key, value pair
|
||||||
|
return new_dict
|
||||||
|
# else:
|
||||||
|
# just fall through and return ourselves as dictionary
|
||||||
|
|
||||||
|
# END handle recursion
|
||||||
|
return self.__dict__
|
||||||
|
|
||||||
|
def copy(self):
|
||||||
|
"""@return a (deep) copy of self"""
|
||||||
|
return type(self)(self.to_dict())
|
||||||
|
|
||||||
|
def clone(self):
|
||||||
|
"""@return a deep copy of this dict. This onyl means that the key-sets are independent. However, the
|
||||||
|
values are still shared, which matters in case of lists for instance"""
|
||||||
|
return type(self)(deepcopy(self.to_dict(recursive=True)))
|
||||||
|
|
||||||
|
def inversed_dict(self):
|
||||||
|
"""@return new dictionary which uses this dicts keys as values, and values as keys
|
||||||
|
@note duplicate values will result in just a single key, effectively drupping items.
|
||||||
|
Use this only if you have unique key-value pairs"""
|
||||||
|
return dict(list(zip(list(self.__dict__.values()), list(self.__dict__.keys()))))
|
||||||
|
|
||||||
|
def get(self, name, default=None):
|
||||||
|
"""as dict.get"""
|
||||||
|
return self.__dict__.get(name, default)
|
||||||
|
|
||||||
|
def keys(self):
|
||||||
|
"""as dict.keys"""
|
||||||
|
return list(self.__dict__.keys())
|
||||||
|
|
||||||
|
def values(self):
|
||||||
|
"""as dict.values"""
|
||||||
|
return list(self.__dict__.values())
|
||||||
|
|
||||||
|
def items(self):
|
||||||
|
"""as dict.items"""
|
||||||
|
return list(self.__dict__.items())
|
||||||
|
|
||||||
|
def iteritems(self):
|
||||||
|
"""as dict.iteritems"""
|
||||||
|
return iter(self.__dict__.items())
|
||||||
|
|
||||||
|
def pop(self, key, default=re):
|
||||||
|
"""as dict.pop"""
|
||||||
|
if default is re:
|
||||||
|
return self.__dict__.pop(key)
|
||||||
|
else:
|
||||||
|
return self.__dict__.pop(key, default)
|
||||||
|
# end assure semantics are kept
|
||||||
|
|
||||||
|
|
||||||
|
# end class DictObject
|
||||||
|
|
||||||
|
|
||||||
__version__ = "0.3.2"
|
__version__ = "0.3.2"
|
||||||
__author__ = "Roland Koebler <rk at simple-is-better dot org>"
|
__author__ = "Roland Koebler <rk at simple-is-better dot org>"
|
||||||
__license__ = """Copyright (c) 2007-2013 by Roland Koebler
|
__license__ = """Copyright (c) 2007-2013 by Roland Koebler
|
||||||
@@ -1344,6 +1544,7 @@ def load_data(datafiles):
|
|||||||
mydata = {}
|
mydata = {}
|
||||||
|
|
||||||
for filename, n, namespace in datafiles:
|
for filename, n, namespace in datafiles:
|
||||||
|
data = None
|
||||||
if filename[-5:].lower() == ".json":
|
if filename[-5:].lower() == ".json":
|
||||||
if not imported_json:
|
if not imported_json:
|
||||||
try:
|
try:
|
||||||
@@ -1352,14 +1553,9 @@ def load_data(datafiles):
|
|||||||
import json
|
import json
|
||||||
imported_json = True
|
imported_json = True
|
||||||
try:
|
try:
|
||||||
myjson = json.load(open(filename, 'r'))
|
data = json.load(open(filename, 'r'))
|
||||||
if n != -1:
|
if n != -1:
|
||||||
myjson = myjson[n]
|
data = data[n]
|
||||||
|
|
||||||
if namespace is None:
|
|
||||||
mydata.update(myjson)
|
|
||||||
else:
|
|
||||||
mydata.update({namespace: myjson})
|
|
||||||
except ValueError as err:
|
except ValueError as err:
|
||||||
raise ValueError("Invalid JSON in file '%s'. (%s)" % (filename, str(err)))
|
raise ValueError("Invalid JSON in file '%s'. (%s)" % (filename, str(err)))
|
||||||
elif filename[-5:].lower() == ".yaml":
|
elif filename[-5:].lower() == ".yaml":
|
||||||
@@ -1368,13 +1564,16 @@ def load_data(datafiles):
|
|||||||
imported_yaml = True
|
imported_yaml = True
|
||||||
if n == -1:
|
if n == -1:
|
||||||
n = 0
|
n = 0
|
||||||
myyaml = yaml.load_all(open(filename, 'r'))
|
data = yaml.load_all(open(filename, 'r'))
|
||||||
if namespace is not None:
|
data = list(data)[n]
|
||||||
mydata.update({namespace: list(myyaml)[n]})
|
|
||||||
else:
|
|
||||||
mydata.update(list(myyaml)[n])
|
|
||||||
else:
|
else:
|
||||||
raise ValueError("Invalid data-file '%s', must be .json or .yaml" % filename)
|
raise ValueError("Invalid data-file '%s', must be .json or .yaml" % filename)
|
||||||
|
assert data is not None
|
||||||
|
data = DictObject(data)
|
||||||
|
if namespace is None:
|
||||||
|
mydata.update(data)
|
||||||
|
else:
|
||||||
|
mydata.update({namespace: data})
|
||||||
return mydata
|
return mydata
|
||||||
|
|
||||||
#-----------------------------------------
|
#-----------------------------------------
|
||||||
@@ -1466,4 +1665,3 @@ if __name__ == "__main__":
|
|||||||
sys.exit(30)
|
sys.exit(30)
|
||||||
|
|
||||||
#-----------------------------------------
|
#-----------------------------------------
|
||||||
|
|
||||||
|
|||||||
24
src/pyra/deps.pyra
Normal file
24
src/pyra/deps.pyra
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
$!setvar("api_info", "[]")!$#!
|
||||||
|
|
||||||
|
<!--(for a in api.list)-->
|
||||||
|
$!setvar("gen_root", "directories.output + '/' + a.name + '_' + a.version")!$#!
|
||||||
|
$!setvar("api_name", "a.name+a.version")!$#!
|
||||||
|
$!setvar("api_clean", "api_name+'-clean'")!$#!
|
||||||
|
$!gen_root!$: $!directories.api_base!$/$!a.name!$/$!a.version!$/$!a.name!$-api.json
|
||||||
|
$!api_name!$: $!gen_root!$
|
||||||
|
$!api_clean!$:
|
||||||
|
rm -Rf $!gen_root!$
|
||||||
|
$!api_info.append((api_name, api_clean, gen_root))!$#!
|
||||||
|
|
||||||
|
<!--(end)-->
|
||||||
|
|
||||||
|
.PHONY += $(.PHONY) $!' '.join(a[0] for a in api_info)!$ $!' '.join(a[1] for a in api_info)!$
|
||||||
|
|
||||||
|
help-api:
|
||||||
|
<!--(for a in api_info)-->
|
||||||
|
$(info $!a[0]!$ - build the $!a[0]!$ api)
|
||||||
|
$(info $!a[1]!$ - clean all generated files of the $!a[0]!$ api)
|
||||||
|
<!--(end)-->
|
||||||
|
|
||||||
|
|
||||||
|
clean-api: $!' '.join(a[1] for a in api_info)!$
|
||||||
Reference in New Issue
Block a user