My project read the file if I clone it from github, but if I use the hex package fails

Hey, guys. I got this package.

if you clone it and run it on your machine it works properly

iex -S mix
Pronouncingex.pronounce("are you kidding me", :ipa)
# => ɑɹ ju kɪdɪŋ m̩i

I uploaded it to hex in case someone can be useful, but if I add it as a package to a project I see that the file

cmudict-0.7b.txt

cannot be found

I guess the problem turns out to be the path of the file, this file is in the root of the package, so I just put this

https://github.com/cocodrino/pronouncingex/blob/master/lib/pronunciadata.ex
File.stream!("cmudict-0.7b.txt")

how should I define the paths within my packet so that it doesn’t fail to use hex?

thank you guys!

Such data belongs into Priv, and even then I think it should be compiled into the module directly by reading the file into a module attribute during compile time.

2 Likes

@clag: You need to specify this file for mix configuration for hex.pm. For more information please see: Publishing a package article.

2 Likes

To conform to a package definition and fit with the OTP structure:

  1. Your file should live in the priv directory. This is the standard place to put files your package needs to use.

  2. In your mix.exs file you will need something like:

def project do
  [
    app: :cmu
    package: package()
    ...
  ]
end

def package do
  [
    "lib",
    "priv",
    "config",
    "mix.exs",
    ...
  ]
end

Then in your code:

File.stream!(to_string(:code.priv_dir(:cmu))<>"/cmudict-0.7b.txt")
2 Likes

This won’t work if the cwd changes or it’s an embedded tar or so, you should always get the priv directory by asking for the priv directories location like: File.string!(to_string(:code.priv_dir(:cmu))<>"/cmudict-0.7b.txt")
Or whatever the application name is should go inside the :code.priv_dir/1 call

1 Like

You’re right of course, that was lazy of me. Edited to correct.

2 Likes

Also, it returns an iolist (charlist specifically), so need to run to_string(...) on it as I updated my post if you want to update yours too, my bad. ^.^;

1 Like

And thats why doing this at 3:08am isn’t such a great idea :slight_smile:

2 Likes

thanks for the reply @kip @OvermindDL1, I put the code

File.stream!(to_string(:code.priv_dir(:cmu))<>"/cmudict-0.7b.txt")

now I’m getting the error

  ** (Protocol.UndefinedError) protocol String.Chars not implemented for {:error, :bad_name}. This protocol is implemented for: Atom, BitString, Date, DateTime, Float, Integer, List, NaiveDateTime, Time, URI, Version, Version.Requirement
(elixir) /build/elixir/src/elixir-1.7.2/lib/elixir/lib/string/chars.ex:3: String.Chars.impl_for!/1
(elixir) /build/elixir/src/elixir-1.7.2/lib/elixir/lib/string/chars.ex:22: String.Chars.to_string/1

running the local repository seems that the problem is here

iex(1)> :code.priv_dir(:cmu)
{:error, :bad_name}

can you check the github repo, why not just use File.stream!(“priv/cmudict-0.7b.txt”)???

the priv folder is include in the mix.exs…what could be the issue here???

thank you so much!

It would not work in prod environment after deployment, because you have no source code tree there. :code.priv_dir/1 is used to solve problem with such extra files.

If I remember correctly {:error, :bad_name} happens when your app (here :cmu) is not found. Not sure, but you need to add some extra configuration to mix.exs in project which uses your library. However I don’t had such error for a long time, so I simply do not remember it.

1 Like

If you look at my example above (which I modified a couple of times) you will see in mix.exs:

def project do
  [
    app: :cmu
    package: package()
    ...
  ]
end

Then you can see that your apps :app is consistent when using :code.priv_dir(:app)

1 Like

thank so much @Eiji @kip it works correctly…thank you guys!

1 Like