Commit f60ee257 authored by Dylan Trotter's avatar Dylan Trotter

Initial import.

parents
build
errors.err
Want to contribute? Great! First, read this page (including the small print at the end).
### Before you contribute
Before we can use your code, you must sign the
[Google Individual Contributor License Agreement]
(https://cla.developers.google.com/about/google-individual)
(CLA), which you can do online. The CLA is necessary mainly because you own the
copyright to your changes, even after your contribution becomes part of our
codebase, so we need your permission to use and distribute your code. We also
need to be sure of various other things—for instance that you'll tell us if you
know that your code infringes on other people's patents. You don't have to sign
the CLA until after you've submitted your code for review and a member has
approved it, but you must do it before we can put your code into our codebase.
Before you start working on a larger contribution, you should get in touch with
us first through the issue tracker with your idea so that we can help out and
possibly guide you. Coordinating up front makes it much easier to avoid
frustration later on.
### Code reviews
All submissions, including submissions by project members, require review. We
use GitHub pull requests for this purpose.
### The small print
Contributions made by corporations are covered by a different agreement than
the one above, the
[Software Grant and Corporate Contributor License Agreement]
(https://cla.developers.google.com/about/google-corporate).
This diff is collapsed.
# Copyright 2016 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.
# ------------------------------------------------------------------------------
# General setup
# ------------------------------------------------------------------------------
GO_ENV := $(shell go env GOOS GOARCH)
GOOS ?= $(word 1,$(GO_ENV))
GOARCH ?= $(word 2,$(GO_ENV))
ROOT_DIR := $(realpath .)
PKG_DIR := build/pkg/$(GOOS)_$(GOARCH)
PY_DIR := build/site-packages
export GOPATH := $(ROOT_DIR)/build
export PYTHONPATH := $(ROOT_DIR)/$(PY_DIR)
export PATH := $(ROOT_DIR)/build/bin:$(PATH)
COMPILER_BIN := build/bin/grumpc
COMPILER_SRCS := $(addprefix $(PY_DIR)/grumpy/compiler/,$(notdir $(shell find compiler -name '*.py' -not -name '*_test.py'))) $(PY_DIR)/grumpy/__init__.py
COMPILER_TESTS := $(patsubst %.py,grumpy/%,$(filter-out compiler/expr_visitor_test.py compiler/stmt_test.py,$(wildcard compiler/*_test.py)))
COMPILER_TEST_SRCS := $(patsubst %,$(PY_DIR)/%.py,$(COMPILER_TESTS))
COMPILER_SHARDED_TEST_SRCS := $(patsubst %,build/site-packages/grumpy/compiler/%,expr_visitor_test.py stmt_test.py)
COMPILER_PASS_FILES := $(patsubst %,$(PY_DIR)/%.pass,$(COMPILER_TESTS))
COMPILER_EXPR_VISITOR_PASS_FILES := $(patsubst %,build/site-packages/grumpy/compiler/expr_visitor_test.%of32.pass,$(shell seq 32))
COMPILER_STMT_PASS_FILES := $(patsubst %,build/site-packages/grumpy/compiler/stmt_test.%of16.pass,$(shell seq 16))
COMPILER_D_FILES := $(patsubst %,$(PY_DIR)/%.d,$(COMPILER_TESTS))
COMPILER := $(COMPILER_BIN) $(COMPILER_SRCS)
RUNNER_BIN := build/bin/grumprun
RUNTIME_SRCS := $(addprefix build/src/grumpy/,$(notdir $(wildcard runtime/*.go)))
RUNTIME := $(PKG_DIR)/grumpy.a
RUNTIME_PASS_FILE := $(PKG_DIR)/grumpy.pass
RUNTIME_COVER_FILE := $(PKG_DIR)/grumpy.cover
RUNNER = $(RUNNER_BIN) $(COMPILER) $(RUNTIME) $(STDLIB)
GRUMPY_STDLIB_SRCS := $(shell find lib -name '*.py')
GRUMPY_STDLIB_PACKAGES := $(foreach x,$(GRUMPY_STDLIB_SRCS),$(patsubst lib/%.py,%,$(patsubst lib/%/__init__.py,%,$(x))))
THIRD_PARTY_STDLIB_SRCS := $(wildcard third_party/stdlib/*.py)
THIRD_PARTY_STDLIB_PACKAGES := $(foreach x,$(THIRD_PARTY_STDLIB_SRCS),$(patsubst third_party/stdlib/%.py,%,$(x)))
STDLIB_SRCS := $(GRUMPY_STDLIB_SRCS) $(THIRD_PARTY_STDLIB_SRCS)
STDLIB_PACKAGES := $(GRUMPY_STDLIB_PACKAGES) $(THIRD_PARTY_STDLIB_PACKAGES)
STDLIB := $(patsubst %,$(PKG_DIR)/grumpy/lib/%.a,$(STDLIB_PACKAGES))
STDLIB_TESTS := $(patsubst lib/%.py,%,$(shell find lib -name '*_test.py'))
STDLIB_PASS_FILES := $(patsubst %,$(PKG_DIR)/grumpy/lib/%.pass,$(STDLIB_TESTS))
ACCEPT_TESTS := $(patsubst %.py,%,$(wildcard testing/*.py))
ACCEPT_PASS_FILES := $(patsubst %,build/%.pass,$(ACCEPT_TESTS))
BENCHMARKS := $(patsubst %.py,%,$(wildcard benchmarks/*.py))
BENCHMARK_BINS := $(patsubst %,build/%_benchmark,$(BENCHMARKS))
TOOL_BINS = $(patsubst %,build/bin/%,benchcmp coverparse diffrange)
all: $(COMPILER) $(RUNTIME) $(STDLIB) $(TOOL_BINS)
benchmarks: $(BENCHMARK_BINS)
clean:
@rm -rf build
# Convenient wrapper around grumprun that avoids having to set up PATH, etc.
run: $(RUNNER)
@grumprun
test: $(ACCEPT_PASS_FILES) $(COMPILER_PASS_FILES) $(COMPILER_EXPR_VISITOR_PASS_FILES) $(COMPILER_STMT_PASS_FILES) $(RUNTIME_PASS_FILE) $(STDLIB_PASS_FILES)
# Run 'make test' whenever the the source code changes.
watch:
-@$(MAKE) test
@while inotifywait -q -e modify --exclude '^\./(build|\.git)/' --recursive .; do sleep 0.2; $(MAKE) test; done
.PHONY: all benchmarks clean cover run test watch
# ------------------------------------------------------------------------------
# grumpc compiler
# ------------------------------------------------------------------------------
$(COMPILER_BIN) $(RUNNER_BIN) $(TOOL_BINS): build/bin/%: tools/%
@mkdir -p build/bin
@cp -f $< $@
$(COMPILER_SRCS) $(COMPILER_TEST_SRCS) $(COMPILER_SHARDED_TEST_SRCS): $(PY_DIR)/grumpy/%.py: %.py
@mkdir -p $(PY_DIR)/grumpy/compiler
@cp -f $< $@
$(COMPILER_PASS_FILES): %.pass: %.py $(COMPILER)
@python $< -q
@touch $@
@echo compiler/`basename $*` PASS
$(COMPILER_D_FILES): $(PY_DIR)/%.d: $(PY_DIR)/%.py $(COMPILER_SRCS)
@python -m modulefinder $< | awk '{if (match($$2, /^grumpy\>/)) { print "$(PY_DIR)/$*.pass: " substr($$3, length("$(ROOT_DIR)/") + 1) }}' > $@
-include $(COMPILER_D_FILES)
$(COMPILER_EXPR_VISITOR_PASS_FILES): build/site-packages/grumpy/compiler/expr_visitor_test.%.pass: build/site-packages/grumpy/compiler/expr_visitor_test.py $(RUNNER)
@python $< --shard=$*
@touch $@
@echo 'compiler/expr_visitor_test $* PASS'
$(COMPILER_STMT_PASS_FILES): build/site-packages/grumpy/compiler/stmt_test.%.pass: build/site-packages/grumpy/compiler/stmt_test.py $(RUNNER)
@python $< --shard=$*
@touch $@
@echo 'compiler/stmt_test $* PASS'
# ------------------------------------------------------------------------------
# Grumpy runtime
# ------------------------------------------------------------------------------
$(RUNTIME_SRCS): build/src/grumpy/%.go: runtime/%.go
@mkdir -p build/src/grumpy
@cp -f $< $@
$(RUNTIME): $(filter-out %_test.go,$(RUNTIME_SRCS))
@mkdir -p $(PKG_DIR)
@go tool compile -o $@ -p grumpy -complete -I $(PKG_DIR) -pack $^
$(RUNTIME_PASS_FILE): $(RUNTIME) $(filter %_test.go,$(RUNTIME_SRCS))
@go test grumpy
@touch $@
@echo 'runtime/grumpy PASS'
$(RUNTIME_COVER_FILE): $(RUNTIME) $(filter %_test.go,$(RUNTIME_SRCS))
@go test -coverprofile=$@ grumpy
cover: $(RUNTIME_COVER_FILE) $(TOOL_BINS)
@bash -c 'comm -12 <(coverparse $< | sed "s/^grumpy/runtime/" | sort) <(git diff --dst-prefix= $(DIFF_COMMIT) | diffrange | sort)' | sort -t':' -k1,1 -k2n,2 | sed 's/$$/: missing coverage/' | tee errors.err
# ------------------------------------------------------------------------------
# Standard library
# ------------------------------------------------------------------------------
$(STDLIB_PASS_FILES): $(PKG_DIR)/grumpy/lib/%.pass: $(PKG_DIR)/grumpy/lib/%.a
@grumprun -m `echo $* | tr / .`
@touch $@
@echo 'lib/$* PASS'
define GRUMPY_STDLIB
build/src/grumpy/lib/$(2)/module.go: $(1) $(COMPILER)
@mkdir -p build/src/grumpy/lib/$(2)
@grumpc -modname=$(notdir $(2)) $(1) > $$@
build/src/grumpy/lib/$(2)/module.d: $(1)
@mkdir -p build/src/grumpy/lib/$(2)
@python -m modulefinder -p $(ROOT_DIR)/lib:$(ROOT_DIR)/third_party/stdlib $$< | awk '{if (($$$$1 == "m" || $$$$1 == "P") && $$$$2 != "__main__" && $$$$2 != "$(2)") {gsub(/\./, "/", $$$$2); print "$(PKG_DIR)/grumpy/lib/$(2).a: $(PKG_DIR)/grumpy/lib/" $$$$2 ".a"}}' > $$@
$(PKG_DIR)/grumpy/lib/$(2).a: build/src/grumpy/lib/$(2)/module.go $(RUNTIME)
@mkdir -p $(PKG_DIR)/grumpy/lib/$(dir $(2))
@go tool compile -o $$@ -p grumpy/lib/$(2) -complete -I $(PKG_DIR) -pack $$<
-include build/src/grumpy/lib/$(2)/module.d
endef
$(eval $(foreach x,$(shell seq $(words $(STDLIB_SRCS))),$(call GRUMPY_STDLIB,$(word $(x),$(STDLIB_SRCS)),$(word $(x),$(STDLIB_PACKAGES)))))
# ------------------------------------------------------------------------------
# Acceptance tests & benchmarks
# ------------------------------------------------------------------------------
$(patsubst %_test,build/%.go,$(ACCEPT_TESTS)): build/%.go: %_test.py $(COMPILER)
@mkdir -p $(@D)
@grumpc $< > $@
$(patsubst %,build/%,$(ACCEPT_TESTS)): build/%_test: build/%.go $(RUNTIME) $(STDLIB)
@mkdir -p $(@D)
@go build -o $@ $<
$(ACCEPT_PASS_FILES): build/%_test.pass: build/%_test
@$<
@touch $@
@echo '$*_test PASS'
$(patsubst %,build/%.go,$(BENCHMARKS)): build/%.go: %.py $(COMPILER)
@mkdir -p $(@D)
@grumpc $< > $@
$(BENCHMARK_BINS): build/benchmarks/%_benchmark: build/benchmarks/%.go $(RUNTIME) $(STDLIB)
@mkdir -p $(@D)
@go build -o $@ $<
# Grumpy: Go running Python
[TOC]
## Overview
Grumpy is a Python to Go source code transcompiler and runtime that is intended
to be a near drop in replacement for CPython. The key difference is that it
compiles Python source code to Go source code which is then compiled to native
code, rather than to bytecode. This means that Grumpy has no VM. The compiled Go
source code is a series of calls to the Grumpy runtime, a Go library serving a
similar purpose to the Python C API.
## Running Grumpy Programs
### Method 1: grumprun:
The simplest way to execute a Grumpy program is to use `make run`, which wraps a
shell script called grumprun that takes Python code on stdin and builds and runs
the code under Grumpy. All of the commands below are assumed to be run from the
root directory of the Grumpy source code distribution:
```
echo "print 'hello, world'" | make run
```
### Method 2: grumpc:
For more complicated programs you'll want to compile your Python source code to
Go using grumpc (the Grumpy compiler) and then build the Go code using `go
build`. First, write a simple .py script:
```
echo 'print "hello, world"' > hello.py
```
Next, build the toolchain and export some environment variables that make the
toolchain work:
```
make
export GOPATH=$PWD/build
export PYTHONPATH=$PWD/build/site-packages
```
Finally, compile the Python script and build a binary from it:
```
tools/grumpc hello.py > hello.go
go build -o hello hello.go
```
Now execute The `./hello` binary to your heart's content.
## Developing Grumpy
There are three main components and depending on what kind of feature you're
writing, you may need to change one or more of these.
### grumpc
Grumpy converts Python programs into Go programs and grumpc is the tool
responsible for parsing Python code and generating Go code from it. grumpc is
written in Python and uses the `ast` module to accomplish parsing.
The grumpc script itself lives at tools/grumpc. It is supported by a number of
Python modules in the compiler subdir.
### Grumpy Runtime
The Go code generated by grumpc performs operations on data structures that
represent Python objects in running Grumpy programs. These data structures and
operations are defined in the `grumpy` Go library (source is in the runtime
subdir of the source distribution). This runtime is analogous to the Python C
API and many of the structures and operations defined by `grumpy` have
counterparts in CPython.
### Grumpy Standard Library
Much of the Python standard library is written in Python and so it "just works"
in Grumpy. These parts of the standard library are copied from CPython 2.7
(possibly with light modifications). For licensing reasons, these files are kept
in the third_party/stdlib subdir.
The parts of the standard library that cannot be written in pure Python, e.g.
file and directory operations, are kept in the lib subdir. In CPython these
kinds of modules are written as C extensions. In Grumpy they are written in
Python but they use native Go extensions to access facilities not otherwise
available in Python.
### Source Code Overview
- `compiler`: Python package implementating Python -> Go transcompilation logic.
- `lib`: Grumpy-specific Python standard library implementation.
- `runtime`: Go source code for the Grumpy runtime library.
- `third_party/stdlib`: Pure Python standard libraries copied from CPython.
- `tools`: Transcompilation and utility binaries.
# Copyright 2016 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.
# Copyright 2016 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.
"""Benchmarks for function calls."""
# pylint: disable=unused-argument
import weetest
def BenchmarkCallNoArgs(b):
def Foo():
pass
for _ in xrange(b.N):
Foo()
def BenchmarkCallPositionalArgs(b):
def Foo(a, b, c):
pass
for _ in xrange(b.N):
Foo(1, 2, 3)
def BenchmarkCallKeywords(b):
def Foo(a, b, c):
pass
for _ in xrange(b.N):
Foo(a=1, b=2, c=3)
def BenchmarkCallDefaults(b):
def Foo(a=1, b=2, c=3):
pass
for _ in xrange(b.N):
Foo()
def BenchmarkCallVarArgs(b):
def Foo(*args):
pass
for _ in xrange(b.N):
Foo(1, 2, 3)
def BenchmarkCallKwargs(b):
def Foo(**kwargs):
pass
for _ in xrange(b.N):
Foo(a=1, b=2, c=3)
if __name__ == '__main__':
weetest.RunBenchmarks()
# Copyright 2016 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.
"""Benchmarks for comprehensions."""
# pylint: disable=unused-argument
import weetest
def BenchmarkGeneratorExpCreate(b):
l = []
for _ in xrange(b.N):
(x for x in l) # pylint: disable=pointless-statement
def BenchmarkGeneratorExpIterate(b):
for _ in (x for x in xrange(b.N)):
pass
def BenchmarkListCompCreate(b):
for _ in xrange(b.N):
[x for x in xrange(1000)] # pylint: disable=expression-not-assigned
def BenchmarkDictCompCreate(b):
for _ in xrange(b.N):
{x: x for x in xrange(1000)} # pylint: disable=expression-not-assigned
if __name__ == '__main__':
weetest.RunBenchmarks()
# Copyright 2016 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.
"""Benchmarks for simple parallel calculations."""
import threading
import weetest
def Arithmetic(n):
return n * 3 + 2
def Fib(n):
if n < 2:
return 1
return Fib(n - 1) + Fib(n - 2)
_WORKLOADS = [
(Arithmetic, 1001),
(Fib, 10),
]
def _MakeParallelBenchmark(p, work_func, *args):
"""Create and return a benchmark that runs work_func p times in parallel."""
def Benchmark(b): # pylint: disable=missing-docstring
e = threading.Event()
def Target():
e.wait()
for _ in xrange(b.N / p):
work_func(*args)
threads = []
for _ in xrange(p):
t = threading.Thread(target=Target)
t.start()
threads.append(t)
b.ResetTimer()
e.set()
for t in threads:
t.join()
return Benchmark
def _RegisterBenchmarks():
for p in xrange(1, 13):
for work_func, arg in _WORKLOADS:
name = 'Benchmark' + work_func.__name__
if p > 1:
name += 'Parallel%s' % p
globals()[name] = _MakeParallelBenchmark(p, work_func, arg)
_RegisterBenchmarks()
if __name__ == '__main__':
weetest.RunBenchmarks()
# Copyright 2016 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.
"""Benchmarks for dictionary operations."""
# pylint: disable=pointless-statement
import weetest
def BenchmarkDictGetItem(b):
d = {42: 123}
for _ in xrange(b.N):
d[42]
def BenchmarkDictStringOnlyGetItem(b):
d = {'foo': 123}
for _ in xrange(b.N):
d['foo']
def BenchmarkDictSetItem(b):
d = {}
for _ in xrange(b.N):
d[42] = 123
def BenchmarkDictStringOnlySetItem(b):
d = {}
for _ in xrange(b.N):
d['foo'] = 123
def BenchmarkHashStrCached(b):
"""Hashes the same value repeatedly to exercise any hash caching logic."""
h = hash # Prevent builtins lookup each iteration.
for _ in xrange(b.N):
h('foobarfoobarfoobar')
if __name__ == '__main__':
weetest.RunBenchmarks()
# Copyright 2016 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.
"""Benchmarks for generator functions."""
import weetest
def BenchmarkGeneratorIterate(b):
def Gen(n):
for i in xrange(n):
yield i
for _ in Gen(b.N):
pass
def BenchmarkGeneratorCreate(b):
def Gen():
yield 1
for _ in xrange(b.N):
Gen()
if __name__ == '__main__':
weetest.RunBenchmarks()
# Copyright 2016 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.
"""Benchmarks for list operations."""
# pylint: disable=pointless-statement
import weetest
def BenchmarkListGetItem(b):
l = [1, 3, 9]
for _ in xrange(b.N):
l[2]
def BenchmarkListContains3(b):
l = [1, 3, 9]
for _ in xrange(b.N):
9 in l
def BenchmarkListContains10(b):
l = range(10)
for _ in xrange(b.N):
9 in l
if __name__ == '__main__':
weetest.RunBenchmarks()
# Copyright 2016 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.
"""Benchmarks for simple low overhead loops."""
import weetest
def BenchmarkForXRange(b):
for _ in xrange(b.N):
pass
def BenchmarkWhileCounter(b):
i = 0
while i < b.N:
i += 1
def BenchmarkWhileXRange(b):
i = iter(xrange(b.N))
try:
while True:
i.next()
except StopIteration:
pass
if __name__ == '__main__':
weetest.RunBenchmarks()
# Copyright 2016 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.
"""Benchmarks for list operations."""
# pylint: disable=pointless-statement
import weetest
def BenchmarkTupleGetItem(b):
l = (1, 3, 9)
for _ in xrange(b.N):
l[2]
def BenchmarkTupleContains3(b):
t = (1, 3, 9)
for _ in xrange(b.N):
9 in t
def BenchmarkTupleContains10(b):
t = tuple(range(10))
for _ in xrange(b.N):
9 in t
if __name__ == '__main__':
weetest.RunBenchmarks()
# Copyright 2016 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.
This diff is collapsed.
This diff is collapsed.
# coding=utf-8
# Copyright 2016 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.
"""Classes representing generated expressions."""
import abc
from grumpy.compiler import util
class GeneratedExpr(object):
"""GeneratedExpr is a generated Go expression in transcompiled output."""
__metaclass__ = abc.ABCMeta
def __enter__(self):
return self
def __exit__(self, unused_type, unused_value, unused_traceback):
self.free()
@abc.abstractproperty
def expr(self):
pass
def free(self):
pass
class GeneratedTempVar(GeneratedExpr):
"""GeneratedTempVar is an expression result stored in a temporary value."""
def __init__(self, block_, name, type_):
self.block = block_
self.name = name
self.type_ = type_
@property
def expr(self):
return self.name
def free(self):
self.block.free_temp(self)
class GeneratedLocalVar(GeneratedExpr):
"""GeneratedLocalVar is the Go local var corresponding to a Python local."""
def __init__(self, name):
self._name = name
@property
def expr(self):
return util.adjust_local_name(self._name)
class GeneratedLiteral(GeneratedExpr):
"""GeneratedLiteral is a generated literal Go expression."""
def __init__(self, expr):
self._expr = expr
@property
def expr(self):
return self._expr
nil_expr = GeneratedLiteral('nil')
This diff is collapsed.
# coding=utf-8
# Copyright 2016 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 ExprVisitor."""
import ast
import subprocess
import textwrap
import unittest
from grumpy.compiler import block
from grumpy.compiler import expr_visitor
from grumpy.compiler import shard_test
from grumpy.compiler import util
def _MakeExprTest(expr):
def Test(self):
code = 'assert ({}) == ({!r}), {!r}'.format(expr, eval(expr), expr) # pylint: disable=eval-used
self.assertEqual((0, ''), _GrumpRun(code))
return Test
def _MakeLiteralTest(lit):
def Test(self):
status, output = _GrumpRun('print repr({!r}),'.format(lit))
self.assertEqual(0, status, output)
self.assertEqual(lit, eval(output)) # pylint: disable=eval-used
return Test
def _MakeSliceTest(subscript, want):
def Test(self):
code = textwrap.dedent("""\
class Slicer(object):
def __getitem__(self, slice):
print slice
Slicer()[{}]""")
status, output = _GrumpRun(code.format(subscript))
self.assertEqual(0, status, output)
self.assertEqual(want, output.strip())
return Test
class ExprVisitorTest(unittest.TestCase):
# pylint: disable=invalid-name
def testAttribute(self):
code = textwrap.dedent("""\
class Foo(object):
bar = 42
assert Foo.bar == 42""")
self.assertEqual((0, ''), _GrumpRun(code))
testBinOpArithmeticAdd = _MakeExprTest('1 + 2')
testBinOpArithmeticAnd = _MakeExprTest('7 & 12')
testBinOpArithmeticDiv = _MakeExprTest('8 / 4')
testBinOpArithmeticFloorDiv = _MakeExprTest('8 // 4')
testBinOpArithmeticFloorDivRemainder = _MakeExprTest('5 // 2')
testBinOpArithmeticMod = _MakeExprTest('9 % 5')
testBinOpArithmeticMul = _MakeExprTest('3 * 2')
testBinOpArithmeticOr = _MakeExprTest('2 | 6')
testBinOpArithmeticSub = _MakeExprTest('10 - 3')
testBinOpArithmeticXor = _MakeExprTest('3 ^ 5')
def testBinOpNotImplemented(self):
self.assertRaisesRegexp(util.ParseError, 'binary op not implemented',
_ParseAndVisitExpr, 'x ** y')
testBoolOpTrueAndFalse = _MakeExprTest('True and False')
testBoolOpTrueAndTrue = _MakeExprTest('True and True')
testBoolOpTrueAndExpr = _MakeExprTest('True and 2 == 2')
testBoolOpTrueOrFalse = _MakeExprTest('True or False')
testBoolOpFalseOrFalse = _MakeExprTest('False or False')
testBoolOpFalseOrExpr = _MakeExprTest('False or 2 == 2')
def testCall(self):
code = textwrap.dedent("""\
def foo():
print 'bar'
foo()""")
self.assertEqual((0, 'bar\n'), _GrumpRun(code))
def testCallKeywords(self):
code = textwrap.dedent("""\
def foo(a=1, b=2):
print a, b
foo(b=3)""")
self.assertEqual((0, '1 3\n'), _GrumpRun(code))
def testCallVarArgs(self):
code = textwrap.dedent("""\
def foo(a, b):
print a, b
foo(*(123, 'abc'))""")
self.assertEqual((0, '123 abc\n'), _GrumpRun(code))
def testCallKwargs(self):
code = textwrap.dedent("""\
def foo(a, b=2):
print a, b
foo(**{'a': 4})""")
self.assertEqual((0, '4 2\n'), _GrumpRun(code))
testCompareLT = _MakeExprTest('1 < 2')
testCompareLE = _MakeExprTest('7 <= 12')
testCompareEq = _MakeExprTest('8 == 4')
testCompareNE = _MakeExprTest('9 != 5')
testCompareGE = _MakeExprTest('3 >= 2')
testCompareGT = _MakeExprTest('2 > 6')
testCompareLTLT = _MakeExprTest('3 < 6 < 9')
testCompareLTEq = _MakeExprTest('3 < 6 == 9')
testCompareLTGE = _MakeExprTest('3 < 6 >= -2')
testCompareGTEq = _MakeExprTest('88 > 12 == 12')
testCompareInStr = _MakeExprTest('"1" in "abc"')
testCompareInTuple = _MakeExprTest('1 in (1, 2, 3)')
testCompareNotInTuple = _MakeExprTest('10 < 12 not in (1, 2, 3)')
testDictEmpty = _MakeLiteralTest({})
testDictNonEmpty = _MakeLiteralTest({'foo': 42, 'bar': 43})
testDictCompFor = _MakeExprTest('{x: str(x) for x in range(3)}')
testDictCompForIf = _MakeExprTest(
'{x: 3 * x for x in range(10) if x % 3 == 0}')
testDictCompForFor = _MakeExprTest(
'{x: y for x in range(3) for y in range(x)}')
testGeneratorExpFor = _MakeExprTest('tuple(int(x) for x in "123")')
testGeneratorExpForIf = _MakeExprTest(
'tuple(x / 3 for x in range(10) if x % 3)')
testGeneratorExprForFor = _MakeExprTest(
'tuple(x + y for x in range(3) for y in range(x + 2))')
testIfExpr = _MakeExprTest('1 if True else 0')
testIfExprCompound = _MakeExprTest('42 if "ab" == "a" + "b" else 24')
testIfExprNested = _MakeExprTest(
'"foo" if "" else "bar" if 0 else "baz"')
testListEmpty = _MakeLiteralTest([])
testListNonEmpty = _MakeLiteralTest([1, 2])
testListCompFor = _MakeExprTest('[int(x) for x in "123"]')
testListCompForIf = _MakeExprTest('[x / 3 for x in range(10) if x % 3]')
testListCompForFor = _MakeExprTest(
'[x + y for x in range(3) for y in range(x + 2)]')
def testNameGlobal(self):
code = textwrap.dedent("""\
foo = 123
assert foo == 123""")
self.assertEqual((0, ''), _GrumpRun(code))
def testNameLocal(self):
code = textwrap.dedent("""\
def foo():
bar = 'abc'
assert bar == 'abc'
foo()""")
self.assertEqual((0, ''), _GrumpRun(code))
testNumInt = _MakeLiteralTest(42)
testNumLong = _MakeLiteralTest(42L)
testNumIntLarge = _MakeLiteralTest(12345678901234567890)
testNumFloat = _MakeLiteralTest(102.1)
testNumFloatNoDecimal = _MakeLiteralTest(5.)
testNumFloatOnlyDecimal = _MakeLiteralTest(.5)
testNumFloatSci = _MakeLiteralTest(1e6)
testNumFloatSciCap = _MakeLiteralTest(1E6)
testNumFloatSciCapPlus = _MakeLiteralTest(1E+6)
testNumFloatSciMinus = _MakeLiteralTest(1e-6)
testSubscriptDictStr = _MakeExprTest('{"foo": 42}["foo"]')
testSubscriptListInt = _MakeExprTest('[1, 2, 3][2]')
testSubscriptTupleSliceStart = _MakeExprTest('(1, 2, 3)[2:]')
testSubscriptTupleSliceStartStop = _MakeExprTest('(1, 2, 3)[10:11]')
testSubscriptTupleSliceStartStep = _MakeExprTest('(1, 2, 3, 4, 5, 6)[-2::-2]')
testSubscriptStartStop = _MakeSliceTest('2:3', 'slice(2, 3, None)')
testSubscriptMultiDim = _MakeSliceTest('1,2,3', '(1, 2, 3)')
testSubscriptStartStopObjects = _MakeSliceTest(
'True:False', 'slice(True, False, None)')
testSubscriptMultiDimSlice = _MakeSliceTest(
"'foo','bar':'baz':'qux'", "('foo', slice('bar', 'baz', 'qux'))")
testStrEmpty = _MakeLiteralTest('')
testStrAscii = _MakeLiteralTest('abc')
testStrUtf8 = _MakeLiteralTest('\tfoo\n\xcf\x80')
testStrQuoted = _MakeLiteralTest('"foo"')
testStrUtf16 = _MakeLiteralTest(u'\u0432\u043e\u043b\u043d')
testTupleEmpty = _MakeLiteralTest(())
testTupleNonEmpty = _MakeLiteralTest((1, 2, 3))
testUnaryOpNot = _MakeExprTest('not True')
testUnaryOpInvert = _MakeExprTest('~4')
def testUnaryOpNotImplemented(self):
self.assertRaisesRegexp(util.ParseError, 'unary op not implemented',
_ParseAndVisitExpr, '-foo')
def _MakeModuleBlock():
return block.ModuleBlock('__main__', 'grumpy', 'grumpy/lib', '<test>', [])
def _ParseExpr(expr):
return ast.parse(expr).body[0].value
def _ParseAndVisitExpr(expr):
writer = util.Writer()
visitor = expr_visitor.ExprVisitor(_MakeModuleBlock(), writer)
visitor.visit(_ParseExpr(expr))
return writer.out.getvalue()
def _GrumpRun(cmd):
p = subprocess.Popen(['grumprun'], stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
out, _ = p.communicate(cmd)
return p.returncode, out
if __name__ == '__main__':
shard_test.main()
# Copyright 2016 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.
"""Wrapper for unit tests that loads a subset of all test methods."""
import argparse
import random
import re
import sys
import unittest
class _ShardAction(argparse.Action):
def __call__(self, parser, args, values, option_string=None):
match = re.match(r'(\d+)of(\d+)$', values)
if not match:
raise argparse.ArgumentError(self, 'bad shard spec: {}'.format(values))
shard = int(match.group(1))
count = int(match.group(2))
if shard < 1 or count < 1 or shard > count:
raise argparse.ArgumentError(self, 'bad shard spec: {}'.format(values))
setattr(args, self.dest, (shard, count))
class _ShardTestLoader(unittest.TestLoader):
def __init__(self, shard, count):
super(_ShardTestLoader, self).__init__()
self.shard = shard
self.count = count
def getTestCaseNames(self, test_case_cls):
names = super(_ShardTestLoader, self).getTestCaseNames(test_case_cls)
state = random.getstate()
random.seed(self.count)
random.shuffle(names)
random.setstate(state)
n = len(names)
# self.shard is one-based.
return names[(self.shard - 1) * n / self.count:self.shard * n / self.count]
class _ShardTestRunner(object):
def run(self, test):
result = unittest.TestResult()
unittest.registerResult(result)
test(result)
for kind, errors in [('FAIL', result.failures), ('ERROR', result.errors)]:
for test, err in errors:
sys.stderr.write('{} {}\n{}'.format(test, kind, err))
return result
def main():
parser = argparse.ArgumentParser()
parser.add_argument('--shard', default=(1, 1), action=_ShardAction)
parser.add_argument('unittest_args', nargs='*')
args = parser.parse_args()
unittest.main(argv=[sys.argv[0]] + args.unittest_args,
testLoader=_ShardTestLoader(*args.shard),
testRunner=_ShardTestRunner)
This diff is collapsed.
This diff is collapsed.
# coding=utf-8
# Copyright 2016 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.
"""Utilities for generating Go code."""
import contextlib
import cStringIO
import string
import textwrap
_SIMPLE_CHARS = set(string.digits + string.letters + string.punctuation)
_ESCAPES = {'\0': r'\0', '\t': r'\t', '\r': r'\r', '\n': r'\n', '"': r'\"'}
class ParseError(Exception):
def __init__(self, node, msg):
if hasattr(node, 'lineno'):
msg = 'line {}: {}'.format(node.lineno, msg)
super(ParseError, self).__init__(msg)
class Writer(object):
"""Utility class for writing blocks of Go code to a file-like object."""
def __init__(self, out=None):
self.out = out or cStringIO.StringIO()
self.indent_level = 0
@contextlib.contextmanager
def indent_block(self, n=1):
"""A context manager that indents by n on entry and dedents on exit."""
self.indent(n)
yield
self.dedent(n)
def write(self, output):
for line in output.split('\n'):
if line:
self.out.write('\t' * self.indent_level)
self.out.write(line)
self.out.write('\n')
def write_block(self, block_, body):
"""Outputs the boilerplate necessary for code blocks like functions.
Args:
block_: The Block object representing the code block.
body: String containing Go code making up the body of the code block.
"""
self.write('var πE *πg.BaseException\n_ = πE')
self.write_temp_decls(block_)
# Write the function body.
self.write_tmpl('πBlock := πg.NewBlock($name, $filename, '
'func(πF *πg.Frame, πSent *πg.Object) '
'(*πg.Object, *πg.BaseException) {',
name=go_str(block_.name),
filename=go_str(block_.filename))
with self.indent_block():
self.write('switch πF.State() {')
self.write('case 0:')
for checkpoint in block_.checkpoints:
self.write_tmpl('case $state: goto Label$state', state=checkpoint)
self.write('default: panic("unexpected function state")')
self.write('}')
# Assume that body is aligned with goto labels.
self.write(body)
with self.indent_block():
if block_.is_generator:
self.write('return nil, πF.Raise('
'πg.StopIterationType.ToObject(), nil, nil)')
else:
self.write('return πg.None, nil')
self.write('})')
def write_import_block(self, imports):
if not imports:
return
self.write('import (')
with self.indent_block():
for name in sorted(imports):
self.write('{} "{}"'.format(imports[name].alias, name))
self.write(')')
def write_label(self, label):
with self.indent_block(-1):
self.write('Label{}:'.format(label))
def write_py_context(self, lineno, line):
self.write_tmpl('// line $lineno: $line', lineno=lineno, line=line)
def write_tmpl(self, tmpl, **kwargs):
self.write(string.Template(tmpl).substitute(kwargs))
def write_checked_call2(self, result, call, *args, **kwargs):
return self.write_tmpl(textwrap.dedent("""\
if $result, πE = $call; πE != nil {
\treturn nil, πE
}"""), result=result.name, call=call.format(*args, **kwargs))
def write_checked_call1(self, call, *args, **kwargs):
return self.write_tmpl(textwrap.dedent("""\
if raised := $call; raised != nil {
\treturn nil, raised
}"""), call=call.format(*args, **kwargs))
def write_temp_decls(self, block_):
all_temps = block_.free_temps | block_.used_temps
for temp in sorted(all_temps, key=lambda t: t.name):
self.write('var {0} {1}\n_ = {0}'.format(temp.name, temp.type_))
def indent(self, n=1):
self.indent_level += n
def dedent(self, n=1):
self.indent_level -= n
def go_str(value):
"""Returns value as a valid Go string literal."""
io = cStringIO.StringIO()
io.write('"')
for c in value:
if c in _ESCAPES:
io.write(_ESCAPES[c])
elif c in _SIMPLE_CHARS:
io.write(c)
else:
io.write(r'\x{:02x}'.format(ord(c)))
io.write('"')
return io.getvalue()
def adjust_local_name(name):
"""Returns a Go identifier for the given Python variable name."""
return 'µ' + name
# coding=utf-8
# Copyright 2016 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 Writer and other utils."""
import unittest
from grumpy.compiler import block
from grumpy.compiler import util
class WriterTest(unittest.TestCase):
def testIndentBlock(self):
writer = util.Writer()
writer.write('foo')
with writer.indent_block(n=2):
writer.write('bar')
writer.write('baz')
self.assertEqual(writer.out.getvalue(), 'foo\n\t\tbar\nbaz\n')
def testWriteBlock(self):
writer = util.Writer()
writer.write_block(block.ModuleBlock(
'__main__', 'grumpy', 'grumpy/lib', '<test>', []), 'BODY')
output = writer.out.getvalue()
dispatch = 'switch πF.State() {\n\tcase 0:\n\tdefault: panic'
self.assertIn(dispatch, output)
self.assertIn('return πg.None, nil\n}', output)
def testWriteImportBlockEmptyImports(self):
writer = util.Writer()
writer.write_import_block({})
self.assertEqual(writer.out.getvalue(), '')
def testWriteImportBlockImportsSorted(self):
writer = util.Writer()
imports = {name: block.Package(name) for name in ('a', 'b', 'c')}
writer.write_import_block(imports)
self.assertEqual(writer.out.getvalue(),
'import (\n\tπ_a "a"\n\tπ_b "b"\n\tπ_c "c"\n)\n')
def testWriteMultiline(self):
writer = util.Writer()
writer.indent(2)
writer.write('foo\nbar\nbaz\n')
self.assertEqual(writer.out.getvalue(), '\t\tfoo\n\t\tbar\n\t\tbaz\n')
def testWritePyContext(self):
writer = util.Writer()
writer.write_py_context(12, 'print "foo"')
self.assertEqual(writer.out.getvalue(), '// line 12: print "foo"\n')
def testWriteSkipBlankLine(self):
writer = util.Writer()
writer.write('foo\n\nbar')
self.assertEqual(writer.out.getvalue(), 'foo\nbar\n')
def testWriteTmpl(self):
writer = util.Writer()
writer.write_tmpl('$foo, $bar\n$baz', foo=1, bar=2, baz=3)
self.assertEqual(writer.out.getvalue(), '1, 2\n3\n')
def testIndent(self):
writer = util.Writer()
writer.indent(2)
writer.write('foo')
self.assertEqual(writer.out.getvalue(), '\t\tfoo\n')
def testDedent(self):
writer = util.Writer()
writer.indent(4)
writer.dedent(3)
writer.write('foo')
self.assertEqual(writer.out.getvalue(), '\tfoo\n')
if __name__ == '__main__':
unittest.main()
This directory contains Grumpy Python standard library code. It is only expected
to run under Grumpy, not CPython.
# Copyright 2016 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.
"""Built-in Python identifiers."""
# pylint: disable=invalid-name
from __go__.grumpy import Builtins
for k, v in Builtins.iteritems():
globals()[k] = v
# Copyright 2016 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.
"""Built-in exception classes."""
from __go__.grumpy import ExceptionTypes
g = globals()
for t in ExceptionTypes:
g[t.__name__] = t
# Copyright 2016 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.
"""Utilities for iterating over containers."""
import sys
class islice(object): # pylint: disable=invalid-name
"""Iterator that returns sliced elements from the iterable."""
def __init__(self, iterable, *args):
s = slice(*args)
self._range = iter(xrange(s.start or 0, s.stop or sys.maxint, s.step or 1))
self._iter = iter(iterable)
self._i = 0
def __iter__(self):
return self
def next(self):
nexti = next(self._range)
while True:
el = next(self._iter)
i = self._i
self._i += 1
if i == nexti:
return el
# Copyright 2016 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.
import itertools
import weetest
def TestISlice():
r = range(10)
cases = [
((r, 5), (0, 1, 2, 3, 4)),
((r, 25, 30), ()),
((r, 1, None, 3), (1, 4, 7)),
]
for args, want in cases:
got = tuple(itertools.islice(*args))
assert got == want, 'tuple(islice%s) == %s, want %s' % (args, got, want)
if __name__ == '__main__':
weetest.RunTests()
# Copyright 2016 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.
"""Miscellaneous operating system interfaces."""
# pylint: disable=g-multiple-import
from os import path
import stat as stat_module
import sys
from __go__.os import Chmod, Environ, Remove, Stat
from __go__.path.filepath import Separator
from __go__.grumpy import NewFileFromFD
from __go__.syscall import Close, SYS_FCNTL, Syscall, F_GETFD
sep = chr(Separator)
environ = {}
for var in Environ():
k, v = var.split('=', 1)
environ[k] = v
def chmod(filepath, mode):
# TODO: Support mode flags other than perms.
err = Chmod(filepath, stat(filepath).st_mode & ~0o777 | mode & 0o777)
if err:
raise OSError(err.Error())
def close(fd):
err = Close(fd)
if err:
raise OSError(err.Error())
def fdopen(fd, mode='r'): # pylint: disable=unused-argument
# Ensure this is a valid file descriptor to match CPython behavior.
_, _, err = Syscall(SYS_FCNTL, fd, F_GETFD, 0)
if err:
raise OSError(err.Error())
return NewFileFromFD(fd)
def remove(filepath):
if stat_module.S_ISDIR(stat(filepath).st_mode):
raise OSError('Operation not permitted: ' + filepath)
err = Remove(filepath)
if err:
raise OSError(err.Error())
def rmdir(filepath):
if not stat_module.S_ISDIR(stat(filepath).st_mode):
raise OSError('Operation not permitted: ' + filepath)
err = Remove(filepath)
if err:
raise OSError(err.Error())
class StatResult(object):
def __init__(self, mode):
self.st_mode = mode
def stat(filepath):
info, err = Stat(filepath)
if err:
raise OSError(err.Error())
# TODO: This is an incomplete mode flag. It should include S_IFDIR, etc.
return StatResult(info.Mode())
# Copyright 2016 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.
""""Utilities for manipulating and inspecting OS paths."""
from __go__.path.filepath import Clean as normpath, IsAbs as isabs, Join # pylint: disable=g-multiple-import,unused-import
# NOTE(compatibility): This method uses Go's filepath.Join() method which
# implicitly normalizes the resulting path (pruning extra /, .., etc.) The usual
# CPython behavior is to leave all the cruft. This deviation is reasonable
# because a) result paths will point to the same files and b) one cannot assume
# much about the results of join anyway since it's platform dependent.
def join(*paths):
if not paths:
raise TypeError('join() takes at least 1 argument (0 given)')
parts = []
for p in paths:
if isabs(p):
parts = [p]
else:
parts.append(p)
result = Join(*parts)
if result and not paths[-1]:
result += '/'
return result
# Copyright 2016 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.
# pylint: disable=g-import-not-at-top
import os.path
path = os.path
import weetest
def TestIsAbs():
assert path.isabs('/abc')
assert not path.isabs('abc/123')
def TestJoin():
assert path.join('') == ''
assert path.join('', '') == ''
assert path.join('abc') == 'abc'
assert path.join('abc', '') == 'abc/'
assert path.join('abc', '', '') == 'abc/'
assert path.join('abc', '', '123') == 'abc/123'
assert path.normpath(path.join('abc', '.', '123')) == 'abc/123'
assert path.normpath(path.join('abc', '..', '123')) == '123'
assert path.join('/abc', '123') == '/abc/123'
assert path.join('abc', '/123') == '/123'
assert path.join('abc/', '123') == 'abc/123'
assert path.join('abc', 'x/y/z') == 'abc/x/y/z'
assert path.join('abc', 'x', 'y', 'z') == 'abc/x/y/z'
def TestNormPath():
assert path.normpath('abc/') == 'abc'
assert path.normpath('/a//b') == '/a/b'
assert path.normpath('abc/../123') == '123'
assert path.normpath('../abc/123') == '../abc/123'
assert path.normpath('x/y/./z') == 'x/y/z'
if __name__ == '__main__':
weetest.RunTests()
# Copyright 2016 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.
import os
import stat
import tempfile
import weetest
def TestChmod():
fd, path = tempfile.mkstemp()
os.close(fd)
os.chmod(path, 0o644)
mode = os.stat(path).st_mode & 0o777
os.remove(path)
assert mode == 0o644
def TestChmodOSError():
tempdir = tempfile.mkdtemp()
try:
os.chmod(tempdir + '/DoesNotExist', 0o644)
except OSError:
pass
else:
raise AssertionError
def TestClose():
fd, _ = tempfile.mkstemp()
os.close(fd)
try:
os.fdopen(fd)
except OSError:
pass
else:
raise AssertionError
def TestCloseOSError():
fd, _ = tempfile.mkstemp()
os.close(fd)
try:
os.close(fd)
except OSError:
pass
else:
raise AssertionError
def TestEnviron():
assert 'HOME' in os.environ
def TestFDOpen():
fd, path = tempfile.mkstemp()
f = os.fdopen(fd, 'w')
f.write('foobar')
f.close()
f = open(path)
contents = f.read()
f.close()
assert contents == 'foobar', contents
def TestFDOpenOSError():
fd, _ = tempfile.mkstemp()
os.close(fd)
try:
os.fdopen(fd)
except OSError:
pass
else:
raise AssertionError
def TestRemove():
fd, path = tempfile.mkstemp()
os.close(fd)
os.stat(path)
os.remove(path)
try:
os.stat(path)
except OSError:
pass
else:
raise AssertionError
def TestRemoveNoExist():
path = tempfile.mkdtemp()
try:
os.remove(path + '/nonexistent')
except OSError:
pass
else:
raise AssertionError
finally:
os.rmdir(path)
def TestRemoveDir():
path = tempfile.mkdtemp()
try:
os.remove(path)
except OSError:
pass
else:
raise AssertionError
finally:
os.rmdir(path)
def TestRmDir():
path = tempfile.mkdtemp()
assert stat.S_ISDIR(os.stat(path).st_mode)
os.rmdir(path)
try:
os.stat(path)
except OSError:
pass
else:
raise AssertionError
def TestRmDirNoExist():
path = tempfile.mkdtemp()
try:
os.rmdir(path + '/nonexistent')
except OSError:
pass
else:
raise AssertionError
finally:
os.rmdir(path)
def TestRmDirFile():
fd, path = tempfile.mkstemp()
os.close(fd)
try:
os.rmdir(path)
except OSError:
pass
else:
raise AssertionError
finally:
os.remove(path)
def TestStatFile():
fd, path = tempfile.mkstemp()
os.close(fd)
mode = os.stat(path).st_mode
os.remove(path)
assert not stat.S_ISDIR(mode)
assert stat.S_IMODE(mode) == 0o600
def TestStatDir():
path = tempfile.mkdtemp()
mode = os.stat(path).st_mode
os.rmdir(path)
assert stat.S_ISDIR(mode)
assert stat.S_IMODE(mode) == 0o700
def TestStatNoExist():
path = tempfile.mkdtemp()
try:
os.stat(path + '/nonexistent')
except OSError:
pass
else:
raise AssertionError
finally:
os.rmdir(path)
if __name__ == '__main__':
weetest.RunTests()
# Copyright 2016 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.
# Copyright 2016 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.
"""Interpreting stat() results."""
# pylint: disable=g-multiple-import
from __go__.os import ModeDir, ModePerm
def S_ISDIR(mode): # pylint: disable=invalid-name
return mode & ModeDir
def S_IMODE(mode): # pylint: disable=invalid-name
return mode & ModePerm
# Copyright 2016 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.
"""System-specific parameters and functions."""
from __go__.os import Args
from __go__.grumpy import SysModules, MaxInt # pylint: disable=g-multiple-import
from __go__.runtime import Version
argv = []
for arg in Args:
argv.append(arg)
goversion = Version()
maxint = MaxInt
modules = SysModules
py3kwarning = False
warnoptions = []
class _Flags(object):
"""Container class for sys.flags."""
debug = 0
py3k_warning = 0
division_warning = 0
division_new = 0
inspect = 0
interactive = 0
optimize = 0
dont_write_bytecode = 0
no_user_site = 0
no_site = 0
ignore_environment = 0
tabcheck = 0
verbose = 0
unicode = 0
bytes_warning = 0
hash_randomization = 0
flags = _Flags()
def exc_info():
e, tb = __frame__().__exc_info__() # pylint: disable=undefined-variable
t = None
if e:
t = type(e)
return t, e, tb
def exit(code=None): # pylint: disable=redefined-builtin
raise SystemExit(code)
# Copyright 2016 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.
# pylint: disable=bare-except
import sys
import types
import weetest
def TestArgv():
assert sys.argv
def TestMaxInt():
assert sys.maxint > 2000000000
def TestSysModules():
assert sys.modules['sys'] is not None
def TestExcInfoNoException():
assert sys.exc_info() == (None, None, None)
def TestExcInfoWithException():
try:
raise RuntimeError
except:
t, e, tb = sys.exc_info()
else:
assert False
assert t is RuntimeError
assert isinstance(e, t)
assert isinstance(tb, types.TracebackType)
def TestExitEmpty():
try:
sys.exit()
except SystemExit as e:
assert e.code == None, e.code # pylint: disable=g-equals-none
except:
assert False
def TestExitCode():
try:
sys.exit(42)
except SystemExit as e:
assert e.code == 42, e.code
except:
assert False
def TestExitInvalidArgs():
try:
sys.exit(1, 2, 3)
except TypeError as e:
assert str(e) == 'exit() takes 1 arguments (3 given)', str(e)
except:
assert False
if __name__ == '__main__':
# This call will incidentally test sys.exit().
weetest.RunTests()
# Copyright 2016 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.
"""Generate temporary files and directories."""
# pylint: disable=g-multiple-import
from __go__.io.ioutil import TempDir, TempFile
from __go__.syscall import Dup
# pylint: disable=redefined-builtin
def mkdtemp(suffix='', prefix='tmp', dir=None):
if dir is None:
dir = ''
# TODO: Make suffix actually follow the rest of the filename.
path, err = TempDir(dir, prefix + '-' + suffix)
if err:
raise OSError(err.Error())
return path
def mkstemp(suffix='', prefix='tmp', dir=None, text=False):
if text:
raise NotImplementedError
if dir is None:
dir = ''
# TODO: Make suffix actually follow the rest of the filename.
f, err = TempFile(dir, prefix + '-' + suffix)
if err:
raise OSError(err.Error())
try:
fd, err = Dup(f.Fd())
if err:
raise OSError(err.Error())
return fd, f.Name()
finally:
f.Close()
# Copyright 2016 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.
import os
import stat
import tempfile
import weetest
def TestMkdTemp():
path = tempfile.mkdtemp()
mode = os.stat(path).st_mode
os.rmdir(path)
assert stat.S_ISDIR(mode), mode
assert stat.S_IMODE(mode) == 0o700, mode
def TestMkdTempDir():
tempdir = tempfile.mkdtemp()
path = tempfile.mkdtemp(dir=tempdir)
os.rmdir(path)
os.rmdir(tempdir)
assert path.startswith(tempdir)
def TestMkdTempOSError():
tempdir = tempfile.mkdtemp()
os.chmod(tempdir, 0o500)
try:
tempfile.mkdtemp(dir=tempdir)
except OSError:
pass
else:
raise AssertionError
os.rmdir(tempdir)
def TestMkdTempPrefixSuffix():
path = tempfile.mkdtemp(prefix='foo', suffix='bar')
os.rmdir(path)
assert 'foo' in path
assert 'bar' in path
# TODO: assert path.endswith('bar')
def TestMksTemp():
fd, path = tempfile.mkstemp()
f = os.fdopen(fd, 'w')
f.write('foobar')
f.close()
f = open(path)
contents = f.read()
f.close()
os.remove(path)
assert contents == 'foobar', contents
def TestMksTempDir():
tempdir = tempfile.mkdtemp()
fd, path = tempfile.mkstemp(dir=tempdir)
os.close(fd)
os.remove(path)
os.rmdir(tempdir)
assert path.startswith(tempdir)
def TestMksTempOSError():
tempdir = tempfile.mkdtemp()
os.chmod(tempdir, 0o500)
try:
tempfile.mkstemp(dir=tempdir)
except OSError:
pass
else:
raise AssertionError
os.rmdir(tempdir)
def TestMksTempPerms():
fd, path = tempfile.mkstemp()
os.close(fd)
mode = os.stat(path).st_mode
os.remove(path)
assert stat.S_IMODE(mode) == 0o600, mode
def TestMksTempPrefixSuffix():
fd, path = tempfile.mkstemp(prefix='foo', suffix='bar')
os.close(fd)
os.remove(path)
assert 'foo' in path
assert 'bar' in path
# TODO: assert path.endswith('bar')
if __name__ == '__main__':
weetest.RunTests()
# Copyright 2016 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.
"""Concurrent programming functionality."""
from __go__.grumpy import StartThread
from __go__.sync import NewCond, type_Mutex as Mutex
class Event(object):
"""Event is a way to signal conditions between threads."""
def __init__(self):
self._mutex = Mutex.new()
self._cond = NewCond(self._mutex)
self._is_set = False
def set(self):
self._mutex.Lock()
try:
self._is_set = True
finally:
self._mutex.Unlock()
self._cond.Broadcast()
# TODO: Support timeout param.
def wait(self):
self._mutex.Lock()
try:
while not self._is_set:
self._cond.Wait()
finally:
self._mutex.Unlock()
return True
class Thread(object):
"""Thread is an activity to be executed concurrently."""
def __init__(self, target=None, args=()):
self._target = target
self._args = args
self._event = Event()
def run(self):
self._target(*self._args)
def start(self):
StartThread(self._run)
# TODO: Support timeout param.
def join(self):
self._event.wait()
def _run(self):
try:
self.run()
finally:
self._event.set()
# Copyright 2016 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.
import threading
import time
import weetest
def TestEvent():
e = threading.Event()
target_result = []
x = 'not ready'
def Target():
e.wait()
target_result.append(x)
t = threading.Thread(target=Target)
t.start()
# Sleeping gives us some confidence that t had the opportunity to wait on e
# and that if e is broken (e.g. wait() returned immediately) then the test
# will fail below.
time.sleep(0.1)
x = 'ready'
e.set()
t.join()
assert target_result == ['ready']
def TestThread():
ran = []
def Target():
ran.append(True)
t = threading.Thread(target=Target)
t.start()
t.join()
assert ran
def TestThreadArgs():
target_args = []
def Target(*args):
target_args.append(args)
t = threading.Thread(target=Target, args=('foo', 42))
t.start()
t.join()
assert target_args == [('foo', 42)]
if __name__ == '__main__':
weetest.RunTests()
# Copyright 2016 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.
"""Time access and conversions."""
from __go__.time import Now, Second, Sleep # pylint: disable=g-multiple-import
def sleep(secs):
Sleep(secs * Second)
def time():
return float(Now().UnixNano()) / Second
# Copyright 2016 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.
import time
assert time.time() > 1000000000
assert time.time() < 3000000000
# Copyright 2016 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.
"""Print or retrieve a stack traceback."""
def print_exc(e):
print str(e)
# Copyright 2016 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.
import types
from __go__.grumpy import (FunctionType, MethodType, ModuleType, StrType, # pylint: disable=g-multiple-import
TracebackType, TypeType)
# Verify a sample of all types as a sanity check.
assert types.FunctionType is FunctionType
assert types.MethodType is MethodType
assert types.UnboundMethodType is MethodType
assert types.ModuleType is ModuleType
assert types.StringType is StrType
assert types.TracebackType is TracebackType
assert types.TypeType is TypeType
# Copyright 2016 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.
"""Weak reference functionality."""
from __go__.grumpy import WeakRefType as ref # pylint: disable=unused-import
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
// Copyright 2016 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.
package grumpy
import (
"testing"
)
func TestNormalizeEncoding(t *testing.T) {
cases := []struct {
encoding string
want string
}{
{"utf8", "utf8"},
{"UTF-16 ", "utf16"},
{" __Ascii__", "ascii"},
{"utf@#(%*#(*%16 ", "utf16"},
{"", ""},
}
for _, cas := range cases {
if got := normalizeEncoding(cas.encoding); got != cas.want {
t.Errorf("normalizeEncoding(%q) = %q, want %q", cas.encoding, got, cas.want)
}
}
}
func BenchmarkEscapeRune(b *testing.B) {
b.Run("low values", func(b *testing.B) {
for i := 0; i < b.N; i++ {
escapeRune(0x10)
}
})
b.Run("mid values", func(b *testing.B) {
for i := 0; i < b.N; i++ {
escapeRune(0x200)
}
})
b.Run("high values", func(b *testing.B) {
for i := 0; i < b.N; i++ {
escapeRune(0x20000)
}
})
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment