diff --git a/.gitignore b/.gitignore
index 668e0bd..6d11dc7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,4 +18,5 @@ pipeline/
.factorypath
pyvenv.cfg
.coverage
-*.csv
+predictions.csv
+out.csv
diff --git a/src/cli.py b/src/cli.py
index 513bc9c..b313765 100644
--- a/src/cli.py
+++ b/src/cli.py
@@ -27,6 +27,7 @@
import typer
+from .pre_filter import PreFilter
from .model_map import ModelMap
from .filter_pipe import FilterPipe
from src import NAME, VERSION
@@ -55,14 +56,8 @@ def filter(
"""
Filter repositories.
"""
+ PreFilter(out).prepare()
models = ModelMap().build()
- # @todo #18:30min Find effective way for processing readme.
- # For now we are not processing readme because of
- # this.
- # We need to find actual way to process readme too since it can be crucial
- # data as model input. Let's study papers, outlined
- # here
- # first, rethink it and try to implement here.
FilterPipe(repositories, out, models.get(model), typer).apply()
diff --git a/src/feed.py b/src/feed.py
index 28629e8..d327d1b 100644
--- a/src/feed.py
+++ b/src/feed.py
@@ -30,11 +30,10 @@ class Feed:
def __init__(self, file):
self.file = file
- # @todo #105:60min Process all fields required as inputs.
- # We should process all fields required as inputs: full_name, readme,
- # created_at, last_commit. In case of transformer we should do it in a
- # prompt way, like repository advanced description. Check
- # this.
+ # @todo #109:90min Feed `readme`, `last_commit`, `created_at`, and `commits`.
+ # We should feed other important fields too. For now we can feed readme,
+ # but transformer model can't process it since input tensor is too big.
+ # Let's resolve that problem and feed readme.
def read(self):
with open(self.file, "r") as input:
csv.field_size_limit(2 * 1024 * 1024 * 1024)
diff --git a/src/filter_pipe.py b/src/filter_pipe.py
index 0ffa704..d24c09b 100644
--- a/src/filter_pipe.py
+++ b/src/filter_pipe.py
@@ -21,6 +21,7 @@
# SOFTWARE.
import csv
+from .input import Input
from .feed import Feed
from .text_prediction import TextPrediction
@@ -43,7 +44,7 @@ def __init__(self, repos, output, mdl, typer):
def apply(self):
instance = self.model()
self.typer.echo(f"Filtering {self.repos} with {instance.name()}...")
- feed = Feed(self.repos).read()
+ feed = Feed(Input(self.repos).copy()).read()
with open("predictions.csv", "w") as predictions:
writer = csv.DictWriter(
predictions,
diff --git a/src/input.py b/src/input.py
index 26db7fa..eee052b 100644
--- a/src/input.py
+++ b/src/input.py
@@ -39,14 +39,8 @@ def copy(self):
pipe,
fieldnames=[
"full_name",
- "default_branch",
- "stars",
- "forks",
"created_at",
- "size",
- "open_issues_count",
"description",
- "topics",
"readme"
]
)
@@ -54,24 +48,13 @@ def copy(self):
for row in reader:
repo = row["full_name"]
branch = row["default_branch"]
- stars = row["stars"]
- forks = row["forks"]
created = row["created_at"]
- size = row["size"]
- issues = row["open_issues_count"]
description = row["description"]
- topics = row["topics"]
readme = Readme(repo, branch).asText()
out = {
"full_name": repo,
- "default_branch": branch,
- "stars": stars,
- "forks": forks,
"created_at": created,
- "size": size,
- "open_issues_count": issues,
"description": description,
- "topics": topics,
"readme": readme
}
writer.writerow(out)
diff --git a/src/text_prediction.py b/src/text_prediction.py
index a1c060c..fb4f7e6 100644
--- a/src/text_prediction.py
+++ b/src/text_prediction.py
@@ -32,7 +32,7 @@ def __init__(self, pred, name):
def as_text(self):
if self.model == "rf":
- if self.pred == [0]:
+ if self.pred == [1]:
label = "sample"
else:
label = "real"
diff --git a/tests/test-feed.csv b/tests/test-feed.csv
new file mode 100644
index 0000000..a18504b
--- /dev/null
+++ b/tests/test-feed.csv
@@ -0,0 +1,637 @@
+full_name,created_at,description,readme
+totond/TextPathView,2018-01-10T10:36:47Z,A View with text path animation!,"# TextPathView
+
+![](https://img.shields.io/badge/JCenter-0.2.1-brightgreen.svg)
+
+
+
+
+
+
+ > [Go to the English README](https://github.com/totond/TextPathView/blob/master/README-en.md)
+
+
+## 介绍
+ TextPathView是一个把文字转化为路径动画然后展现出来的自定义控件。效果如上图。
+
+ > 这里有[原理解析!](https://juejin.im/post/5a9677b16fb9a063375765ad)
+
+### v0.2.+重要更新
+
+ - 现在不但可以控制文字路径结束位置end,还可以控制开始位置start,如上图二
+ - 可以通过PathCalculator的子类来控制实现一些字路径变化,如下面的MidCalculator、AroundCalculator、BlinkCalculator
+ - 可以通知直接设置FillColor属性来控制结束时是否填充颜色
+
+ ![TextPathView v0.2.+](https://raw.githubusercontent.com/totond/MyTUKU/master/textpathnew1.png)
+
+## 使用
+ 主要的使用流程就是输入文字,然后设置一些动画的属性,还有画笔特效,最后启动就行了。想要自己控制绘画的进度也可以,详情见下面。
+
+### Gradle
+
+```
+compile 'com.yanzhikai:TextPathView:0.2.1'
+```
+
+ > minSdkVersion 16
+
+ > 如果遇到播放完后消失的问题,请关闭硬件加速,可能是硬件加速对`drawPath()`方法不支持
+
+### 使用方法
+
+#### TextPathView
+ TextPathView分为两种,一种是每个笔画按顺序刻画的SyncTextPathView,一种是每个笔画同时刻画的AsyncTextPathView,使用方法都是一样,在xml里面配置属性,然后直接在java里面调用startAnimation()方法就行了,具体的可以看例子和demo。下面是一个简单的例子:
+
+xml里面:
+
+```
+
+
+
+
+```
+
+java里面使用:
+
+```
+ atpv1 = findViewById(R.id.atpv_1);
+ stpv_2017 = findViewById(R.id.stpv_2017);
+
+ //从无到显示
+ atpv1.startAnimation(0,1);
+ //从显示到消失
+ stpv_2017.startAnimation(1,0);
+```
+
+还可以通过控制进度,来控制TextPathView显示,这里用SeekBar:
+
+```
+ sb_progress.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ atpv1.drawPath(progress / 1000f);
+ stpv_2017.drawPath(progress / 1000f);
+
+ }
+ }
+```
+
+#### PathView
+ PathView是0.1.1版本之后新增的,拥有三个子类TextPathView、SyncPathView和AsyncPathView,前者上面有介绍是文字的路径,后面这两个就是图形的路径,必须要输入一个Path类,才能正常运行:
+
+```
+public class TestPath extends Path {
+ public TestPath(){
+ init();
+ }
+
+ private void init() {
+ addCircle(350,300,150,Direction.CCW);
+ addCircle(350,300,100,Direction.CW);
+ addCircle(350,300,50,Direction.CCW);
+ moveTo(350,300);
+ lineTo(550,500);
+ }
+}
+```
+
+```
+ //必须先调用setPath设置路径
+ aspv.setPath(new TestPath());
+ aspv.startAnimation(0,1);
+```
+
+![](https://github.com/totond/MyTUKU/blob/master/textdemo2.gif?raw=true)
+ (录屏可能有些问题,实际上是没有背景色的)上面就是SyncPathView和AsyncPathView效果,区别和文字路径是一样的。
+
+### 属性
+
+|**属性名称**|**意义**|**类型**|**默认值**|
+|--|--|:--:|:--:|
+|textSize | 文字的大小size | integer| 108 |
+|text | 文字的具体内容 | String| Test|
+|autoStart| 是否加载完后自动启动动画 | boolean| false|
+|showInStart| 是否一开始就把文字全部显示 | boolean| false|
+|textInCenter| 是否让文字内容处于控件中心 | boolean| false|
+|duration | 动画的持续时间,单位ms | integer| 10000|
+|showPainter | 在动画执行的时候是否执行画笔特效 | boolean| false|
+|showPainterActually| 在所有时候是否展示画笔特效| boolean| false|
+|~~textStrokeWidth~~ strokeWidth | 路径刻画的线条粗细 | dimension| 5px|
+|~~textStrokeColor~~ pathStrokeColor| 路径刻画的线条颜色 | color| Color.black|
+|paintStrokeWidth | 画笔特效刻画的线条粗细 | dimension| 3px|
+|paintStrokeColor | 画笔特效刻画的线条颜色 | color| Color.black|
+|repeat| 是否重复播放动画,重复类型| enum | NONE|
+|fillColor| 文字动画结束时是否填充颜色 | boolean | false |
+
+|**repeat属性值**|**意义**|
+|--|--|
+|NONE|不重复播放|
+|RESTART|动画从头重复播放|
+|REVERSE|动画从尾重复播放|
+
+
+ > PS:showPainterActually属性,由于动画绘画完毕应该将画笔特效消失,所以每次执行完动画都会自动设置为false。因此最好用于使用非自带动画的时候。
+
+### 方法
+
+#### 画笔特效
+
+```
+ //设置画笔特效
+ public void setPainter(SyncPathPainter painter);
+ //设置画笔特效
+ public void setPainter(SyncPathPainter painter);
+```
+ 因为绘画的原理不一样,画笔特效也分两种:
+
+```
+ public interface SyncPathPainter extends PathPainter {
+ //开始动画的时候执行
+ void onStartAnimation();
+
+ /**
+ * 绘画画笔特效时候执行
+ * @param x 当前绘画点x坐标
+ * @param y 当前绘画点y坐标
+ * @param paintPath 画笔Path对象,在这里画出想要的画笔特效
+ */
+ @Override
+ void onDrawPaintPath(float x, float y, Path paintPath);
+ }
+
+ public interface AsyncPathPainter extends PathPainter {
+ /**
+ * 绘画画笔特效时候执行
+ * @param x 当前绘画点x坐标
+ * @param y 当前绘画点y坐标
+ * @param paintPath 画笔Path对象,在这里画出想要的画笔特效
+ */
+ @Override
+ void onDrawPaintPath(float x, float y, Path paintPath);
+ }
+```
+ 看名字就知道是对应哪一个了,想要自定义画笔特效的话就可以实现上面之中的一个或者两个接口来自己画啦。
+ 另外,还有里面已经自带了3种画笔特效,可供参考和使用(关于这些画笔特效的实现,可以参考[原理解析](http://blog.csdn.net/totond/article/details/79375200)):
+
+```
+
+//箭头画笔特效,根据传入的当前点与上一个点之间的速度方向,来调整箭头方向
+public class ArrowPainter implements SyncPathPainter {
+
+//一支笔的画笔特效,就是在绘画点旁边画多一支笔
+public class PenPainter implements SyncPathPainter,AsyncPathPainter {
+
+//火花特效,根据箭头引申变化而来,根据当前点与上一个点算出的速度方向来控制火花的方向
+public class FireworksPainter implements SyncPathPainter {
+
+```
+
+ 由上面可见,因为烟花和箭头画笔特效都需要记录上一个点的位置,所以只适合按顺序绘画的SyncTextPathView,而PenPainter就适合两种TextPathView。仔细看它的代码的话,会发现画起来都是很简单的哦。
+
+#### 自定义画笔特效
+ 自定义画笔特效也是非常简单的,原理就是在当前绘画点上加上一个附加的Path,实现SyncPathPainter和AsyncPathPainter之中的一个或者两个接口,重写里面的`onDrawPaintPath(float x, float y, Path paintPath)`方法就行了,如下面这个:
+
+```
+ atpv2.setPathPainter(new AsyncPathPainter() {
+ @Override
+ public void onDrawPaintPath(float x, float y, Path paintPath) {
+ paintPath.addCircle(x,y,6, Path.Direction.CCW);
+ }
+ });
+```
+![](https://github.com/totond/MyTUKU/blob/master/textdemo3.gif?raw=true)
+
+#### 动画监听
+
+```
+ //设置自定义动画监听
+ public void setAnimatorListener(PathAnimatorListener animatorListener);
+
+```
+ PathAnimatorListener是实现了AnimatorListener接口的类,继承它的时候注意不要删掉super父类方法,因为里面可能有一些操作。
+
+#### 画笔获取
+
+```
+ //获取绘画文字的画笔
+ public Paint getDrawPaint() {
+ return mDrawPaint;
+ }
+
+ //获取绘画画笔特效的画笔
+ public Paint getPaint() {
+ return mPaint;
+ }
+```
+
+#### 控制绘画
+
+```
+ /**
+ * 绘画文字路径的方法
+ *
+ * @param start 路径开始点百分比
+ * @param end 路径结束点百分比
+ */
+ public abstract void drawPath(float start, float end);
+
+ /**
+ * 开始绘制路径动画
+ * @param start 路径比例,范围0-1
+ * @param end 路径比例,范围0-1
+ */
+ public void startAnimation(float start, float end);
+
+ /**
+ * 绘画路径的方法
+ * @param progress 绘画进度,0-1
+ */
+ public void drawPath(float progress);
+
+ /**
+ * Stop animation
+ */
+ public void stopAnimation();
+
+ /**
+ * Pause animation
+ */
+ @RequiresApi(api = Build.VERSION_CODES.KITKAT)
+ public void pauseAnimation();
+
+ /**
+ * Resume animation
+ */
+ @RequiresApi(api = Build.VERSION_CODES.KITKAT)
+ public void resumeAnimation();
+```
+
+#### 填充颜色
+
+```
+ //直接显示填充好颜色了的全部文字
+ public void showFillColorText();
+
+ //设置动画播放完后是否填充颜色
+ public void setFillColor(boolean fillColor)
+```
+ 由于正在绘画的时候文字路径不是封闭的,填充颜色会变得很混乱,所以这里给出`showFillColorText()`来设置直接显示填充好颜色了的全部文字,一般可以在动画结束后文字完全显示后过渡填充
+
+![](https://github.com/totond/MyTUKU/blob/master/textdemo4.gif?raw=true)
+
+
+
+
+
+#### 取值计算器
+
+ 0.2.+版本开始,加入了取值计算器PathCalculator,可以通过`setCalculator(PathCalculator calculator)`方法设置。PathCalculator可以控制路径的起点start和终点end属性在不同progress对应的取值。TextPathView自带一些PathCalculator子类:
+
+- **MidCalculator**
+
+ start和end从0.5开始往两边扩展:
+
+![MidCalculator](https://github.com/totond/MyTUKU/blob/master/text4.gif?raw=true)
+
+- **AroundCalculator**
+
+ start会跟着end增长,end增长到0.75后start会反向增长
+
+![AroundCalculator](https://github.com/totond/MyTUKU/blob/master/text5.gif?raw=true)
+
+- **BlinkCalculator**
+
+ start一直为0,end自然增长,但是每增加几次会有一次end=1,造成闪烁
+
+![BlinkCalculator](https://github.com/totond/MyTUKU/blob/master/text2.gif?raw=true)
+
+- **自定义PathCalculator:**用户可以通过继承抽象类PathCalculator,通过里面的`setStart(float start)`和`setEnd(float end)`,具体可以参考上面几个自带的PathCalculator实现代码。
+
+#### 其他
+
+```
+ //设置文字内容
+ public void setText(String text);
+
+ //设置路径,必须先设置好路径在startAnimation(),不然会报错!
+ public void setPath(Path path) ;
+
+ //设置字体样式
+ public void setTypeface(Typeface typeface);
+
+ //清除画面
+ public void clear();
+
+ //设置动画时能否显示画笔效果
+ public void setShowPainter(boolean showPainter);
+
+ //设置所有时候是否显示画笔效果,由于动画绘画完毕应该将画笔特效消失,所以每次执行完动画都会自动设置为false
+ public void setCanShowPainter(boolean canShowPainter);
+
+ //设置动画持续时间
+ public void setDuration(int duration);
+
+ //设置重复方式
+ public void setRepeatStyle(int repeatStyle);
+
+ //设置Path开始结束取值的计算器
+ public void setCalculator(PathCalculator calculator)
+
+```
+
+## 更新
+
+ - 2018/03/08 **version 0.0.5**:
+ - 增加了`showFillColorText()`方法来设置直接显示填充好颜色了的全部文字。
+ - 把PathAnimatorListener从TextPathView的内部类里面解放出来,之前使用太麻烦了。
+ - 增加`showPainterActually`属性,设置所有时候是否显示画笔效果,由于动画绘画完毕应该将画笔特效消失,所以每次执行完动画都会自动将它设置为false。因此它用处就是在不使用自带Animator的时候显示画笔特效。
+
+ - 2018/03/08 **version 0.0.6**:
+ - 增加了`stop(), pause(), resume()`方法来控制动画。之前是觉得让使用者自己用Animator实现就好了,现在一位外国友人[toanvc](https://github.com/toanvc)提交的PR封装好了,我稍作修改,不过后两者使用时API要大于等于19。
+ - 增加了`repeat`属性,让动画支持重复播放,也是[toanvc](https://github.com/toanvc)同学的PR。
+
+ - 2018/03/18 **version 0.1.0**:
+ - 重构代码,加入路径动画SyncPathView和AsyncPathView,把总父类抽象为PathView
+ - 增加`setDuration()`、`setRepeatStyle()`
+ - 修改一系列名字如下:
+
+|Old Name|New Name|
+|---|---|
+|TextPathPainter|PathPainter|
+|SyncTextPainter|SyncPathPainter|
+|AsyncTextPainter|AsyncPathPainter|
+|TextAnimatorListener|PathAnimatorListener|
+
+ - 2018/03/21 **version 0.1.2**:
+ - 修复高度warp_content时候内容有可能显示不全
+ - 原来PathMeasure获取文字Path时候,最后会有大概一个像素的缺失,现在只能在onDraw判断progress是否为1来显示完全路径(但是这样可能会导致硬件加速上显示不出来,需要手动关闭这个View的硬件加速)
+ - 增加字体设置
+ - 支持自动换行
+
+![](https://github.com/totond/MyTUKU/blob/master/textdemo5.gif?raw=true)
+
+ - 2018/09/09 **version 0.1.3**:
+ - 默认关闭此控件的硬件加速
+ - 加入内存泄漏控制
+ - 准备后续优化
+- 2019/04/04 **version 0.2.1**:
+ - 现在不但可以控制文字路径结束位置end,还可以控制开始位置start
+ - 可以通过PathCalculator的子类来控制实现一些字路径变化,如上面的MidCalculator、AroundCalculator、BlinkCalculator
+ - 可以通知直接设置FillColor属性来控制结束时是否填充颜色
+ - 硬件加速问题解决,默认打开
+ - 去除无用log和报错
+
+
+#### 后续将会往下面的方向努力:
+
+ - 更多的特效,更多的动画,如果有什么想法和建议的欢迎issue提出来一起探讨,还可以提交PR出一份力。
+ - 更好的性能,目前单个TextPathView在模拟器上运行动画时是不卡的,多个就有一点点卡顿了,在性能较好的真机多个也是没问题的,这个性能方面目前还没头绪。
+ - 文字换行符支持。
+ - Path的宽高测量(包含空白,从坐标(0,0)开始)
+
+
+## 贡献代码
+ 如果想为TextPathView的完善出一份力的同学,欢迎提交PR:
+ - 首先请创建一个分支branch。
+ - 如果加入新的功能或者效果,请不要覆盖demo里面原来用于演示Activity代码,如FristActivity里面的实例,可以选择新增一个Activity做演示测试,或者不添加演示代码。
+ - 如果修改某些功能或者代码,请附上合理的依据和想法。
+ - 翻译成English版README(暂时没空更新英文版)
+
+## 开源协议
+ TextPathView遵循MIT协议。
+
+## 关于作者
+ > id:炎之铠
+
+ > 炎之铠的邮箱:yanzhikai_yjk@qq.com
+
+ > CSDN:http://blog.csdn.net/totond
+
+
+
+
+
+
+"
+square/mortar,2013-11-09T00:01:50Z,"A simple library that makes it easy to pair thin views with dedicated controllers, isolated from most of the vagaries of the Activity life cycle.","# Mortar
+
+## Deprecated
+
+Mortar had a good run and served us well, but new use is strongly discouraged. The app suite at Square that drove its creation is in the process of replacing Mortar with [Square Workflow](https://square.github.io/workflow/).
+
+## What's a Mortar?
+
+Mortar provides a simplified, composable overlay for the Android lifecycle,
+to aid in the use of [Views as the modular unit of Android applications][rant].
+It leverages [Context#getSystemService][services] to act as an a la carte supplier
+of services like dependency injection, bundle persistence, and whatever else
+your app needs to provide itself.
+
+One of the most useful services Mortar can provide is its [BundleService][bundle-service],
+which gives any View (or any object with access to the Activity context) safe access to
+the Activity lifecycle's persistence bundle. For fans of the [Model View Presenter][mvp]
+pattern, we provide a persisted [Presenter][presenter] class that builds on BundleService.
+Presenters are completely isolated from View concerns. They're particularly good at
+surviving configuration changes, weathering the storm as Android destroys your portrait
+Activity and Views and replaces them with landscape doppelgangers.
+
+Mortar can similarly make [Dagger][dagger] ObjectGraphs (or [Dagger2][dagger2]
+Components) visible as system services. Or not — these services are
+completely decoupled.
+
+Everything is managed by [MortarScope][scope] singletons, typically
+backing the top level Application and Activity contexts. You can also spawn
+your own shorter lived scopes to manage transient sessions, like the state of
+an object being built by a set of wizard screens.
+
+
+
+These nested scopes can shadow the services provided by higher level scopes.
+For example, a [Dagger extension graph][ogplus] specific to your wizard session
+can cover the one normally available, transparently to the wizard Views.
+Calls like `ObjectGraphService.inject(getContext(), this)` are now possible
+without considering which graph will do the injection.
+
+## The Big Picture
+
+An application will typically have a singleton MortarScope instance.
+Its job is to serve as a delegate to the app's `getSystemService` method, something like:
+
+```java
+public class MyApplication extends Application {
+ private MortarScope rootScope;
+
+ @Override public Object getSystemService(String name) {
+ if (rootScope == null) rootScope = MortarScope.buildRootScope().build(getScopeName());
+
+ return rootScope.hasService(name) ? rootScope.getService(name) : super.getSystemService(name);
+ }
+}
+```
+
+This exposes a single, core service, the scope itself. From the scope you can
+spawn child scopes, and you can register objects that implement the
+[Scoped](https://github.com/square/mortar/blob/master/mortar/src/main/java/mortar/Scoped.java#L18)
+interface with it for setup and tear-down calls.
+
+ * `Scoped#onEnterScope(MortarScope)`
+ * `Scoped#onExitScope(MortarScope)`
+
+To make a scope provide other services, like a [Dagger ObjectGraph][og],
+you register them while building the scope. That would make our Application's
+`getSystemService` method look like this:
+
+```java
+ @Override public Object getSystemService(String name) {
+ if (rootScope == null) {
+ rootScope = MortarScope.buildRootScope()
+ .with(ObjectGraphService.SERVICE_NAME, ObjectGraph.create(new RootModule()))
+ .build(getScopeName());
+ }
+
+ return rootScope.hasService(name) ? rootScope.getService(name) : super.getSystemService(name);
+ }
+```
+
+Now any part of our app that has access to a `Context` can inject itself:
+
+```java
+public class MyView extends LinearLayout {
+ @Inject SomeService service;
+
+ public MyView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ ObjectGraphService.inject(context, this);
+ }
+}
+```
+
+To take advantage of the BundleService describe above, you'll put similar code
+into your Activity. If it doesn't exist already, you'll
+build a sub-scope to back the Activity's `getSystemService` method, and
+while building it set up the `BundleServiceRunner`. You'll also notify
+the BundleServiceRunner each time `onCreate` and `onSaveInstanceState` are
+called, to make the persistence bundle available to the rest of the app.
+
+```java
+public class MyActivity extends Activity {
+ private MortarScope activityScope;
+
+ @Override public Object getSystemService(String name) {
+ MortarScope activityScope = MortarScope.findChild(getApplicationContext(), getScopeName());
+
+ if (activityScope == null) {
+ activityScope = MortarScope.buildChild(getApplicationContext()) //
+ .withService(BundleServiceRunner.SERVICE_NAME, new BundleServiceRunner())
+ .withService(HelloPresenter.class.getName(), new HelloPresenter())
+ .build(getScopeName());
+ }
+
+ return activityScope.hasService(name) ? activityScope.getService(name)
+ : super.getSystemService(name);
+ }
+
+ @Override protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ BundleServiceRunner.getBundleServiceRunner(this).onCreate(savedInstanceState);
+ setContentView(R.layout.main_view);
+ }
+
+ @Override protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ BundleServiceRunner.getBundleServiceRunner(this).onSaveInstanceState(outState);
+ }
+}
+```
+
+With that in place, any object in your app can sign up with the `BundleService`
+to save and restore its state. This is nice for views, since Bundles are less
+of a hassle than the `Parcelable` objects required by `View#onSaveInstanceState`,
+and a boon to any business objects in the rest of your app.
+
+Download
+--------
+
+Download [the latest JAR][jar] or grab via Maven:
+
+```xml
+
+ com.squareup.mortar
+ mortar
+ (insert latest version)
+
+```
+
+Gradle:
+
+```groovy
+compile 'com.squareup.mortar:mortar:(latest version)'
+```
+
+## Full Disclosure
+
+This stuff has been in ""rapid"" development over a pretty long gestation period,
+but is finally stabilizing. We don't expect drastic changes before cutting a
+1.0 release, but we still cannot promise a stable API from release to release.
+
+Mortar is a key component of multiple Square apps, including our flagship
+[Square Register][register] app.
+
+License
+--------
+
+ Copyright 2013 Square, 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.
+
+[bundle-service]: https://github.com/square/mortar/blob/master/mortar/src/main/java/mortar/bundler/BundleService.java
+[mvp]: http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93presenter
+[dagger]: http://square.github.io/dagger/
+[dagger2]: http://google.github.io/dagger/
+[jar]: http://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=com.squareup.mortar&a=mortar&v=LATEST
+[og]: https://square.github.io/dagger/1.x/dagger/dagger/ObjectGraph.html
+[ogplus]: https://github.com/square/dagger/blob/dagger-parent-1.1.0/core/src/main/java/dagger/ObjectGraph.java#L96
+[presenter]: https://github.com/square/mortar/blob/master/mortar/src/main/java/mortar/Presenter.java
+[rant]: http://corner.squareup.com/2014/10/advocating-against-android-fragments.html
+[register]: https://play.google.com/store/apps/details?id=com.squareup
+[scope]: https://github.com/square/mortar/blob/master/mortar/src/main/java/mortar/MortarScope.java
+[services]: http://developer.android.com/reference/android/content/Context.html#getSystemService(java.lang.String)
+"
+joyoyao/superCleanMaster,2015-02-12T03:37:41Z,[DEPRECATED] ,"# superCleanMaster
+superCleanMaster is deprecated Thanks for all your support!
+
+
+"
diff --git a/tests/test_feed.py b/tests/test_feed.py
new file mode 100644
index 0000000..e014e38
--- /dev/null
+++ b/tests/test_feed.py
@@ -0,0 +1,53 @@
+# The MIT License (MIT)
+#
+# Copyright (c) 2024 Aliaksei Bialiauski
+#
+# 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 NON-INFRINGEMENT. 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.
+import unittest
+
+from src.feed import Feed
+
+"""
+Test case for feed.py.
+"""
+
+
+class TestFeed(unittest.TestCase):
+
+ def test_reads_feed(self):
+ feed = Feed("test-feed.csv").read()
+ expected = [
+ {
+ 'id': 'totond/TextPathView',
+ 'input': 'A View with text path animation!'
+ },
+ {
+ 'id': 'square/mortar',
+ 'input': 'A simple library that makes it easy to pair thin views with dedicated controllers, isolated from most of the vagaries of the Activity life cycle.'
+ },
+ {
+ 'id': 'joyoyao/superCleanMaster',
+ 'input': '[DEPRECATED] '
+ }
+ ]
+ self.assertEqual(
+ feed,
+ expected,
+ f"Received feed {feed} does not match with expected {expected}"
+ )
diff --git a/tests/test_text_prediction.py b/tests/test_text_prediction.py
index bab1e15..9e1ae47 100644
--- a/tests/test_text_prediction.py
+++ b/tests/test_text_prediction.py
@@ -57,7 +57,7 @@ def test_raises_error_on_invalid_input(self):
TextPrediction("", "test").as_text()
def test_transforms_rf_positive_predicts(self):
- prediction = [0]
+ prediction = [1]
text = TextPrediction(prediction, "rf").as_text()
expected = "sample"
self.assertEqual(
@@ -67,7 +67,7 @@ def test_transforms_rf_positive_predicts(self):
)
def test_transforms_rf_negative_predicts(self):
- prediction = [1]
+ prediction = [0]
text = TextPrediction(prediction, "rf").as_text()
expected = "real"
self.assertEqual(