Proof of Concept - Subscriptions over HTTP

Hello!
I've put together a demonstration that GraphqQl subscriptions work great over plain HTTP with Server Sent Events (chunk responses in Plug)..
The core logic is pretty simple, most of this is test code... It'd be quite nice to have subscriptions work in Absinthe.Plug out of the box w/o need for WebSockets. These HTTP based subscriptions work from most plain HTTP clients, including good 'ol curl..
Let me know what ya'll think! (I know this would need some work before merging...)

Made that encoding change as well as a handful of others!

@binaryseed I don't do a lot with chunked responses so this may be totally off base, but is it possible for the client to send down an additional subscription document? That is, if they want to subscribe to several things would they have to send it down all at once (think transport batching) or would they be able to send them down individually?

So with Server Sent Events, the client only sends the initial request. After that it's one way communication from server -> client.
Does Absinthe support sending multiple subscriptions in a single query? If so, we could support that, SSE supports "naming" each event that is sent down to the client, which could match the subscription object.
https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events

It seems that it fails if there are 2 subscription fields..
query = "subscription {update secondField}"
# ...
(MatchError) no match of right hand side value: [%Absinthe.Blueprint.Document.Field{...
    (absinthe) lib/absinthe/phase/subscription/subscribe_self.ex:73: Absinthe.Phase.Subscription.SubscribeSelf.get_field/1
    (absinthe) lib/absinthe/phase/subscription/subscribe_self.ex:34: Absinthe.Phase.Subscription.SubscribeSelf.get_field_key/2
    (absinthe) lib/absinthe/phase/subscription/subscribe_self.ex:24: Absinthe.Phase.Subscription.SubscribeSelf.do_subscription/1

so with SSE as it stands, we just do a single subscription per entire request. this seems fine to me...

@binaryseed According to the specification, only one root field is allowed per subscription. https://github.com/facebook/graphql/blob/e80bbfa8640e2cddd7aa6fe30ee1ae64abd7e2e9/spec/Section 5 -- Validation.md#single-root-field
We should, however, have a nice validation error instead of what you're encountering.

Yeah there's a missing validation. If the server can't send additional requests later, we could still probably leverage transport batching and have it send a batch of subscription docs all at once.

Where would the transport batching be handled? Does the phoenix / websocket variety support this yet?

Also, the GraphiQl plug.. It appears to reference this plug's call and init, so it should "just work" I suspect. of course the client JS doesn't yet have support for it

@binaryseed transport batching happens within Absinthe.Plug, it will happen if the batched document structure is used, I'll see if I can draw up a test case and get it to work. Absinthe.Phoenix doesn't need to do this because since it has a persistent connection it can just serially push documents without really any additional overhead.

Actually, I think that a single subscription per request is a totally fine place to start.. With http/2 on the way, that pretty much means native support for transport batching will come for free

Well, transport batching isn' simply a matter of using a single HTTP request to send multiple docs, it also lets you perform Absinthe batching across the whole set of documents. That is, if you submit
# doc 1
{
  post(id: 1) { comments { body } }
}
# doc 2
{
  post(id: 2) { comments { body } }
}

Absinthe will only do a single DB request to get the comments, even though they happen in completely different documents. This requires not only that the requests are sent over a single http connection, but that they are actually sent at the same time.

That sounds useful for the first event in the subscription, but after that, it's not guaranteed that the will happen at the same time anymore... Comments could be minutes even hours apart

Ran into a bit of a snag with this... the Browser's EventSource API for dealing with Server Sent Events is only able to make GET requests :(
This is something the GraphQL spec seems to allow.. http://graphql.org/learn/serving-over-http/#http-methods-headers-and-body
But.. AbsinthePlug seems to dis-allow GET for mutation and subscriptions..
https://github.com/absinthe-graphql/absinthe_plug/blob/master/lib/absinthe/validation/http_method.ex
Is there a specific reason for that? Seems like subscriptions should be fine over GET

Tweaked it to do just that!

Are ya'll interested in getting this in for 1.4? Are there code changes you'd like to see? specs, moving stuff, etc?

Hey @binaryseed sorry, hadn't had a chance to look at it after the last commit.

This looks great, thank you!


Execution failed for task ':app:flutterDependenciesDebug'.

Write my_app example app on windows 10 using Android Studio.  Run app or Debug app.
Launching lib\main.dart on Nexus 5 in debug mode...
Initializing gradle...
Resolving dependencies...
Running 'gradlew assembleDebug'...
Oops; flutter has exited unexpectedly.
Crash report written to C:\Users\owner\AndroidstudioProjects\my_app\flutter_06.log;
please let us know at https://github.com/flutter/flutter/issues.
FAILURE: Build failed with an exception.

Where:
Script 'C:\flutter\packages\flutter_tools\gradle\flutter.gradle' line: 421

What went wrong:
Execution failed for task ':app:flutterDependenciesDebug'.

Process 'command 'C:\flutter\bin\flutter.bat'' finished with non-zero exit value 1

Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

Get more help at https://help.gradle.org

BUILD FAILED in 6s
Finished with error: Gradle build failed: 1
[!] Flutter (on Microsoft Windows [Version 10.0.16299.248], locale en-US, channel beta)
• Flutter version 0.1.4 at C:\flutter
• Framework revision f914e701c5 (9 days ago), 2018-02-19 21:12:17 +0000
• Engine revision 13cf22c284
• Dart version 2.0.0-dev.27.0-flutter-0d5cf900b0
X Downloaded executables cannot execute on host (see https://github.com/flutter/flutter/issues/6207 for more information)
[√] Android toolchain - develop for Android devices (Android SDK 27.0.2)
• Android SDK at C:\Users\owner\AppData\Local\Android\sdk
• Android NDK location not configured (optional; useful for native profiling support)
• Platform android-27, build-tools 27.0.2
• Java binary at: C:\Program Files\Android\Android Studio\jre\bin\java
• Java version OpenJDK Runtime Environment (build 1.8.0_152-release-915-b01)
[√] Android Studio (version 3.0)
• Android Studio at C:\Program Files\Android\Android Studio
• Java version OpenJDK Runtime Environment (build 1.8.0_152-release-915-b01)
[!] IntelliJ IDEA Community Edition (version 2017.3)
X Flutter plugin not installed; this adds Flutter specific functionality.
X Dart plugin not installed; this adds Dart specific functionality.
• For information about installing plugins, see
https://flutter.io/intellij-setup/#installing-the-plugins
[√] Connected devices
• Nexus 5 • 037bb12f2152a091 • android-arm • Android 5.0 (API 21)
! Doctor found issues in 2 categories.

I was able to resolve this by selecting tools|flutter|flutter upgrade.  I am closing this issue.


Wrap widget doesn't layout correctly in certain cases, like Column does

When using the technique listed here, under the heading "Expanding content to fit the viewport": https://api.flutter.dev/flutter/widgets/SingleChildScrollView-class.html,
a Column widget works very well, but a Wrap does not. Is there something maybe missing from the way the Wrap widget lays itself out that could be improved to act more like a Column?
Essentially, the following sample shows the problem. If you run this app on a device, it should start out with a view that can be scrolled so all children are accessible. Hitting the button at the top to switch to using a Wrap will cause an Overflow.
Switching back to a Column, you can scroll again, and if you change the number in the text field to a smaller number, you can get the Wrap widget to work well as long as no Overflow happens.
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: WrapHomePage(),
    );
  }
}

class WrapHomePage extends StatefulWidget {
  const WrapHomePage();

  @override
  _WrapHomePageState createState()  => _WrapHomePageState();
}

class _WrapHomePageState extends State<WrapHomePage> {

  bool _useColumn = true;
  int _numTexts = 8;

  List<Widget> _buildTexts(int numTexts) {
    List<Widget> texts = [];
    for (int i=0; i<numTexts; i++) {
      texts.add(Padding(
        padding: const EdgeInsets.only(top: 24.0),
        child: Text(
            "Hello, this is some long text. It can go on and on. This test is to make sure we can scroll"),
      ));
    }
    return texts;
  }

  @override
  Widget build(BuildContext context) {

    final texts = _buildTexts(_numTexts);

    return Scaffold(
        body: SafeArea(
          child: Padding(
            padding: const EdgeInsets.all(24),
            child: LayoutBuilder(
              builder: (context, constraints) {
                return SingleChildScrollView(
                    child: ConstrainedBox(
                      constraints: BoxConstraints(
                        minHeight: constraints.maxHeight,
                      ),
                      child: IntrinsicHeight(
                        child: DefaultTextStyle(
                          style: TextStyle(fontSize: 20, color: Colors.black),
                          child: Column(
                            mainAxisAlignment: MainAxisAlignment.start,
                            mainAxisSize: MainAxisSize.max,
                            children: [
                              FlatButton(
                                  onPressed: () {
                                    setState(() {
                                      _useColumn = !_useColumn;
                                    });
                                  },
                                  child: Text(_useColumn ? "Switch to Wrap!" : "Switch to Column!", style: TextStyle(fontSize: 20, color: Colors.black))
                              ),
                              if (_useColumn)
                                Column(
                                  key: ValueKey("header"),
                                  children: texts,
                                )
                              else
                                Wrap(
                                  key: ValueKey("header"),
                                  children: texts,
                                ),
                              Expanded(
                                  key: ValueKey("middle"),
                                  child: Container(
                                    color: Colors.red,
                                    child: Center(
                                        child: TextField(
                                          onChanged: (value) {
                                            setState(() {
                                              _numTexts = int.parse(value);
                                            });
                                          },
                                        )
                                    ),
                                  )
                              ),
                              Padding(
                                key: ValueKey("footer"),
                                padding: const EdgeInsets.only(top: 24.0),
                                child: Column(
                                  children: [
                                    Text("Final message")
                                  ],
                                ),
                              )
                            ],
                          ),
                        ),
                      ),
                    )
                );
              }
            ),
          )
        )
    );
  }
}

The flutter_markdown plugin works by creating Wrap widgets, and thus cannot be used in this type of layout unfortunately. Also, what is strange is if the code is changed to create multiple Wrap widgets inside of a Column, then it causes other issues, such as sometimes not generating an Overflow warning, but instead causes the Expanded child of the outer column to not render.

Hi @dannyvalentesonos
you may want to with the change below
Wrap(
  direction: Axis.vertical, /// <= THIS
  key: ValueKey("header"),
  children: texts,
),

please let me know if it fixes the issue
thank you

Thanks @iapicca . It does fix the overflow, but it causes the text to get truncated on the horizontal axis, and it prevents a Wrap from being used in the intended fashion for the Markdown plugin. The intent is to place all pieces next to each other horizontally and then flow downward as needed.
So this unfortunately does not solve the problem.
Thanks.

flutter doctor -v
[✓] Flutter (Channel dev, 1.20.0-7.1.pre, on Mac OS X 10.15.5 19F101, locale
    en-GB)
    • Flutter version 1.20.0-7.1.pre at /Users/taha/Code/flutter_dev
    • Framework revision 7736f3bc90 (3 days ago), 2020-07-10 16:33:05 -0700
    • Engine revision d48085141c
    • Dart version 2.9.0 (build 2.9.0-21.2.beta)

[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.0)
    • Android SDK at /Users/taha/Code/sdk
    • Platform android-30, build-tools 30.0.0
    • ANDROID_HOME = /Users/taha/Code/sdk
    • Java binary at: /Applications/Android
      Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build
      1.8.0_242-release-1644-b3-6222593)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 11.5)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Xcode 11.5, Build version 11E608c
    • CocoaPods version 1.9.3

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 4.0)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin version 47.1.2
    • Dart plugin version 193.7361
    • Java version OpenJDK Runtime Environment (build
      1.8.0_242-release-1644-b3-6222593)

[✓] VS Code (version 1.47.0)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.12.2

[✓] Connected device (6 available)
    • SM M305F (mobile)      • 32003c30dc19668f                     •
      android-arm64  • Android 10 (API 29)
    • Taha’s iPhone (mobile) • 00008020-001059882212002E            • ios
      • iOS 13.5.1
    • iPhone 11 (mobile)     • C56E212F-BE8E-4766-8610-12CFADC797F0 • ios
      • com.apple.CoreSimulator.SimRuntime.iOS-13-5 (simulator)
    • macOS (desktop)        • macos                                • darwin-x64
      • Mac OS X 10.15.5 19F101
    • Web Server (web)       • web-server                           •
      web-javascript • Flutter Tools
    • Chrome (web)           • chrome                               •
      web-javascript • Google Chrome 83.0.4103.116

• No issues found!

Hi @dannyvalentesonos can you describe the expected behavior? I am not sure what the Wrap widget should be doing in your use case that is incorrect.

@Piinks The expected behavior is for the Wrap widget to behave like a Column, so that the elements can all be scrolled nicely in the example I attached in the description. If you run the app with the code I attached, you can see that when using a Wrap, it causes an overflow, even though the widget is inside a scrollable view. When using a Column, everything works as expected. Is it possible to have the Wrap widget behave properly in that scenario? I've also noticed that different behavior can be seen when Wrap widgets inside a Column, which is how the Flutter Markdown plugin works. It's rather strange.
In any case, as @iapicca pointed out, using direction: Axis.vertical, /// <= THIS fixes the issue, but it doesn't give the actual result the developer wants, which is to lay elements out horizontally first.

It sounds like a Column gives you the expected behavior, is there a reason why a Column will not satisfy your need?
I don't know that the Wrap widget can be expected to work as a Column would. They have very different render objects, RenderFlex for the Column and RenderWrap for the Wrap, and they calculate their layout in different ways.
The expanding behavior described in the sample code from the api docs above (re: SingleChildScrollView) is referring to Flex widgets, but Wrap isn't one of those.

@Piinks Thanks for explaining that.
In my description, I wrote

a Column widget works very well, but a Wrap does not. Is there something maybe missing from the way the Wrap widget lays itself out that could be improved to act more like a Column?

Therefore, if you tell me it's not possible, then that can be enough. The unfortunate problem is that the flutter markdown plugin uses the Wrap widget for laying pieces out horizontally first, then vertically. This prevents us from using it in our layouts.
I will see about putting in a Feature Request with them to possibly use Wrap widgets only when absolutely necessary.

Would you say it is the fact that the Wrap overflows that is the issue?
I'm going to dig a bit more on this and see what's happening in the layout for Wrap. I'm going to try to reduce the code above to a more minimal sample. I think there is a way to achieve the desired layout with Wrap, just with a different composition since the sample was intended to work with Flex widgets. :)

Thanks @Piinks . You should be able to reduce the code quite a bit. I did it that way so anyone who works on it could easily see the difference between Column and Wrap.
It's important to note that we absolutely need to have a SingleChildScrollView with a IntrinsicHeight because we do need Flex widgets. I'm not sure what you're proposing about a new layout, but we'll need to still work just like the sample code does.
Thanks!

@Piinks ok here's a smaller example, that uses the layout we need to use, along with the Markdown plugin's MarkdownBody widget.
Code
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: WrapHomePage2(),
    );
  }
}

class WrapHomePage2 extends StatefulWidget {
  const WrapHomePage2();

  @override
  _WrapHomePage2State createState()  => _WrapHomePage2State();
}

class _WrapHomePage2State extends State<WrapHomePage2> {

  @override
  Widget build(BuildContext context) {

    final List<Widget> middleTexts = [];
    for (int i=0; i<15; i++) {
      middleTexts.add(
          Padding(
            padding: const EdgeInsets.only(top: 24.0, bottom: 24.0),
            child: Text("Yo"),
          )
      );
    }

    String shortText = "This is paragraph.";
    String longText = "This is paragraph. Making it run onto 2 lines causes the problem!";

    // use longText to cause an overflow!
    //String firstParagraph = shortText;
    String firstParagraph = longText;
    String secondParagraph = "This is some **bold** text!";

    TextStyle defaultStyle = TextStyle(
      fontSize: 16.0,
      color: Colors.black
    );

    return Scaffold(
        body: SafeArea(
          child: Padding(
            padding: const EdgeInsets.all(24),
            child: LayoutBuilder(
              builder: (context, constraints) {
                return SingleChildScrollView(
                    child: ConstrainedBox(
                      constraints: BoxConstraints(
                        minHeight: constraints.maxHeight,
                      ),
                      child: IntrinsicHeight(
                        child: Column(
                          mainAxisAlignment: MainAxisAlignment.start,
                          mainAxisSize: MainAxisSize.max,
                          crossAxisAlignment: CrossAxisAlignment.stretch,
                          children: [
                            Padding(
                              padding: EdgeInsets.only(top: 24.0),
                              child: Column(
                                mainAxisSize: MainAxisSize.max,
                                mainAxisAlignment: MainAxisAlignment.start,
                                crossAxisAlignment: CrossAxisAlignment.stretch,
                                children: [
                                  Text("Header text can go here", style: TextStyle(fontSize: 24),),
                                  Padding(
                                    padding: const EdgeInsets.only(top: 24.0),
                                    child: MarkdownBody(
                                        data: "$firstParagraph"
                                              "\n\n"
                                              "$secondParagraph",
                                        styleSheet: MarkdownStyleSheet.fromTheme(Theme.of(context)).copyWith(
                                            p: defaultStyle,
                                            a: defaultStyle.copyWith(decoration: TextDecoration.underline, color: Colors.blue),
                                            em: defaultStyle.copyWith(fontStyle: FontStyle.italic),
                                            strong: defaultStyle.copyWith(fontWeight: FontWeight.bold),
                                            blockSpacing: 24.0,
                                        ),
                                    ),
                                  ),
                                ],
                              ),
                            ),
                            Expanded(
                                child: Column(
                                  mainAxisSize: MainAxisSize.max,
                                  crossAxisAlignment: CrossAxisAlignment.stretch,
                                  children: middleTexts
                                )
                            ),
                            Padding(
                              key: ValueKey("footer"),
                              padding: const EdgeInsets.only(top: 24.0),
                              child: Column(
                                children: [
                                  Text("Bottom")
                                ],
                              ),
                            )
                          ],
                        ),
                      ),
                    )
                );
              }
            ),
          )
        )
    );
  }
}

pubspec.yaml
name: flutter_wrap_issues_test
description: A Flutter application to test the Wrap widget.

# The following defines the version and build number for your application.
# A version number is three numbers separated by dots, like 1.2.43
# followed by an optional build number separated by a +.
# Both the version and the builder number may be overridden in flutter
# build by specifying --build-name and --build-number, respectively.
# In Android, build-name is used as versionName while build-number used as versionCode.
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 1.0.0+1

environment:
  sdk: ">=2.3.0 <3.0.0"

dependencies:
  flutter:
    sdk: flutter

  flutter_markdown: 0.4.2

  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^0.1.2

dev_dependencies:
  flutter_test:
    sdk: flutter

# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec

# The following section is specific to Flutter.
flutter:

  # The following line ensures that the Material Icons font is
  # included with your application, so that you can use the icons in
  # the material Icons class.
  uses-material-design: true

  # To add assets to your application, add an assets section, like this:
  # assets:
  #  - images/a_dot_burr.jpeg
  #  - images/a_dot_ham.jpeg

  # An image asset can refer to one or more resolution-specific "variants", see
  # https://flutter.dev/assets-and-images/#resolution-aware.

  # For details regarding adding assets from package dependencies, see
  # https://flutter.dev/assets-and-images/#from-packages

  # To add custom fonts to your application, add a fonts section here,
  # in this "flutter" section. Each entry in this list should have a
  # "family" key with the font family name, and a "fonts" key with a
  # list giving the asset and other descriptors for the font. For
  # example:
  # fonts:
  #   - family: Schyler
  #     fonts:
  #       - asset: fonts/Schyler-Regular.ttf
  #       - asset: fonts/Schyler-Italic.ttf
  #         style: italic
  #   - family: Trajan Pro
  #     fonts:
  #       - asset: fonts/TrajanPro.ttf
  #       - asset: fonts/TrajanPro_Bold.ttf
  #         weight: 700
  #
  # For details regarding fonts from package dependencies,
  # see https://flutter.dev/custom-fonts/#from-packages

The issue stems whenever the Wrap widget has actual content that ends up having to lay itself out vertically because it can't lay itself out completely horizontally.
The following lines can be modified to see it working properly, or make it cause an overflow at the bottom of the page.
    // use longText to cause an overflow!
    //String firstParagraph = shortText;
    String firstParagraph = longText;

Might be related: #44529

Might be related: #44529

Ah yep, that seems about right @Piinks !

Some observations: This could be another instantiation of https://github.com/flutter/flutter/issues/48679. I noticed that the wrap always determines the hight of its Text children as 40 - no matter how many lines they have. That is the hight that a one line Text child would have in this context. Given https://github.com/flutter/flutter/issues/48679 that behavior is not surprising. And if I hack RenderWrap's computeMaxIntrinsicHeight to return the correct height for the multiline Text widget, the problem appears to go away. All strong indications that the problem may go away once we fix https://github.com/flutter/flutter/issues/48679.
Now, the more interesting question is why Column doesn't expose the https://github.com/flutter/flutter/issues/48679 bug.

To answer my previous question, Column works as expected because it calls child.getMaxIntrinsicHeight(extent) [1] on the child where extent is the width that's actually available for the Column. In that case, RenderText has no problems computing the correct height and everything works. Wrap on the other hand determines the max intrinsic height based on the text's intrinsic width:
https://github.com/flutter/flutter/blob/67e9b2945ec6b09d4c1719a9aa81578e95cd6071/packages/flutter/lib/src/rendering/wrap.dart#L412-L413
By definition, that returns the height of a single line of text. I think (I don't have all the details of how Wrap is implemented in my head) this code would need to change to use the new intrinsics API described in https://github.com/flutter/flutter/issues/48679#issuecomment-577456960.
[1] https://github.com/flutter/flutter/blob/67e9b2945ec6b09d4c1719a9aa81578e95cd6071/packages/flutter/lib/src/rendering/flex.dart#L622

Actually, when we were discussing the fix last in https://github.com/flutter/flutter/issues/48679#issuecomment-577456960 we noted:

Check Wrap if it suffers under similar problems and wether they can be solved with this API

Sounds like Wrap does suffer under the same problem. We need to do some more investigation to verify that the new proposed API in that comment would actually also fix this problem.

@goderbauer and @Piinks
I am curious why do we assume the size from
 final double childWidth = child.getMaxIntrinsicWidth(double.infinity);
 final double childHeight = child.getMaxIntrinsicHeight(childWidth);

to be the layout size where the incoming constraint is input width
shouldn't it be?
 final double childWidth = math.min(child.getMaxIntrinsicWidth(double.infinity), width);
 final double childHeight = child.getMaxIntrinsicHeight(childWidth);

It seems weird that we return childHeight as intrinsic height when the childWidth is bigger than the input width.
I put up a pr to do the above fix https://github.com/flutter/flutter/pull/63420, and it seems to fix the issue

 final double childWidth = math.min(child.getMaxIntrinsicWidth(double.infinity), width);
 final double childHeight = child.getMaxIntrinsicHeight(childWidth);

Makes sense to me, since we're going to wrap at width, not childWidth. To accurately compute the intrinsic height of a Wrap widget, it doesn't seem like there's a way to avoid effectively doing a complete layout, albeit in terms of getMaxIntrinsicHeight, given the incoming width.

Let's track this as https://github.com/flutter/flutter/issues/63302 since that one got the higher priority.


the instance of UndefinedObject should be immutable

Using Object.freeze() might be a solution?

Fixed for Pharo10 see commit https://github.com/PharoJS/PharoJS/tree/9d919b93197a42d8d0db0b79aea0151fb1008d93


Set spi chunk limit on linux with cfg!

Spi.write now uses a max byte chunk size of 4096 on linux device because of a default defined max byte transfer size of 4096 on most linux devices (https://raspberrypi.stackexchange.com/questions/65595/spi-transfer-fails-with-buffer-size-greater-than-4096)
Fixes #13

Tested and it's now working once more


Drag column in el-table,but the column's "sortable" attribute can not be  draged.

Problem:

Using element-ui in project，Drag column in el-table,but the column's "sortable" attribute can not be  dragged.
Init：

Dragged the Imp.  column :

code:

Please open this issue on element-ui. I cannot help with this.


Remove enableWebInspectorMenuItem outlet

Fixes a console warning about the removed property.

I forgot to remove an outlet to the Enable Web Inspector menu item from the storyboard after learning that the Debug menu was removed completely in release builds.


Replace include_once with include

Causing tests to fail in Laravel applications when ray.php is used.
In Laravel tests, when Ray is re-instantiated it attempts to load the config file using include_once. When calling include_once the first time, it will work as expected. On subsequent calls within the same process it will simply return true to indicate that the file has already been included. https://www.php.net/manual/en/function.include-once.php
This is a problem in unit tests, as the Laravel container is destroyed and recreated for each test. The first test will run, but subsequent tests will fail as the config is set to true instead of the intended array.
If loading the file from disk multiple times is a concern, we could add file caching. However as this issue has only shown itself in unit tests (in my very brief testing) I'm assuming it's not expected behaviour to load settings from the config file more than once in a request/process.

Thanks! This has been fixed in #30. Release coming soon!

Thanks! This has been fixed in #30. Release coming soon!


It was fine untill “learn Cotype embeddings”

Learn CoType embeddings...
./run.sh: line 20: code/Model/retype/retype: Permission denied

hi @johnarchie1, I think you might want to re-make the binary file to resolve the permission issue. Let me know if this works.

Hey!
I was trying to run the code and I got stuck at the same point -
Learn CoType embeddings...
code/Model/retype/retype: error while loading shared libraries: libgsl.so.19: cannot open shared object file: No such file or directory
I tried installing the GSL library using the below command -
sudo apt-get install libgsl-dev
But, I'm still getting the same error.
I'm unable to find any relevant fixes for this online as well.


Allow spaces inside struct tags. Trivial.

Summary: While trying to use a bencode'd torrent dictionary, I came across a
key "creation date" and "created by". They cannot be decoded into a struct
since spaces are not considered valid characters in the tag.
Fix that ^^^.

Thanks for the work.


Reorganize metric integration tests

My motivation for this is to be able to link to individual fixtures for each metric type (gauge, sum, non-monotonic sum, etc) for the standard and GMP exporter in documentation.
This is probably easiest to review commit-by-commit.

makes a function for the GMP config
simplifies naming of fixture files (e.g. removes most instances of "metrics" and "basic" from names)
adds GMP tests for simple scenarios.
Enables the normalization feature gate for GMP tests.  This demonstrates correct name translation in fixtures for the GMP exporter.
Change units of metrics to UCUM so the translation is tested.
Adds basic resource attributes to simple scenarios.
Disables service metric labels for fixtures
Change names of metrics and labels to include .s so that it tests sanitization.

rebased

clarified all of the test case names to make expectations clearer.


[kubelet] Enable authorization token webhook

When using an authentication method of Webhook on the kubelet, if you
expose the controller and scheduler outside of <IP_ADDRESS> then the
scheduler is no longer able to communicate with the API service.
Adding the --authorization-token-webhook=true flag to the kubelet
service seems to mitigate this problem

+1, merge this one in whenever you're ready. I discovered the same thing was necessary when I tried to catch up on what you've got going on with Prometheus.


Modify reduction rules to include type instantiation

As suggested a while ago, I've modified the evaluation rules in the PLC spec to include type instantiation.  I've left the CK machine unchanged and added some remarks pointing out the differences and claiming that we can prove that it doesn't make too much difference.  We may eventually want to modify the CK machine to match, and say that we do something different in practice (or even have two different versions of the machine).  See https://github.com/input-output-hk/plutus/issues/1145 in connection with this.
There are still a number of unresolved issues, like whether we want unsaturated builtins: see https://github.com/input-output-hk/plutus/pull/1162 . I was hoping for some input from Manuel, but he's away for a couple of weeks and will presumably have a lot of catching up to do when he gets back.  Maybe we should revisit these things before then.

lgtm


netflix not loading  (ec2)

I unable to load netflix after setting this up. I'm using osx and added the nameserver to /etc/resolver/netflix.com. Not sure what went wrong. adding the logs.
Please help

ubuntu@ip-172-31-32-65:~$ curl -sSL https://get.docker.com/ | sh && sudo usermod -aG docker $(who am i | awk '{print $1}') && cd /opt && sudo git clone https://github.com/ab77/netflix-proxy.git && cd netflix-proxy && ./build.sh
modprobe: FATAL: Module aufs not found.

+ sudo -E sh -c sleep 3; apt-get install -y -q linux-image-extra-3.13.0-74-generic linux-image-extra-virtual
Reading package lists...
Building dependency tree...
Reading state information...
The following extra packages will be installed:
  crda iw libnl-3-200 libnl-genl-3-200 linux-firmware
  linux-image-3.13.0-79-generic linux-image-extra-3.13.0-79-generic
  linux-image-generic wireless-regdb
Suggested packages:
  fdutils linux-doc-3.13.0 linux-source-3.13.0 linux-tools
  linux-headers-3.13.0-79-generic
The following NEW packages will be installed:
  crda iw libnl-3-200 libnl-genl-3-200 linux-firmware
  linux-image-3.13.0-79-generic linux-image-extra-3.13.0-74-generic
  linux-image-extra-3.13.0-79-generic linux-image-extra-virtual
  linux-image-generic wireless-regdb
0 upgraded, 11 newly installed, 0 to remove and 58 not upgraded.
Need to get 113 MB of archives.
After this operation, 433 MB of additional disk space will be used.
Get:1 http://us-west-2.ec2.archive.ubuntu.com/ubuntu/ trusty/main libnl-3-200 amd64 3.2.21-1 [44.5 kB]
Get:2 http://us-west-2.ec2.archive.ubuntu.com/ubuntu/ trusty/main libnl-genl-3-200 amd64 3.2.21-1 [10.2 kB]
Get:3 http://us-west-2.ec2.archive.ubuntu.com/ubuntu/ trusty-updates/main linux-image-3.13.0-79-generic amd64 3.13.0-79.123 [15.2 MB]
Get:4 http://us-west-2.ec2.archive.ubuntu.com/ubuntu/ trusty/main wireless-regdb all 2013.02.13-1ubuntu1 [6456 B]
Get:5 http://us-west-2.ec2.archive.ubuntu.com/ubuntu/ trusty/main crda amd64 1.1.2-1ubuntu2 [15.2 kB]
Get:6 http://us-west-2.ec2.archive.ubuntu.com/ubuntu/ trusty/main iw amd64 3.4-1 [51.7 kB]
Get:7 http://us-west-2.ec2.archive.ubuntu.com/ubuntu/ trusty-updates/main linux-firmware all 1.127.20 [24.5 MB]
Get:8 http://us-west-2.ec2.archive.ubuntu.com/ubuntu/ trusty-updates/main linux-image-extra-3.13.0-74-generic amd64 3.13.0-74.118 [36.8 MB]
Get:9 http://us-west-2.ec2.archive.ubuntu.com/ubuntu/ trusty-updates/main linux-image-extra-3.13.0-79-generic amd64 3.13.0-79.123 [36.7 MB]
Get:10 http://us-west-2.ec2.archive.ubuntu.com/ubuntu/ trusty-updates/main linux-image-generic amd64 <IP_ADDRESS>.85 [2240 B]
Get:11 http://us-west-2.ec2.archive.ubuntu.com/ubuntu/ trusty-updates/main linux-image-extra-virtual amd64 <IP_ADDRESS>.85 [1768 B]
Fetched 113 MB in 5s (22.5 MB/s)
perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
	LANGUAGE = (unset),
	LC_ALL = (unset),
	LC_CTYPE = "UTF-8",
	LANG = "en_US.UTF-8"
    are supported and installed on your system.
perl: warning: Falling back to the standard locale ("C").
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
Selecting previously unselected package libnl-3-200:amd64.
(Reading database ... 51150 files and directories currently installed.)
Preparing to unpack .../libnl-3-200_3.2.21-1_amd64.deb ...
Unpacking libnl-3-200:amd64 (3.2.21-1) ...
Selecting previously unselected package libnl-genl-3-200:amd64.
Preparing to unpack .../libnl-genl-3-200_3.2.21-1_amd64.deb ...
Unpacking libnl-genl-3-200:amd64 (3.2.21-1) ...
Selecting previously unselected package linux-image-3.13.0-79-generic.
Preparing to unpack .../linux-image-3.13.0-79-generic_3.13.0-79.123_amd64.deb ...
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
Done.
Unpacking linux-image-3.13.0-79-generic (3.13.0-79.123) ...
Selecting previously unselected package wireless-regdb.
Preparing to unpack .../wireless-regdb_2013.02.13-1ubuntu1_all.deb ...
Unpacking wireless-regdb (2013.02.13-1ubuntu1) ...
Selecting previously unselected package crda.
Preparing to unpack .../crda_1.1.2-1ubuntu2_amd64.deb ...
Unpacking crda (1.1.2-1ubuntu2) ...
Selecting previously unselected package iw.
Preparing to unpack .../archives/iw_3.4-1_amd64.deb ...
Unpacking iw (3.4-1) ...
Selecting previously unselected package linux-firmware.
Preparing to unpack .../linux-firmware_1.127.20_all.deb ...
Unpacking linux-firmware (1.127.20) ...
Selecting previously unselected package linux-image-extra-3.13.0-74-generic.
Preparing to unpack .../linux-image-extra-3.13.0-74-generic_3.13.0-74.118_amd64.deb ...
Unpacking linux-image-extra-3.13.0-74-generic (3.13.0-74.118) ...
Selecting previously unselected package linux-image-extra-3.13.0-79-generic.
Preparing to unpack .../linux-image-extra-3.13.0-79-generic_3.13.0-79.123_amd64.deb ...
Unpacking linux-image-extra-3.13.0-79-generic (3.13.0-79.123) ...
Selecting previously unselected package linux-image-generic.
Preparing to unpack .../linux-image-generic_<IP_ADDRESS>.85_amd64.deb ...
Unpacking linux-image-generic (<IP_ADDRESS>.85) ...
Selecting previously unselected package linux-image-extra-virtual.
Preparing to unpack .../linux-image-extra-virtual_<IP_ADDRESS>.85_amd64.deb ...
Unpacking linux-image-extra-virtual (<IP_ADDRESS>.85) ...
Processing triggers for man-db (<IP_ADDRESS>-1ubuntu1) ...
Setting up libnl-3-200:amd64 (3.2.21-1) ...
Setting up libnl-genl-3-200:amd64 (3.2.21-1) ...
Setting up linux-image-3.13.0-79-generic (3.13.0-79.123) ...
Running depmod.
update-initramfs: deferring update (hook will be called later)
Examining /etc/kernel/postinst.d.
run-parts: executing /etc/kernel/postinst.d/apt-auto-removal 3.13.0-79-generic /boot/vmlinuz-3.13.0-79-generic
run-parts: executing /etc/kernel/postinst.d/initramfs-tools 3.13.0-79-generic /boot/vmlinuz-3.13.0-79-generic
update-initramfs: Generating /boot/initrd.img-3.13.0-79-generic
run-parts: executing /etc/kernel/postinst.d/update-notifier 3.13.0-79-generic /boot/vmlinuz-3.13.0-79-generic
run-parts: executing /etc/kernel/postinst.d/x-grub-legacy-ec2 3.13.0-79-generic /boot/vmlinuz-3.13.0-79-generic
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
Searching for GRUB installation directory ... found: /boot/grub
Searching for default file ... found: /boot/grub/default
Testing for an existing GRUB menu.lst file ... found: /boot/grub/menu.lst
Searching for splash image ... none found, skipping ...
Found kernel: /boot/vmlinuz-3.13.0-74-generic
Found kernel: /boot/vmlinuz-3.13.0-79-generic
Found kernel: /boot/vmlinuz-3.13.0-74-generic
Replacing config file /run/grub/menu.lst with new version
Updating /boot/grub/menu.lst ... done

run-parts: executing /etc/kernel/postinst.d/zz-update-grub 3.13.0-79-generic /boot/vmlinuz-3.13.0-79-generic
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-3.13.0-79-generic
Found initrd image: /boot/initrd.img-3.13.0-79-generic
Found linux image: /boot/vmlinuz-3.13.0-74-generic
Found initrd image: /boot/initrd.img-3.13.0-74-generic
done
Setting up wireless-regdb (2013.02.13-1ubuntu1) ...
Setting up crda (1.1.2-1ubuntu2) ...
Setting up iw (3.4-1) ...
Setting up linux-firmware (1.127.20) ...
Setting up linux-image-extra-3.13.0-74-generic (3.13.0-74.118) ...
run-parts: executing /etc/kernel/postinst.d/apt-auto-removal 3.13.0-74-generic /boot/vmlinuz-3.13.0-74-generic
run-parts: executing /etc/kernel/postinst.d/initramfs-tools 3.13.0-74-generic /boot/vmlinuz-3.13.0-74-generic
update-initramfs: Generating /boot/initrd.img-3.13.0-74-generic
run-parts: executing /etc/kernel/postinst.d/update-notifier 3.13.0-74-generic /boot/vmlinuz-3.13.0-74-generic
run-parts: executing /etc/kernel/postinst.d/x-grub-legacy-ec2 3.13.0-74-generic /boot/vmlinuz-3.13.0-74-generic
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
Searching for GRUB installation directory ... found: /boot/grub
Searching for default file ... found: /boot/grub/default
Testing for an existing GRUB menu.lst file ... found: /boot/grub/menu.lst
Searching for splash image ... none found, skipping ...
Found kernel: /boot/vmlinuz-3.13.0-79-generic
Found kernel: /boot/vmlinuz-3.13.0-74-generic
Updating /boot/grub/menu.lst ... done

run-parts: executing /etc/kernel/postinst.d/zz-update-grub 3.13.0-74-generic /boot/vmlinuz-3.13.0-74-generic
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-3.13.0-79-generic
Found initrd image: /boot/initrd.img-3.13.0-79-generic
Found linux image: /boot/vmlinuz-3.13.0-74-generic
Found initrd image: /boot/initrd.img-3.13.0-74-generic
done
Setting up linux-image-extra-3.13.0-79-generic (3.13.0-79.123) ...
run-parts: executing /etc/kernel/postinst.d/apt-auto-removal 3.13.0-79-generic /boot/vmlinuz-3.13.0-79-generic
run-parts: executing /etc/kernel/postinst.d/initramfs-tools 3.13.0-79-generic /boot/vmlinuz-3.13.0-79-generic
update-initramfs: Generating /boot/initrd.img-3.13.0-79-generic
run-parts: executing /etc/kernel/postinst.d/update-notifier 3.13.0-79-generic /boot/vmlinuz-3.13.0-79-generic
run-parts: executing /etc/kernel/postinst.d/x-grub-legacy-ec2 3.13.0-79-generic /boot/vmlinuz-3.13.0-79-generic
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
Searching for GRUB installation directory ... found: /boot/grub
Searching for default file ... found: /boot/grub/default
Testing for an existing GRUB menu.lst file ... found: /boot/grub/menu.lst
Searching for splash image ... none found, skipping ...
Found kernel: /boot/vmlinuz-3.13.0-79-generic
Found kernel: /boot/vmlinuz-3.13.0-74-generic
Updating /boot/grub/menu.lst ... done

run-parts: executing /etc/kernel/postinst.d/zz-update-grub 3.13.0-79-generic /boot/vmlinuz-3.13.0-79-generic
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-3.13.0-79-generic
Found initrd image: /boot/initrd.img-3.13.0-79-generic
Found linux image: /boot/vmlinuz-3.13.0-74-generic
Found initrd image: /boot/initrd.img-3.13.0-74-generic
done
Setting up linux-image-generic (<IP_ADDRESS>.85) ...
Setting up linux-image-extra-virtual (<IP_ADDRESS>.85) ...
Processing triggers for libc-bin (2.19-0ubuntu6.6) ...
apparmor is enabled in the kernel and apparmor utils were already installed
+ sudo -E sh -c apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D
Executing: gpg --ignore-time-conflict --no-options --no-default-keyring --homedir /tmp/tmp.2X3Smqx00C --no-auto-check-trustdb --trust-model always --keyring /etc/apt/trusted.gpg --primary-keyring /etc/apt/trusted.gpg --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D
gpg: requesting key 2C52609D from hkp server p80.pool.sks-keyservers.net
gpg: key 2C52609D: public key "Docker Release Tool (releasedocker) " imported
gpg: Total number processed: 1
gpg:               imported: 1  (RSA: 1)
+ sudo -E sh -c mkdir -p /etc/apt/sources.list.d
+ dpkg --print-architecture
+ sudo -E sh -c echo deb [arch=amd64] https://apt.dockerproject.org/repo ubuntu-trusty main > /etc/apt/sources.list.d/docker.list
+ sudo -E sh -c sleep 3; apt-get update; apt-get install -y -q docker-engine

Fetched 24.7 kB in 2s (11.4 kB/s)
Reading package lists... Done
Reading package lists...
Building dependency tree...
Reading state information...
The following extra packages will be installed:
  aufs-tools cgroup-lite git git-man liberror-perl libsystemd-journal0
Suggested packages:
  git-daemon-run git-daemon-sysvinit git-doc git-el git-email git-gui gitk
  gitweb git-arch git-bzr git-cvs git-mediawiki git-svn
Recommended packages:
  yubico-piv-tool
The following NEW packages will be installed:
  aufs-tools cgroup-lite docker-engine git git-man liberror-perl
  libsystemd-journal0
0 upgraded, 7 newly installed, 0 to remove and 58 not upgraded.
Need to get 12.3 MB of archives.
After this operation, 65.6 MB of additional disk space will be used.
Get:1 http://us-west-2.ec2.archive.ubuntu.com/ubuntu/ trusty-updates/main libsystemd-journal0 amd64 204-5ubuntu20.18 [49.9 kB]
Get:2 http://us-west-2.ec2.archive.ubuntu.com/ubuntu/ trusty/universe aufs-tools amd64 1:3.2+20130722-1.1 [92.3 kB]
Get:3 http://us-west-2.ec2.archive.ubuntu.com/ubuntu/ trusty/main liberror-perl all 0.17-1.1 [21.1 kB]
Get:4 http://us-west-2.ec2.archive.ubuntu.com/ubuntu/ trusty-updates/main git-man all 1:1.9.1-1ubuntu0.2 [699 kB]
Get:5 http://us-west-2.ec2.archive.ubuntu.com/ubuntu/ trusty-updates/main git amd64 1:1.9.1-1ubuntu0.2 [2701 kB]
Get:6 http://us-west-2.ec2.archive.ubuntu.com/ubuntu/ trusty/main cgroup-lite all 1.9 [3918 B]
Fetched 12.3 MB in 1s (7947 kB/s)
perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
	LANGUAGE = (unset),
	LC_ALL = (unset),
	LC_CTYPE = "UTF-8",
	LANG = "en_US.UTF-8"
    are supported and installed on your system.
perl: warning: Falling back to the standard locale ("C").
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
Selecting previously unselected package libsystemd-journal0:amd64.
(Reading database ... 60947 files and directories currently installed.)
Preparing to unpack .../libsystemd-journal0_204-5ubuntu20.18_amd64.deb ...
Unpacking libsystemd-journal0:amd64 (204-5ubuntu20.18) ...
Selecting previously unselected package aufs-tools.
Preparing to unpack .../aufs-tools_1%3a3.2+20130722-1.1_amd64.deb ...
Unpacking aufs-tools (1:3.2+20130722-1.1) ...
Selecting previously unselected package docker-engine.
Preparing to unpack .../docker-engine_1.10.2-0~trusty_amd64.deb ...
Unpacking docker-engine (1.10.2-0~trusty) ...
Selecting previously unselected package liberror-perl.
Preparing to unpack .../liberror-perl_0.17-1.1_all.deb ...
Unpacking liberror-perl (0.17-1.1) ...
Selecting previously unselected package git-man.
Preparing to unpack .../git-man_1%3a1.9.1-1ubuntu0.2_all.deb ...
Unpacking git-man (1:1.9.1-1ubuntu0.2) ...
Selecting previously unselected package git.
Preparing to unpack .../git_1%3a1.9.1-1ubuntu0.2_amd64.deb ...
Unpacking git (1:1.9.1-1ubuntu0.2) ...
Selecting previously unselected package cgroup-lite.
Preparing to unpack .../cgroup-lite_1.9_all.deb ...
Unpacking cgroup-lite (1.9) ...
Processing triggers for man-db (<IP_ADDRESS>-1ubuntu1) ...
Processing triggers for ureadahead (0.100.0-16) ...
Setting up libsystemd-journal0:amd64 (204-5ubuntu20.18) ...
Setting up aufs-tools (1:3.2+20130722-1.1) ...
Setting up docker-engine (1.10.2-0~trusty) ...
docker start/running, process 29193
Setting up liberror-perl (0.17-1.1) ...
Setting up git-man (1:1.9.1-1ubuntu0.2) ...
Setting up git (1:1.9.1-1ubuntu0.2) ...
Setting up cgroup-lite (1.9) ...
cgroup-lite start/running
Processing triggers for libc-bin (2.19-0ubuntu6.6) ...
Processing triggers for ureadahead (0.100.0-16) ...
+ sudo -E sh -c docker version
Client:
 Version:      1.10.2
 API version:  1.22
 Go version:   go1.5.3
 Git commit:   c3959b1
 Built:        Mon Feb 22 21:37:01 2016
 OS/Arch:      linux/amd64

Server:
 Version:      1.10.2
 API version:  1.22
 Go version:   go1.5.3
 Git commit:   c3959b1
 Built:        Mon Feb 22 21:37:01 2016
 OS/Arch:      linux/amd64

If you would like to use Docker as a non-root user, you should now consider
adding your user to the "docker" group with something like:

  sudo usermod -aG docker ubuntu

Remember that you will have to log out and back in for this to take effect!

Cloning into 'netflix-proxy'...
remote: Counting objects: 819, done.
remote: Compressing objects: 100% (110/110), done.
remote: Total 819 (delta 58), reused 0 (delta 0), pack-reused 708
Receiving objects: 100% (819/819), 201.94 KiB | 0 bytes/s, done.
Resolving deltas: 100% (467/467), done.
Checking connectivity... done.
clientip=<IP_ADDRESS> ipaddr=<IP_ADDRESS> extip=<IP_ADDRESS> -r=1 -b=0 -i=0 -d=0
WARNING: enabling DNS recursion...
		allow-recursion { trusted; };
		recursion yes;
		additional-from-auth yes;
		additional-from-cache yes;
/opt/netflix-proxy /opt/netflix-proxy
adding IPv4 iptables rules..

resolver {
  nameserver <IP_ADDRESS>
  nameserver <IP_ADDRESS>
}
perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
	LANGUAGE = (unset),
	LC_ALL = (unset),
	LC_CTYPE = "UTF-8",
	LANG = "en_US.UTF-8"
    are supported and installed on your system.
perl: warning: Falling back to the standard locale ("C").
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
	LANGUAGE = (unset),
	LC_ALL = (unset),
	LC_CTYPE = "UTF-8",
	LANG = "en_US.UTF-8"
    are supported and installed on your system.
perl: warning: Falling back to the standard locale ("C").
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
  iptables-persistent
0 upgraded, 1 newly installed, 0 to remove and 58 not upgraded.
Need to get 10.2 kB of archives.
After this operation, 62.5 kB of additional disk space will be used.
Get:1 http://us-west-2.ec2.archive.ubuntu.com/ubuntu/ trusty/universe iptables-persistent all 0.5.7 [10.2 kB]
Fetched 10.2 kB in 0s (0 B/s)
perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
	LANGUAGE = (unset),
	LC_ALL = (unset),
	LC_CTYPE = "UTF-8",
	LANG = "en_US.UTF-8"
    are supported and installed on your system.
perl: warning: Falling back to the standard locale ("C").
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
Preconfiguring packages ...
Selecting previously unselected package iptables-persistent.
(Reading database ... 61862 files and directories currently installed.)
Preparing to unpack .../iptables-persistent_0.5.7_all.deb ...
 Removing any system startup links for /etc/init.d/iptables-persistent ...
Unpacking iptables-persistent (0.5.7) ...
Processing triggers for ureadahead (0.100.0-16) ...
Setting up iptables-persistent (0.5.7) ...
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
 * Loading iptables rules...                                                                                *  IPv4...                                                                                *  IPv6...                                                                                [ OK ]

Downloading/unpacking docker-compose
  Downloading docker-compose-1.6.2.tar.gz (128kB): 128kB downloaded
  Running setup.py (path:/tmp/pip_build_root/docker-compose/setup.py) egg_info for package docker-compose

    warning: no previously-included files found matching 'README.md'
    warning: no previously-included files matching '*.pyc' found anywhere in distribution
    warning: no previously-included files matching '*.pyo' found anywhere in distribution
    warning: no previously-included files matching '*.un~' found anywhere in distribution
Downloading/unpacking cached-property>=1.2.0,<2 (from docker-compose)
  Downloading cached_property-1.3.0-py2.py3-none-any.whl
Downloading/unpacking docopt>=0.6.1,<0.7 (from docker-compose)
  Downloading docopt-0.6.2.tar.gz
  Running setup.py (path:/tmp/pip_build_root/docopt/setup.py) egg_info for package docopt

Requirement already satisfied (use --upgrade to upgrade): PyYAML>=3.10,<4 in /usr/lib/python2.7/dist-packages (from docker-compose)
Downloading/unpacking requests>=2.6.1,<2.8 (from docker-compose)
  Downloading requests-2.7.0-py2.py3-none-any.whl (470kB): 470kB downloaded
Downloading/unpacking texttable>=0.8.1,<0.9 (from docker-compose)
  Downloading texttable-0.8.4.tar.gz
  Running setup.py (path:/tmp/pip_build_root/texttable/setup.py) egg_info for package texttable

Downloading/unpacking websocket-client>=0.32.0,<1.0 (from docker-compose)
  Downloading websocket_client-0.35.0.tar.gz (193kB): 193kB downloaded
  Running setup.py (path:/tmp/pip_build_root/websocket-client/setup.py) egg_info for package websocket-client

Downloading/unpacking docker-py>=1.7.0,<2 (from docker-compose)
  Downloading docker-py-1.7.2.tar.gz (68kB): 68kB downloaded
  Running setup.py (path:/tmp/pip_build_root/docker-py/setup.py) egg_info for package docker-py

Downloading/unpacking dockerpty>=0.4.1,<0.5 (from docker-compose)
  Downloading dockerpty-0.4.1.tar.gz
  Running setup.py (path:/tmp/pip_build_root/dockerpty/setup.py) egg_info for package dockerpty

Requirement already satisfied (use --upgrade to upgrade): six>=1.3.0,<2 in /usr/lib/python2.7/dist-packages (from docker-compose)
Downloading/unpacking jsonschema>=2.5.1,<3 (from docker-compose)
  Downloading jsonschema-2.5.1-py2.py3-none-any.whl
Downloading/unpacking enum34>=1.0.4,<2 (from docker-compose)
  Downloading enum34-1.1.2.tar.gz (46kB): 46kB downloaded
  Running setup.py (path:/tmp/pip_build_root/enum34/setup.py) egg_info for package enum34

Downloading/unpacking backports.ssl-match-hostname (from websocket-client>=0.32.0,<1.0->docker-compose)
  Downloading backports.ssl_match_hostname-<IP_ADDRESS>.tar.gz
  Running setup.py (path:/tmp/pip_build_root/backports.ssl-match-hostname/setup.py) egg_info for package backports.ssl-match-hostname

Downloading/unpacking functools32 (from jsonschema>=2.5.1,<3->docker-compose)
  Downloading functools32-3.2.3-2.tar.gz
  Running setup.py (path:/tmp/pip_build_root/functools32/setup.py) egg_info for package functools32

    warning: no files found matching '*.txt'
    no previously-included directories found matching 'build'
    no previously-included directories found matching 'dist'
    no previously-included directories found matching '.git*'
Installing collected packages: docker-compose, cached-property, docopt, requests, texttable, websocket-client, docker-py, dockerpty, jsonschema, enum34, backports.ssl-match-hostname, functools32
  Running setup.py install for docker-compose

    warning: no previously-included files found matching 'README.md'
    warning: no previously-included files matching '*.pyc' found anywhere in distribution
    warning: no previously-included files matching '*.pyo' found anywhere in distribution
    warning: no previously-included files matching '*.un~' found anywhere in distribution
    Installing docker-compose script to /usr/local/bin
  Running setup.py install for docopt

  Found existing installation: requests 2.2.1
    Not uninstalling requests at /usr/lib/python2.7/dist-packages, owned by OS
  Running setup.py install for texttable

  Running setup.py install for websocket-client
    changing mode of build/scripts-2.7/wsdump.py from 644 to 755

    changing mode of /usr/local/bin/wsdump.py to 755
  Running setup.py install for docker-py

  Running setup.py install for dockerpty

  Running setup.py install for enum34

  Running setup.py install for backports.ssl-match-hostname

  Running setup.py install for functools32

    warning: no files found matching '*.txt'
    no previously-included directories found matching 'build'
    no previously-included directories found matching 'dist'
    no previously-included directories found matching '.git*'
Successfully installed docker-compose cached-property docopt requests texttable websocket-client docker-py dockerpty jsonschema enum34 backports.ssl-match-hostname functools32
Cleaning up...

 - For authorized use only/CN=VeriSign Class 3 Public Primary Certification Authority - G3
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIFijCCBHKgAwIBAgIQQ9vZa/gIJmgo9kj2egocUjANBgkqhkiG9w0BAQsFADB+
MQswCQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAd
BgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxLzAtBgNVBAMTJlN5bWFudGVj
IENsYXNzIDMgU2VjdXJlIFNlcnZlciBDQSAtIEc0MB4XDTE1MDQxNDAwMDAwMFoX
DTE3MDQxMjIzNTk1OVowfTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNBTElGT1JO
SUExEjAQBgNVBAcMCUxvcyBHYXRvczEWMBQGA1UECgwNTmV0ZmxpeCwgSW5jLjET
MBEGA1UECwwKT3BlcmF0aW9uczEYMBYGA1UEAwwPd3d3Lm5ldGZsaXguY29tMIIB
IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuahXKETW08vuetLrBeK6Ldf5
SssEHYoJDTkj/CNX+h9jCkJLuU35kYpHHeIBSQFM1nOf6VTLBI6EwRSoaJYZeUfL
kjV/0SSFLpCyxWIeiqRxoZPJi8e+GyAedP8//B6pgJEX/Xqv0twe3OG2IQ1vVX0J
vbzTWl7in6xOUfN0XN6H9blqCSWJdRnIQE511xnJn8GfjbHm2hVbeuPBoogqTvoa
8/8n30BlEFG3GVi9sn2/O+HBsShrfgvmWk91dlH77Jg8koE0L9Qigv8VGltQmpbd
bWt39re8AQ8i52wlsp5tudhO9q+lWwMN3PrX14PZqKk3sjsOxUa8nDU5Uq63sQID
AQABo4ICAzCCAf8wgbQGA1UdEQSBrDCBqYITYWNjb3VudC5uZXRmbGl4LmNvbYIO
Y2EubmV0ZmxpeC5jb22CCm5ldGZsaXguY2GCC25ldGZsaXguY29tghJzaWdudXAu
bmV0ZmxpeC5jb22CDnd3dy5uZXRmbGl4LmNhgg93d3cubmV0ZmxpeC5jb22CEHd3
dzEubmV0ZmxpeC5jb22CEHd3dzIubmV0ZmxpeC5jb22CEHd3dzMubmV0ZmxpeC5j
b20wCQYDVR0TBAIwADAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUH
AwEGCCsGAQUFBwMCMGUGA1UdIAReMFwwWgYKYIZIAYb4RQEHNjBMMCMGCCsGAQUF
BwIBFhdodHRwczovL2Quc3ltY2IuY29tL2NwczAlBggrBgEFBQcCAjAZGhdodHRw
czovL2Quc3ltY2IuY29tL3JwYTAfBgNVHSMEGDAWgBRfYM9hkFXfhEMUimAqsvV6
9EMY7zArBgNVHR8EJDAiMCCgHqAchhpodHRwOi8vc3Muc3ltY2IuY29tL3NzLmNy
bDBXBggrBgEFBQcBAQRLMEkwHwYIKwYBBQUHMAGGE2h0dHA6Ly9zcy5zeW1jZC5j
b20wJgYIKwYBBQUHMAKGGmh0dHA6Ly9zcy5zeW1jYi5jb20vc3MuY3J0MA0GCSqG
SIb3DQEBCwUAA4IBAQCjzCPCZ0QQFwU/ehGm970LQVN/CXtuFI6UvJCMsFXeAaS1
8qDkl9tW/9ihpaUvy7GabfCEglBnnhYlWhcu1jGYVdoJH6fBYWKH6cKGS/NQpRu/
647cpvCVS1STW0vYJF5beKDeP0Rik9YMbiDAOjK3/z0bBxpNFf/xTRlbTOfJeJJa
ZkLvqIuRidMdyvZ6Pw4FkpYLyqSrTA49fs6zutp76ek+KhvHr9nGylKWWm+mg2RP
DM880iAq7A0VQY/eHt3PJCmPyEdO5Q0UG2UQ12OhYXIwpr8ZnwjhtxPMYY/eYdGE
DWkrV+u0kzRIg6UcDlgT44Avd56+e5v7Z8IM+ZTU
-----END CERTIFICATE-----
subject=/C=US/ST=CALIFORNIA/L=Los Gatos/O=Netflix, Inc./OU=Operations/CN=www.netflix.com
issuer=/C=US/O=Symantec Corporation/OU=Symantec Trust Network/CN=Symantec Class 3 Secure Server CA - G4
---
No client certificate CA names sent
---
SSL handshake has read 3400 bytes and written 441 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES128-GCM-SHA256
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES128-GCM-SHA256
    Session-ID: 94985E2666B15FFEC3D0B64F63F50BD63068FD6AF2017A3293B51C6D95ACAD93
    Session-ID-ctx:
    Master-Key: 3C59C6B48A1CF4C8B8E1A31CCA07C0F1BFC910D823472C1C48186EDDCFBF8F2471F94D192E8393067DAB72C01A7723F3
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket lifetime hint: 300 (seconds)
    TLS session ticket:
    0000 - df d0 91 ec 62 a0 07 d7-68 24 6d e4 ed 4c 8e 7d   ....b...h$m..L.}
    0010 - de fe 3a bf 49 05 a4 9c-82 39 83 8e 04 4b 0c cf   ..:.I....9...K..
    0020 - 2e 00 06 17 77 6d d7 25-4a a4 e6 74 a6 2f 89 35   ....wm.%J..t./.5
    0030 - 64 89 a4 c3 56 6e d4 e0-2d d1 fa 53 f0 41 bb d4   d...Vn..-..S.A..
    0040 - 56 e3 87 e0 72 0a 61 30-60 a0 0d cb 2d 62 f5 68   V...r.a0`...-b.h
    0050 - 2e 28 dd 92 47 73 fc 81-32 a1 9d 65 c7 59 5d c5   .(..Gs..2..e.Y].
    0060 - ed fa 6e ac de a7 41 f1-9c 08 13 fe 61 0c e9 d1   ..n...A.....a...
    0070 - 00 8c 29 8c 3a a3 12 e3-3a 20 93 0a 27 d1 5d 41   ..).:...: ..'.]A
    0080 - 7b 10 fe b2 40 9c 1f a6-4d 9c 08 6d 1f b6 ee d0<EMAIL_ADDRESS>    0090 - a3 bc 87 e6 a2 c3 16 52-a1 ca f5 20 72 68 7c 2d   .......R... rh|-
    00a0 - 0c f5 97 03 e6 3a 23 8f-31 01 a6 a8 2f 8e ae 63   .....:#.1.../..c

    Start Time:<PHONE_NUMBER>
    Timeout   : 300 (sec)
    Verify return code: 20 (unable to get local issuer certificate)
---
DONE
/opt/netflix-proxy
Change your DNS to <IP_ADDRESS> and start watching Netflix out of region.
Done!

Also, try assigning an elastic IP on your EC2 instance, if you are not using one already.

Please take this to #netflix-proxy on freenode (IRC).
Cheers!

Thanks got it work :)

Good work, don't forget to vote (link top of readme) if you haven't already. I am starting to capture stats for analysis over time.
-- ab1

On 4 Mar 2016, at 18:07, darkpssngr<EMAIL_ADDRESS>wrote:
Thanks got it work :)
—
Reply to this email directly or view it on GitHub.

Sure. :)


request is deprecated, replace the request module.

🐛 Bug Report

request is deprecated, replace the request module. https://github.com/request/request/issues/3142
See the npm dependency tree below, which comes from installing jest alone:

To Reproduce
Steps to reproduce the behavior:

npm install jest
Notice the deprecation WARN

npm WARN deprecated<EMAIL_ADDRESS>request-promise-native has been deprecated because it extends the now deprecated request package, see https://github.com/request/request/issues/3142
npm WARN deprecated<EMAIL_ADDRESS>Please see https://github.com/lydell/urix#deprecated
npm WARN deprecated<EMAIL_ADDRESS>this library is no longer supported
npm WARN deprecated<EMAIL_ADDRESS>https://github.com/lydell/resolve-url#deprecated
npm WARN deprecated<EMAIL_ADDRESS>request has been deprecated, see https://github.com/request/request/issues/3142

Expected behavior
No deprecation warnings as a result of installing jest.
Notes
Please excuse my ignorance if this issue has already been brought up or is covered in another issue. I looked through both the issues and the pull requests and did not see anything that specifically calls out this WARN message or the fact that the request npm package is deprecated.

This is from jsdom, for which an issue has already been filed:
https://github.com/jsdom/jsdom/issues/2792

Yep, tracking the jsdom issue is better. Whenever they release a version not using request we'll update here 👍

@SimenB Sure, but closing this ticket doesn't mean it's resolved and then someone like me might come and create another ticket for the same thing because they couldn't find it addressed in your backlog.
I was aware that this was a dependency issue, and not that the jest team would have to write code to replace request directly. There are other alternatives to jsdom that people are using, with this in mind.
I believe that the jsdom team is very close to resolving this dependency issue and I appreciate the lookahead for updating this package once that occurs.

Still waiting for jsdom update...


SVN says verion 2.2.7-git

trunk and branches says in /md/md_version.h 2.2.7-git. Should it not be 2.2.7 ?
Builds fine under Windows, running/testing now.

Fixed in Apache subversion. Thanks for spotting.


Introduce API tokens to limit access [optional]

Admins should be able to restrict access, so only authorized clients can poll server information.

Problem: How to retrieve GET params such as ?accesstoken=abc


[Guide Needed] Add Guide for keeping main files

Add Guide for keeping main files after decompilation using python-exe-unpacker  ,i mean  which files are necessary to deobfuscate script

@MikeAndarsons
I dont have time to do it, but you actually dont need to unpack, only run the obfuscated python exe and inject the dll to it.
Download the git content, go to dearmor/main.py and edit line 18 remove sys.executable (and the "," that comes after that)
Then install and run
In the -i option just put your exe instead

@ErezAmihud
Thanks for answering,I changed main.py as you said  and installed.
Now i am using command like:
dearmor -i "App.exe"
That App is opening but in CMD i got error:

Traceback (most recent call last):
  File "C:\Users\WINDOWS10\AppData\Local\Programs\Python\Python37\Scripts\dearmor-script.py", line 11, in <module>
    load_entry_point('dearmor==0.1', 'console_scripts', 'dearmor')()
  File "C:\Users\WINDOWS10\AppData\Local\Programs\Python\Python37\lib\site-packages\dearmor-0.1-py3.7-win-amd64.egg\dearmor\__main__.py", line 35, in main_cli
    main(print_user_messages=True, **parser.parse_args().__dict__)
  File "C:\Users\WINDOWS10\AppData\Local\Programs\Python\Python37\lib\site-packages\dearmor-0.1-py3.7-win-amd64.egg\dearmor\__main__.py", line 22, in main
    inject(child[0].pid, str(Path(__file__).parent.parent / "dearmor-library" / "lib" / "dearmor.dll"))
IndexError: list index out of range

@ErezAmihud Any Solution? or can you suggest other methods to deobfuscate ?

@MikeAndarsons
Hi, I uploaded the package to the pypi artifactory at https://pypi.org/project/dearmor/0.2/ I think it will solve your problems.
Using -i with the exe should be fine. The traceback you sent looks like it is a problem with the compilation script in setup.py. Install from the pypi.org and it will be fine

Hello, why is there no response after I type dearmor -i xxx.exe

Hello, why is there no response after I type dearmor -i xxx.exe

I edited to comment above, decompile the exe first to something you can run python <file>.
Also install all the dependencies packages


Function Overloading Overhaul

The Problem
I think function overloading needs some changes in order for it to really function in the way that most people would find useful. This is especially problematic with event systems, as I and others have encountered.
Example
Currently, let's say I have the following function that I want to provide an overload for:
function Shape:listen(event, callback) end

Using @overload
The first logical option is to use @overload:
---@class Shape
local Shape = {}

---Subscribe to an event on this shape
---@param event "Destroy"
---@param callback fun(self: Shape)
---@overload fun(event: "Repair", callback: fun(self: Shape, amount: number))
function Shape:listen(event, callback) end

But there is a problem, when using methods (:), the first parameter only gets completions for the first @param and ignores the @overload entirely.

Ok, so for testing, let's replace the method (:) with a static function (.):
---@class Shape
local Shape = {}

---Subscribe to an event on this shape
---@param event "Destroy"
---@param callback fun(self: Shape)
---@overload fun(event: "Repair", callback: fun(self: Shape, amount: number))
function Shape.listen(event, callback) end

This still isn't great, we are still offered both callbacks even though the info we have entered only matches the @overload. At least the first parameter was completed this time.

Multiple Definitions
So then maybe we try defining multiple functions where each event param has the type set to the event name we are looking for:
---@class Shape
local Shape = {}

---Subscribe to an event on this shape
---@param event "Destroy"
---@param callback fun(self: Shape)
function Shape:listen(event, callback) end

---Subscribe to an event on this shape
---@param event "Repair"
---@param callback fun(self: Shape, amount: number)
function Shape:listen(event, callback) end

Now, even as methods (:) we are receiving correct completions for the first parameter... nice! However, we are still receiving two completions for the callback - there is no narrowing happening. The completion also shows the event as "Destroy", which is incorrect for our second definition as we have only allowed "Repair".

At least when defining the function twice, we are able to write a separate description for each of them as well as their @params and @returns. However, we receive a warning saying that we have a duplicate field.
Proposed Solution
The issue where overloads work on functions but not methods seems to be an obvious bug that should be fixed, but as for how functions should be overloaded, I think that is a larger problem.
If we take a look at how TypeScript does this, they seem to go for the multiple definition approach within their interfaces:
/**
 * Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements.
 * @param start The zero-based location in the array from which to start removing elements.
 * @param deleteCount The number of elements to remove.
 * @returns An array containing the elements that were deleted.
 */
splice(start: number, deleteCount?: number): T[];
/**
 * Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements.
 * @param start The zero-based location in the array from which to start removing elements.
 * @param deleteCount The number of elements to remove.
 * @param items Elements to insert into the array in place of the deleted elements.
 * @returns An array containing the elements that were deleted.
 */
splice(start: number, deleteCount: number, ...items: T[]): T[];

I personally also prefer to just define the function multiple times so I can be as detailed as possible when defining the different uses for a function. It would also help greatly with documenting event systems as you could have a function per event rather than writing a bunch of @overloads that skip out on a lot of information.
I think if a file has a @meta tag, it should allow duplicate functions and use them as overloads. This would also require the issue of narrowing to be fixed so that we can use the value of previous parameters to figure out which overload to use.

This would also fix another issue I'm having where classes that have both a static and method variant of the same function aren't narrowing, eg:
---@meta

---@class Foo
---@overload fun(): Foo
Foo = {}

---@param eventName string
---@param callback function
function Foo.Subscribe(eventName, callback) end

---@param eventName string
---@param callback function
function Foo:Subscribe(eventName, callback) end

...

local inst = Foo()
inst:Subscribe(" --> Provides autocompletion for the static method, treating the string as the callback

Yeah, I don't know of a way where you can change the callback param given a certain first parameter, which is a very common use-case for an event system or asynchronous code. Hopefully changing how overloads work and improving the narrowing makes it possible 🙂

This problem has been partially solved. However, the inconvenient thing is that it is impossible to display comments for each event separately.
---Registers a callback function for an event.\
---`function(client[, topic[, message]])`. The first parameter is always the client object itself.\
---Any remaining parameters passed differ by event:
--- @class Emit
--- @field on fun(self, event: string, cb: function)
--- @field on fun(self, event: '"connect"',  cb: fun(client))
--- @field on fun(self, event: '"connfail"', cb: fun(client, reason: integer))  #If the event is `"connfail"`, the 2nd parameter will be the connection failure code.
--- @field on fun(self, event: '"message"',  cb: fun(client, topic: string, message: string)) @If event is `"message"`, the 2nd and 3rd parameters are received topic and message, respectively, as Lua strings.
local emit = {}

emit:on("message", function (client, topic, message) end)

or
---comment**********
---@class EmitL
---@field listen fun(self, eventName: string, cb: function)
--- comment for e1
---@field listen fun(self, eventName: '"e1"', cb: fun(i:integer)):table
---@field listen fun( eventName: '"e2"', cb: fun(s:string))  @comment for e2
---@field listen fun(self, eventName: '"e3"', cb: fun(i:integer, s:string))  @comment for e3
local emitL = {}

emitL:listen("e1", function (i) end)
emitL.listen("e2", function (s) end)

Poking my head in to add ideas here (read: personal wish list features :wink:). I think a good solution/step would be to support functions as first-class objects alongside classes.
The issue with function aliases (fun(...))
The fun(...):... syntax is so terse/dense that it becomes cumbersome to use for all but the most simple cases. Also, if you're properly namespacing your custom types in order to not pollute the global ns, you wind up with reeeeeally long lines:
--- This is my function. If you pass it a callback, it does something different.
---
---@param foo string
---@return integer
---@overload fun(foo: string, callback: libraryname.functionname.callback):libraryname.functionname.result
local function do_the_thing(foo) end

---@alias libraryname.functionname.callback fun(result: string|nil, error: string|nil):boolean

An alternative: standalone function definitions
This would make things a lot more flexible.
The @function label
Example:
--- This is an optional callback.
--- Because it has it's own block (instead of `fun(...)`), I can write doc strings for everything (yay!).
---
--- The `@function` label comes first here for consistency with `@class`
---
---@function libraryname.functionname.callback
---@param result? string  # result text (`nil` if there was an error)
---@param error?  string  # an error message (always `nil` when `result` is not `nil`)
---@return boolean success

--- This is my function.
---
---@param foo string
---@return integer
local function do_the_thing(foo) end

--- This is also my function, but when passed a callback.
---
---@function libraryname.functionname-with-callback
---@param foo string
---@param callback libraryname.functionname.callback
---@return libraryname.functionname.result

Reusing @class
Alternatively, the @class label/decorator/keyword could be overloaded to support function annotations:
--- This is an optional callback.
--- Because it has it's own block (instead of `fun(...)`), I can write doc strings for everything (yay!).
---
---@class libraryname.functionname.callback : function
---@param result? string  # result text (`nil` if there was an error)
---@param error?  string  # an error message (always `nil` when `result` is not `nil`)
---@return boolean success

Applying the overload
Now, to apply libraryname.functionname-with-callback as an overload of do_the_thing, we have options...
Overload at the target by passing a type name to @overload
--- This is my function.
---
---@param foo string
---@return integer
---@overload libraryname.functionname-with-callback
local function do_the_thing(foo) en

Annotate at the source with a new @overloads label
--- This is also my function, but when passed a callback.
---
---@function libraryname.functionname-with-callback
---@param foo string
---@param callback libraryname.functionname.callback
---@return libraryname.functionname.result
---@overloads `do_the_thing` -- resolve "do_the_thing" as a lua identifier in local scope

If we allow @function to be applied to actual code, then we can take it a step further and allow overloading from different sources/files, which would be nice for anyone working with framework-y code

libraryname.lua

--- This is my function.
---
---@function libraryname.functionname
---@param foo string
---@return integer
local function do_the_thing(foo) en

other.lua

--- This is also my function, but when passed a callback.
---
---@function libraryname.functionname-with-callback
---@param foo string
---@param callback libraryname.functionname.callback
---@return libraryname.functionname.result
---
---@overloads libraryname.functionname -- resolve "libraryname.functionname" as a fully-qualified type name

The benefit of @function and @overloads is that now it's possible to create function annotations without having to render actual code, which would be a big win IMO.

I think adding a @function annotation would be a nice replacement for the fun(...):... syntax. I too dislike the current way of defining functions because of all the information that is missing and because they have to be one line.
@overload could also be replaced with @overloads which refers to a @function or normal Lua function. For this to really work though, we would probably need to namespace annotations, like @flrgh said. It would be nice if this could be handled automatically so that an annotation on a function myFunction in myLibrary.lua could be referred to by using myLibrary.myFunction.

Here is another issue I am experiencing with @overload, the returns are not narrowing and it results in a union type... no matter how I try to define it:
---@param event "A"
---@param callback fun()
---@return boolean
---@overload fun(event: "B", callback: fun()): string
local function listen(event, callback) end

local result = listen("A", function() end)
local result = listen("B", function() end)

---@overload fun(event: "A", callback: fun()): boolean
---@overload fun(event: "B", callback: fun()): string
local function listen2(event) end

local result = listen("A", function() end)
local result = listen("B", function() end)

result is boolean|string in all of these cases

One other thing with this is that if you're trying to overload something that already exists, it will give you both definitions, which is not ideal (observed by @carsakiller and myself).
On top of that, if you try to nil out an existing function (which perhaps isn't really supported because why would you do it?) doesn't do anything. I'd like to be able to remove an existing documented function that's in the LÖVE documents, but doesn't exist for LÖVE Potion.
See #1834 for the discussion about this.

It's enough to introduce @function tag which would define a new instance function type that can be referenced by @type
@overload per doc isn't intended to be used for function declaration, it's OOP concept for already declared funcs
TypeScript is bad in most of the cases; don't bring anything from that language; you may learn how some things are done, but let's not borrow anything blindly; the TS has too many pitfalls and syntax allows you to write very unoptimized, completely dumb code.

I'm wondering if there is any status on this or plans for the @function tag?

Looks like same issue

reply to: https://github.com/LuaLS/lua-language-server/issues/1456#issuecomment-2299892018
It's unrelated to @overload, it's because in the fun() syntax, there is an ambiguity between function has multi return and function has multiple arguments.

When you write fun(valu, key, cnt): any
=> this is a function that returns any
However when you write fun(valu, key, cnt): any, tbl: table
=> this is also a valid syntax that a function return any and table
so it get parsed as a multi return of the fun() that you defined for consume
rather than a 2nd tbl argument for Table.Each itself

You have to add () to the fun() in your first @overload to eliminate this ambiguity:
local Table = {}

---@overload fun(consume: (fun(value, key, cnt): any), tbl: table): nil, integer
---@overload fun(consume: (fun(value, key, cnt): any)): fun(tbl: table): nil, integer
Table.ForEach = {}  --[[@as function]]

local mock = { 'a', 'b', 'c', 'd', 'e', 'f' }

local each = Table.ForEach(function () end)

local res1, cnt1 = Table.ForEach(function () end, mock) -- res1: nil, cnt1: integer
local res2, cnt2 = each(mock)   -- res2: nil, cnt2: integer

This should work for your case 😄 @vaderkos

I want to add that, I tested some of the incorrect type narrowing issues mentioned in the thread and they actually work in latest version of v3.10.5 🎉 (maybe get fixed in the middle, or by the recent #2765 )
I tested the following and they work, so they maybe closed 😄

the code snippet that @carsakiller provided above: https://github.com/LuaLS/lua-language-server/issues/1456#issuecomment-1244896279
https://github.com/LuaLS/lua-language-server/issues/1898
https://github.com/LuaLS/lua-language-server/issues/2102

Wow, the original example does seem to work!
I still have trouble with CC:Tweaked's event system, though, as an example.
I don't want to define the function 30+ times with all the same description, so I can't just do what is in the original example. But overloads also don't work for me here. There is no way to handle the string... variadic returns for computer_command events, and because os.pullEvent() can be used with custom events, it means I have to also accept any string and return potentially any... value.

Any?
---@async
---@param event? ccTweaked.os.event
---@return any ...
---@overload fun(event: "alarm"): "alarm", integer
---@overload fun(event: "char"): "char", string
---@overload fun(event: "computer_command"): "computer_command", string...
function os.pullEvent(event) end

This results in all of my returns being any even when they are explicitly defined as having a set value for that case.
local event, alarmID = os.pullEvent("alarm")
  --> ccTweaked.os.event, any
local event, character = os.pullEvent("char")
  --> ccTweaked.os.event, any
local event, arg1, arg2, arg3 = os.pullEvent("computer_command")
  --> ccTweaked.os.event, any, any, any

Unknown?
---@async
---@param event? ccTweaked.os.event
---@return unknown ...
---@overload fun(event: "alarm"): "alarm", integer
---@overload fun(event: "char"): "char", string
---@overload fun(event: "computer_command"): "computer_command", string...
function os.pullEvent(event) end

This results in everything being unknown and I don't even get a warning for :sub-ing an unknown.
local event, alarmID = os.pullEvent("alarm")
  --> ccTweaked.os.event, integer|unknown
local event, character = os.pullEvent("char")
  --> ccTweaked.os.event, string|unknown
local event, arg1, arg2, arg3 = os.pullEvent("computer_command")
  --> ccTweaked.os.event, string|unknown, unknown, unknown

local s = character:sub(0, 3)
-- no unknown warning on :sub-ing a possibly unknown value??

---@type unknown
local a -- cannot infer unknown type

I have tried a bunch of combinations of different tricks but am still unable to get os.pullEvent working nicely with a proper description, completion, and type checking for all 30+ events plus custom events.
... pull requests accepted 😆

There is no way to handle the string...

Yeah, seems <type>... is not supported in fun() syntax when using it in @overload. This only works when you write it by redefining functions under a @meta definition file (where you can use @return string ... there)
LuaLS's official wiki also suggested to use @meta with function definition instead of just using @overload 😂
https://luals.github.io/wiki/annotations/#overload

I think the issue you encountered here is that you have to support custom events, in which you have to add string to the @alias ccTweaked.os.event. This just messes up the luals type narrowing feature, because all your built-in event (alarm / char / etc) can be casted to string. So the base function signature that returns any ... always matches and cannot be filtered out. 😕
If you remove the base function signature, then everything works fine. (ofc I know this cannot be the solution, because you have to support custom events).
Some immature idea
When I was trying to fix https://github.com/LuaLS/lua-language-server/issues/2758#issuecomment-2227686601, I leant that the logic of finding matched call resides in here: https://github.com/LuaLS/lua-language-server/blob/ddc96bd1ec0be95a985ab82531763578bf7eb793/script/vm/function.lua#L359
Currently it just uses vm.canCastType when checking if each param can match that in the overload. I have some immature idea that, maybe we can try to further narrow the funcs[]:

The first pass (current logic) will check param type can be casted to function definition param type.
As "alarm" can be casted to string, it matches
=> so the basic function signature is included there (which causes the problem)
We may actually try to further narrow it, say in the second pass, we keep only the longest exact match in param list (without the use of vm.canCastType, but I don't know how currently)
Take your code as an example, when you write os.pullEvent("alarm"), in the 1st pass it matches 2 function signatures when using the vm.canCastType(): the overload one "alarm" and the basic one string

However if we require exact match, only the overload one can match the 1st param "alarm"
So the overload one has an exact match of length 1, while the basic one has length 0
=> finally we only keep function signature that are equal to longest exact match length, which is only the overload one 🤔

As this is unrelated to @function which this issue suggested, I should probably open a new one to track it when my idea become more mature 😄 Stay tuned @carsakiller

reply to: https://github.com/LuaLS/lua-language-server/issues/1456#issuecomment-1209686771
(this maybe a bit late 🙈 )
I think I know why your example code doesn't work as expected. It's because how LuaLS filter out unmatched function signatures. It first check the params count: https://github.com/LuaLS/lua-language-server/blob/ddc96bd1ec0be95a985ab82531763578bf7eb793/script/vm/function.lua#L392-L408
In your code, you have Foo.Subscribe(eventName, callback) and Foo:Subscribe(eventName, callback)

the first one has 2 params (min = 2, max = 2)
the second one can be viewed as Foo.Subscribe(self, eventName, callback)
=> that's 3 params (min = 3, max = 3)

So when you are typing the code in the middle inst:Subscribe("
it can be viewed as inst.Subscribe(self, "

only 2 params are defined (amin = 2, amax = 2)
thus the Foo:Subscribe(eventName, callback) overload get filtered out
it requires 3 params, which is more than you supplied in this intermediate code
(the if amin >= min and amax <= max check failed)
so only the Foo.Subscribe(eventName, callback) left ...
=> then LuaLS infers that your "" is the callback param 🤦♂

If the callback param is declared optional then LuaLS can type narrow it correctly, because in that case min = 2, max = 3
---@meta

---@class Foo
---@overload fun(): Foo
Foo = {}

---@param eventName string
---@param callback? function
function Foo.Subscribe(eventName, callback) end

---@param eventName string
---@param callback? function # add the `?` to callback
function Foo:Subscribe(eventName, callback) end

local inst = Foo()
inst:Subscribe(" --> this will be eventName now

I don't know if this type narrow logic can be optimized, but I don't think an @function will help this case either. What I can be certain is that it should be another issue to track it. 🤔 @Derpius

LuaLS's official wiki also suggested to use @meta with function definition instead of just using @overload 😂
https://luals.github.io/wiki/annotations/#overload

Someone really smart and good-looking must've written that, @tomlau10 😉

After 2 days (probably more) of trying to find a solution, I think I got it! Here is what we have, the following is what people have already been doing to get type narrowing correct with the callback completion, as described by @serg3295:
---@class Emitter
---@field on fun(self: self, event: string, cb: function)
---@field on fun(self: self, event: "success",  cb: fun(client))
---@field on fun(self: self, event: "fail", cb: fun(client, reason: integer))  # Cool Message 1
---@field on fun(self: self, event: "message",  cb: fun(client, topic: string, message: string))
local emitter = {}

emit:on("message", function (client, topic, message) end)

Problem with this as described is you won't be able to have descriptions which is what the proposed @function is for in the context of this problem (it is useful for other things overall and should be added), a workaround for this is using aliases with enumerations ---|, so like this:
---@alias events.success
---|"success" # Emitted on successful connections - important to have only a single entry in this alias

---@alias events.fail
---|"fail" # Emitted on failures

---@alias events.message
---|"message" # Emitted when a message is received

--- @class Emitter
--- @field on fun(self: self, event: string, cb: function)
--- @field on fun(self: self, event: events.success,  cb: fun(client))
--- @field on fun(self: self, event: events.fail, cb: fun(client, reason: integer))  # Cool Message 1
--- @field on fun(self: self, event: events.message,  cb: fun(client, topic: string, message: string))
local emitter = {}

emit:on("message", function (client, topic, message) end) -- now you see a description that otherwise would have no been possible to see

It is tedious when you have a lot of events like this, but not like I will be the on responsible for the large annotation packages in the market place 😝

reply to: https://github.com/LuaLS/lua-language-server/issues/1456#issuecomment-2439765409
I tested the given code snippet, although the auto suggestion is not narrowed correctly at the beginning, it works after typing f and retrigger auto completion 🤔
emitter:on("success", f--< retrigger completion here after typing `f`

I guess this is due to different logic of type narrow between completion and match call

The type narrow in a match call is more complicated and thus perform better, but it will first check the current call arguments count match

i.e. the signature on fun(self: self, event: events.success,  cb: fun(client)) requires 3 arguments: self, event, cb
but when we are still writing the call emitter:on("success",, there are only 2 arguments: self, event
thus luals didn't perform the more complicated type narrow process
matchCall > vm.getExactMatchedFunctions > vm.getMatchedFunctions: https://github.com/LuaLS/lua-language-server/blob/389496827f20bb6d75a2fb2826099f13e9c18730/script/vm/compiler.lua#L600-L611
it will check the amin, amax (min/max argument) count: https://github.com/LuaLS/lua-language-server/blob/389496827f20bb6d75a2fb2826099f13e9c18730/script/vm/function.lua#L430-L446

On the other hand, when trying to type narrow during a completion, luals simply checks if there is a string type event name argument and a literal match.
Therefore when you changed to use alias inside the fun() annotation, the type narrow in completion fails to work 😕
https://github.com/LuaLS/lua-language-server/blob/389496827f20bb6d75a2fb2826099f13e9c18730/script/vm/compiler.lua#L962-L977

I see. What would be the suggested "fixes"?
I would imagine fixing the completion step is the preferred route here, by allowing alias types / alias strings along side string values. Maybe also make it so that the match all case account for the 1 argument difference?
Not really experienced around this code which appears complex to me.
Reminder that the alias solution is a hack around the last proposed one, which ends up duplicated event suggestions.  This one feels easier to fix, by merging equal values as one suggestion instead of letting it duplicate, this merge should account for things like comments.

I would imagine fixing the completion step is the preferred route here, by allowing alias types / alias strings along side string values.

Yes, I agree that this is the preferred route.
I am trying to come up with a fix for this use case, and after some trial and error I think I nailed it 👀 .
I will open a PR for it later after more testing. 😄 @Bilal2453
Here is my work in progress (subject to change): https://github.com/tomlau10/lua-language-server/commit/4de84f337c6e548925925d10db1e6e33db20cbeb


@chain one-liner nested in an outer @chain may not work?

This might be "overusing" @chain, but I found there was an inconsistency between one-liner and nested blocks with this:
This works:
@chain read(open("Day-8.txt"), String) begin
    strip
    split("\n")
    map(_) do _
        map(split(_, "|")) do _
            @chain _ begin
                strip
                split
            end
        end
    end
end

But making the inner @chain into a one-line version fails with "Malformed nested @chain macro"
@chain read(open("Day-8.txt"), String) begin
    strip
    split("\n")
    map(_) do _
        map(split(_, "|")) do _
            @chain _ strip split
        end
    end
end

FYI I tried using do x rather than do _, but to no avail.
I'm not sure the nesting is a good design — I was attempting to parse a heavily nested string, and was using new indentation to signify each level of nesting — so I'm putting this in for info, rather than something that's important per-se.
Thanks for the excellent package, I'm really enjoying using it

Tangentially — if there were a way of combining the map ... do x with @chain; that would be ideal; e.g.:
@chain read(open("Day-8.txt"), String) begin
    strip
    split("\n")
    @. begin
        split("|")
        @. begin
            strip
            split
        end
    end
end

The single line nested chain error is a bug, fixed that here https://github.com/jkrumbiegel/Chain.jl/pull/43
The other thing is that you should not really repeat the underscore so often, it can work if the variable inside map just shadows the outer one, but it's not very clear. Better like this:
@chain "a\nb" begin
    strip
    split("\n")
    map(_) do x
        map(split(x, "|")) do y
            @chain y strip split
        end
    end
end

Ah and I guess you don't need the underscore in the nested @chain anyway, because it's implicitly inserted

The single line nested chain error is a bug, fixed that here #43

Thanks a lot!
I agree re the underscores. That's related to something I liked about the idea of combining the map ... do x with @chain (with, say @. as in the example, though maybe there are better names) — the whole block could be point-free.

Re the narrower issue — confirmed it works — thanks again. I'll close this issue