how to have libraries import libraries from the same package? - dart

The dart page http://pub.dartlang.org/doc/#adding-a-dependency describes how you can have a dart file (parser_test.dart) import files from its own package using the 'import "package:..." style of import. It seems to imply this is a good thing - better than using relative paths. This example shown is for a file in test which appears to be special. But, then why does it not make sense for importing same package lib files from a lib in the package. Maybe it does make sense, but if so the pub update does not make it convenient.
foo/
/lib/
foo_lib_1.dart
foo_lib_2.dart
src/
foo_lib_1/
foo_lib_1_impl.dart
foo_lib_2/
foo_lib_2_impl.dart
Assume foo_lib_2 uses foo_lib_1. There are two options for foo_lib_2.dart:
import "../foo_lib_1.dart";
import "packages:foo/foo_lib_1.dart";
My guess is the suggested approach is the first for any such import that resides under lib. The reason I think this is pub update seems to automagically provide a soft link in the packages folder of any of bin, test, or example to foo, like foo -> ../lib. Yet, it does not do the same for the packages folder in top level foo. This means to get the second type of import (i.e. the packages import) to work you need to add:
foo:
path: lib
to the dependencies of foo in the pubspec.yaml. Is there any advantage or disadvantage for a library to use the package style import to import another library (not in test, bin, or example) from its own package? Is there a reason for the apparent inconsistency?
After accepting the answer below, I still am not seeing it. Here is what I'm seeing in a shell session and I would like to reconcile this behavior with the answer. Any explanations appreciated. I am using emacs instead of DartEditor, thus the old-school command line approach here.
### Show all files, one dart library file and one yaml, plus empty
### lib and test folders
user#user-thinkpad:/tmp/uml_codegen_sample$ ls -R
.:
lib pubspec.yaml test
./lib:
plusauri.dart
./test:
### Show contents of pubspec
user#user-thinkpad:/tmp/uml_codegen_sample$ cat pubspec.yaml
name: domain_model
version: 0.0.1
description: >
Auto-generated support from /home/user/plusauri/modeling/plusauri.xmi.json
dependencies:
ebisu:
path: /home/user/open_source/codegen/dart/ebisu
### Run pub install and show the changes. Note there is a soft
### link to packages from test, but not lib.
user#user-thinkpad:/tmp/uml_codegen_sample$ pub install
Resolving dependencies...
Dependencies installed!
Some packages that were installed are not compatible with your SDK version 0.4.7+5.r21658 and may not work:
- 'pathos' requires >=0.5.0+1
You may be able to resolve this by upgrading to the latest Dart SDK
or adding a version constraint to use an older version of a package.
user#user-thinkpad:/tmp/uml_codegen_sample$ ls -R
.:
lib packages pubspec.lock pubspec.yaml test
./lib:
plusauri.dart
./packages:
domain_model ebisu pathos
./test:
packages
### Note here the program does not work, and suspiciously pub
### install put no packages link under lib like it did test
user#user-thinkpad:/tmp/uml_codegen_sample$ dart lib/plusauri.dart
Unable to open file: /tmp/uml_codegen_sample/lib/packages/ebisu/ebisu_utils.dart'file:///tmp/uml_codegen_sample/lib/plusauri.dart': Error: line 5 pos 1: library handler failed
import "package:ebisu/ebisu_utils.dart" as EBISU_UTILS;
^
### Copy the same dart file to test to show that it can run there
### just fine
user#user-thinkpad:/tmp/uml_codegen_sample$ cp lib/plusauri.dart test/
user#user-thinkpad:/tmp/uml_codegen_sample$ dart test/plusauri.dart
Main for library plusauri
user#user-thinkpad:/tmp/uml_codegen_sample$
### Finally, manually create the soft link in lib, to show it will
### then run
user#user-thinkpad:/tmp/uml_codegen_sample$ ln -s ../packages lib/packages
user#user-thinkpad:/tmp/uml_codegen_sample$ dart lib/plusauri.dart
Main for library plusauri

Actually, you can definitely import using the package:foo/foo_lib_1.dart syntax without needing to change your pubspec.yaml or even creating a pubspec.yaml in the first place!
You can see that this is true from a language level, in this test: https://github.com/dart-lang/bleeding_edge/blob/master/dart/tests/standalone/package/packages/package1.dart
and an example of this in the wild is: https://github.com/kevmoo/hop.dart/blob/master/lib/hop_tasks.dart#L17
I do not think there is any benefit from writing one way or another except that writing relative paths is slightly shorter.
From a project structure point of view, I would use relative path imports when I am drilling into subdirectories that are not going to be exposed to the user. src is generally seen as implementation specific details that won't be visible to external users, so use relative paths to your heart's content.
However, if you're working within multiple directories, then you should use package: imports to reinforce the idea that the parts are stand-alone and interchangeable. Within the lib directory itself, you want to say that these two libraries, although they might rely on each other, can live separately and are not bound by their physical location.
I would recommend not ever using ../ in your imports, as that is fragile and may break in strange ways if/when you modify directory structure or deploy.

Related

Cargo registry directory

How do I specify another directory where cargo keeps the unpacked sources, e.g. on Windows this is %userprofile%/.cargo/registry/src?
I working that is going to be a collection of crates like:
myproject-tree/
foo
+Cargo.toml
bar
+Cargo.toml
So I would like the dependencies to be loaded in unpacked somewhere near the myproject-tree directory, e.g.
myproject-tree/
cargo-cache/
I think that would make it easier to inspect the code of dependencies (e.g. in the code editors with file tree UI). I can see that there is CARGO_HOME that seems like it has something like this, but it does not look convenient, e.g. each time I am going to work with myproject-tree I have to set it.
Looks like this is possible. I think it called "vendoring" and repositories like Fuchsia and Mozilla has source copy of third-party crates in their repositories. This is what I have found:
Cargo supports "Source replacement" thing configured in .cargo/config, which can be in a project relative dir:
With this configuration Cargo attempts to look up all crates in the
directory "vendor" rather than querying the online registry at
crates.io. Using source replacement Cargo can express:
Vendoring - custom sources can be defined which represent crates on
the local filesystem. These sources are subsets of the source that
they're replacing and can be checked into packages if necessary.
Mirroring - sources can be replaced with an equivalent version which
acts as a cache for crates.io itself.
There is a tool https://github.com/alexcrichton/cargo-vendor that can used to populate the directory with source codes of the dependencies:
Simply run cargo vendor inside of any Cargo project:

Haskell, create stack or cabal file from source directory

In Haskell: Given an existing directory tree (with sub-directors) of source files.
Is there a way to get a .cabal or .stack file, created automatically, with all the necessary dependents (references to the import files that are embedded inside the source file) embedded in the command file,with no need to manualy editing the command file.
In other words, get a command file that I will be able to run "straight out of the box" without the regular methods of stack new/stack build etc,commands?
cabal init will create a file that lists all the modules in your sourcedir for you. But you will still need to provide the package dependencies yourself. This is because a module Foo.Bar.Baz may come from multiple packages -- hence the package you intend to import must be explicitly specified.

py.test trying to import wrong module on Travis but not locally

I have a Travis CI build that is failing; py.test seems to be trying to import the wrong module, though I cannot reproduce this locally. I expect it to import tools.lint.tests.test_lint, not lint.tests.test_lint, as you can see in the traceback, given that build has --full-trace! This leads to the error beneath it when it tries to do a relative import from the tools package.
The short trackback is:
___________________ ERROR collecting lint/tests/test_lint.py ___________________
.tox/py27/lib/python2.7/site-packages/py/_path/local.py:650: in pyimport
__import__(modname)
lint/__init__.py:1: in <module>
from . import lint
lint/lint.py:15: in <module>
from .. import localpaths
E ValueError: Attempted relative import beyond toplevel package
Given the name of the top level package is just the directory that the repo is in, I wouldn't be surprised to see that differ—but I'd still expect to see it there!
Take a look at the path Travis has that file at: /home/travis/build/w3c/wpt-tools/lint/tests/test_lint.py. The directory called tools on your computer is called wpt-tools on Travis, following the name of the repo on GitHub.
Vitally, wpt-tools isn't a valid Python package name, as Python packages cannot contain hyphens in the name. (They have to be an identifier). This leads py.test to conclude it isn't a package, despite the __init__.py contained within, and hence it doesn't include it in the import path, leading to the error when code tries a relative import from what is meant to be the top-level package.
There's a couple of solutions here:
The possibly simple one is renaming the repository so that it doesn't contain any hyphens, though obviously if you're an established repository this is likely undesirable.
Get Travis CI to run the code from some directory, by copying/moving the repository to a directory whose name doesn't contain a hyphen, at the start of before_install, using something like:
before_install:
- mv `pwd` /tmp/tools
- cd /tmp/tools
This will then run all the install and later steps from /tmp/tools, which will allow everything to run as expected.
(Note you cannot use a symbolic link here as os.getcwd() in Python will eliminate the link from the path, returning the real path, leading that seeming workaround not to work at all.)

Usage of local dart library

I have created some local libraries in my dart lib directory.
These libraries are visible in dart packages for each newly created folder in the web directory. However, when I attempt to access them using the dart's package nomenclature eg package:reg/name.dart, the system always generates an error.
I think I am missing something.
I have read http://pub.dartlang.org/doc/package-layout.html but this did not help me either.
You need to ensure that the name you're using as the package matches that in pubspec.yaml.
Eg. if in pubspec.yaml you havename: my_app and your file is at lib\my_library.dart then you need to use import 'package:my_app/my_library.dart';.

"Bundling" external libraries in Erlang?

I have an erlang application I have been writing which uses the erldis library for communicating with redis.
Being a bit of a newbie with actually deploying erlang applications to production, I wanted to know if there was anyway to 'bundle' these external libraries with the application rather than installing into my system wide /usr/lib/erlang/lib/ folder.
Currently my directory structure looks like...
\
--\conf
--\ebin
--\src
I have a basic Makefile that I stole from a friend's project, but I am unsure how to write them properly.
I suspect this answer could involve telling me how to write my Makefile properly rather than just which directory to plonk some external library code into.
You should really try to avoid project nesting whenever possible. It can lead to all sorts of problems because of how module/application version is structured within Erlang.
In my development environment, I do a few things to simplify dependancies and multiple developed projects. Specifically, I keep most of my projects sourced in a dev directory and create symlinks into an elibs dir that is set in the ERL_LIBS environmental variables.
~/dev/ngerakines-etap
~/dev/jacobvorreuter-log_roller
~/dev/elib/etap -> ~/dev/ngerakines-etap
~/dev/elib/log_roller -> ~/dev/jacobvorreuter-log_roller
For projects that are deployed, I've either had package-rpm or package-apt make targets that create individual packages per project. Applications get boot scripts and init.d scripts for easy start/stop controls but libraries and dependancy projects just get listed as package dependencies.
I use mochiweb-inspired style. To see example of this get your copy of mochiweb:
svn checkout http://mochiweb.googlecode.com/svn/trunk/ mochiweb
and use
path/to/mochiweb/scripts/new_mochiweb.erl new_project_name
to create sample project of the structure (feel free to delete everything inside src afterwards and use it for your project).
It looks like this:
/
/ebin/
/deps/
/src/
/include/
/support/
/support/include.mk
Makefile
start.sh
ebin contains *.beam files
src contains ***.erl files and local *.hrl files
include contains global *.hrl files
deps contains symlinks to root directories of dependencies
Makefile and include.mk takes care of including appropriate paths when project is built.
start.sh takes care of including appropriate paths when project is run.
So using symlinks in deps directory you are able to fine tune the versions of libraries you use for every project. It is advised to use relative paths, so afterwards it is enough to rsync this structure to the production server and run it.
On more global scale I use the following structure:
~/code/erlang/libs/*/
~/code/category/project/*/
~/code/category/project/*/deps/*/
Where every symlink in deps points to the library in ~/code/erlang/libs/ or to another project in the same category.
The simplest way to do this would be to just create a folder named erldir and put the beams you need into it and then in your start script just use the -pa flag to the erlang runtime to point out where it should fetch the beams.
The correct way (at least if you buy into the OTP distribution model) would be to create a release using reltool (http://www.erlang.org/doc/man/reltool.html) or systools (http://www.erlang.org/doc/man/systools.html) which includes both your application and erldis.
Add the external libraries that you need, anywhere you want them, and add them to your ERL_LIBS environment variable. Separate the paths with colon in unix or semicolon in dos.
Erlang will add the "ebin"-named subdirs to its code loading path.
Have your *.app file point out the other applications it depends on.
This is a good halfway-there approach for setting up larger applications.
Another way is put your lib path in ~/.erlang.
code:add_pathz("/Users/brucexin/sources/mochiweb/ebin").
code:add_pathz("/Users/brucexin/sources/webnesia/ebin").
code:add_pathz("./ebin").
code:add_pathz("/Users/brucexin/sources/erlang-history/ebin/2.15.2").

Resources