JRuby - Calling Java class - Cannot import class 'com.foo.bar' as 'bar' - jruby

I am getting the below error when in import a custom jar.
require 'java'
require '/path/custom.jar'
java_import 'com.foo.bar'
The error reported is:
cannot import class com.foo.bar' asbar'
I am trying to built a custom logstash input plugin.

as it says because java_import 'com.foo.bar' is likely not a class-name, so you need to specify a (qualified) class-name or you can import the whole package with a java_package declartion
if 'com.foo.bar' is a "valid" Java class-name (which is quite bad practice) it simply won't work since in Ruby constant names start with upper-case, you will be left with doing the import into the current name space (module) on your own e.g. : Bar = Java::com.foo.bar

Related

How to pickle function from imported module with dill

I'm trying to pickle functions with dill. I want to include the whole function and not just a reference to it. Here are my two files:
fun.py:
import dill
from foo import ppp
def qqq(me):
return me + 1
print(dill.dumps(ppp, protocol=4, recurse=True, byref=True))
print(dill.dumps(qqq, protocol=4, recurse=True, byref=True))
And foo.py
def qqq(me):
return me + 1
When I run fun.py I get the following output:
b'\x80\x04\x95\x0f\x00\x00\x00\x00\x00\x00\x00\x8c\x03foo\x94\x8c\x03ppp\x94\x93\x94.'
b'\x80\x04\x95\x90\x00\x00\x00\x00\x00\x00\x00\x8c\ndill._dill\x94\x8c\x10_create_function\x94\x93\x94(h\x00\x8c\n_load_type\x94\x93\x94\x8c\x08CodeType\x94\x85\x94R\x94(K\x01K\x00K\x01K\x02KCC\x08|\x00d\x01\x17\x00S\x00\x94NK\x01\x86\x94)\x8c\x02me\x94\x85\x94\x8c\x06fun.py\x94\x8c\x03qqq\x94K\x04C\x02\x00\x01\x94))t\x94R\x94}\x94h\rNN}\x94Nt\x94R\x94.'
I want to be able to make the first line of output be more similar to the second line, and actually encapsulate the function without the need for a context when reloaded later. Is there a way to do this?
Thanks so much!
James
If the module (foo) is installed on both computers, then there should be no need to do anything but import the function. So, I'll assume the question is in regard to a module that is only installed on the first machine.
It also depends on whether the module foo is "installed" on sys.path or is just available in the current directory. See:
https://github.com/uqfoundation/dill/issues/123
If it's only available in the current directory, either use dill to pickle the file itself or use something like dill.source.getsource to extract the source of the module as a string, and then transfer the string as a "pickle" (this is what ppft does).
Generally, however, dill pickles imported functions by reference, and thus assumes they are available on both sides of the load/dump.

How to use SQLAlchemy Utils in a SQLAlchemy model

I'm trying to create a user model that uses UUID as primary key:
from src.db import db # SQLAlchemy instance
import sqlalchemy_utils
import uuid
class User(db.Model):
__tablename__ = 'user'
id = db.Column(sqlalchemy_utils.UUIDType(binary=True), primary_key=True, nullable=False)
But when I generate the migrations I receive:
File "/home/pc/Downloads/project/auth/venv/lib/python3.6/site-packages/alembic/runtime/environment.py", line 836, in run_migrations
self.get_context().run_migrations(**kw)
File "/home/pc/Downloads/project/auth/venv/lib/python3.6/site-packages/alembic/runtime/migration.py", line 330, in run_migrations
step.migration_fn(**kw)
File "/home/pc/Downloads/project/auth/migrations/versions/efae4166f832_.py", line 22, in upgrade
sa.Column('id', sqlalchemy_utils.types.uuid.UUIDType(length=16), nullable=False),
NameError: name 'sqlalchemy_utils' is not defined`
I had try to explicity inform the module I'm using like this and use a 'internal' implementation that SQLAlchemy
Obs: If I manualy import the sqlalchemy_utils in the /migrations/version/efae4166f832_.py and remove the length that is generated automaticaly sa.Column('id', sqlalchemy_utils.types.uuid.UUIDType(length=16), nullable=False) it works fine
I generate the migrations using a generate.py script:
from src import create_app
from src.db import db
from flask_migrate import Migrate
# Models
from src.user.models.user import User
app = create_app()
migrate = Migrate(app, db)`
Obs: MySQL engine
I expect that when I generate migration it generate a user model that uses UUID implemented from SQLAlchemy Utils as primary key
You have just to add:
import sqlalchemy_utils
to your script.py.mako inside migrations folder
Thanks, Marco, but I have already fixed it. I have put the import import sqlalchemy_utils inside env.py and script.py.mako, I have also put the following function:
def render_item(type_, obj, autogen_context):
"""Apply custom rendering for selected items"""
if type_ == "type" and isinstance(obj, sqlalchemy_utils.types.uuid.UUIDType):
# Add import for this type
autogen_context.imports.add("import sqlalchemy_utils")
autogen_context.imports.add("import uuid")
return "sqlalchemy_utils.types.uuid.UUIDType(), default=uuid.uuid4"
# Default rendering for other objects
return False
Inside the env.py, and at the same file I have set render_item=render_item in the function run_migrations_online:
context.configure(
...,
render_item=render_item,
...
)
I researched to do this automatically, but I couldn't find nothing that could help me.
The order of the operations matter:
export FLASK_APP=manage.py
flask db init
Do the tutorial above
flask db migrate
flask db upgrade
Background
It would be ideal if you didn't have to go and manually edit each migration file with an import sqlalchemy_utils statement.
Looking at the Alembic documentation, script.py.mako is "a Mako template file which is used to generate new migration scripts." Therefore, you'll need to re-generate your migration files, with Mako already importing sqlalchemy_utils as part of the migration file generation.
Fix
If possible, remove your old migrations (they're probably broken anyway), and add the import sqlalchemy_utils like so to your script.py.mako file:
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils #<-- line you add
${imports if imports else ""}
then just rerun your alembic migrations:
alembic revision --autogenerate -m "create initial tables"
when you go to look at your migration file you should see sqlalchemy_utils already imported via the mako script.
hope that helps.
Adding import sqlalchemy_utils in the script.py.mako file will automatically import this line on all the migration files that are generated and resolve the issue.
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
${imports if imports else ""}
Add the import sqlalchemy_utils line to the newly-created migrations/versions/{hash}_my_comment.py file. However, this will only fix the problem for that specific step of the migration. If you expect that you'll be making lots of changes to columns which reference sqlalchemy_utils, you should probably do something more robust like Walter's suggestion. Even then, though, it looks like you may need to add code to properly deal with each column type you end up using.
NB: Despite seeing the suggestion in multiple places of just adding the import line to the script.py.mako file, that did not work for me.

How can I make scala's ammonite use scala.util instead of ammonite.util as default for util?

In the "official" scala REPL I can do
scala> import util.Random
scala> util.Random.nextInt
res0: Int => -306696783
but in Ammonite-REPL I get
# import util.Random
cmd3.sc:1: object Random is not a member of pack ammonite.util
import util.Random
^
Compilation Failed
So right now I have to use the scala. prefix to make it work in Ammonite:
# import scala.util.Random
# scala.util.Random.nextInt
res1: Int = 503117434
I'm kind of new to Scala so I don't get why would ammonite use a different util than the (for me) "official" util, so I would appreciate if anyone can provide a rationale for this.
And more specifically, Is there any way to make util to be scala.util instead of ammonite.util?
It's not that Ammonite is replacing a different util library for the normal Scala one, it's that the Ammonite namespace has it's own util package which has a whole bunch of methods specific to Ammonite. Perhaps it would be nicer if the developer had chosen a different name for his package, but this is not an issue specific to Ammonite. It is something you will run into all the time. When there is a clash of namespaces, your only option is to fully qualify the package name for the one you want. So what you actually did is a fine solution. You can find more about this here.
And btw, since there is no util.Random in the Ammonite package you can do this after your import--I tested and this is a cut and paste from my terminal:
# Random.nextInt
res1: Int = 1045964363
When you do actually have a collision of method names, you can find a solution here

jruby - import java class into jruby as different name

I'm using a game framework, libgdx, which includes its own Array class which collides with the JRuby built-in Array. Is there a way to java_import 'com.badlogic.gdx.utils.Array' with a different name? Something like
java_import 'com.badlogic.gdx.utils.Array', :as => GdxArray
? Thanks!
Okay, found a solution!
First I tried this:
GdxArray = java_import 'com.badlogic.gdx.utils.Array'
but that still resulted in the already initialized constant error. Second attempt:
# don't wallpaper over the JRuby Array class
GdxArray = com::badlogic::gdx::utils::Array
A little funny looking with the lowercase package names, but it works!!

Created new package and imported but Definition not found

I have created a simple parser package called parseLine.
I have it in a package in my project.
In parseLine I have a class called "myParse".
I can import it just fine.
import parseLine.myParse.*;
But when I compile I get an error "1172:Definition parseLine.myParse could not be found.".
This is pretty basic I know but would appreciate any help anyone my be able to offer.
myParse is not a package, it is a class, so you are importing it incorrectly.
Basic structure of a package:
src / my / package / name / ClassName
To import ClassName, you would use this:
import my.package.name.ClassName;
or
import my.package.name.*;
In ClassName, it must have the following setup:
package my.package.name {
public class ClassName {
// class code goes here
}
}
As an additional tip, you should follow standard naming schemes for AS3.
Package names should be all lowercase. Even if it is multiple words. my.packagename is proper, whereas my.packageName is not.
Class names should be UppercaseCamelcase. So ClassName is proper, whereas className and classname are not
All objects, including functions, should be lowercaseCamelcase. So var someObject is proper, whereas var SomeObject is not (same for function doSomething() vs function DoSomething())
Constants should be UPPERCASE_UNDERSCORE_SEPARATED. So const SOME_CONSTANT_VALUE is proper, whereas const someConstantValue is not.
Not using those rules won't break anything, but they are the accepted standards in AS3 which makes your code easier to read and maintain in the future.