Adds unit conversion

run the unit_converter.py script to see an example.
This script can be added onto, it does contain most of the typical unit conversions.

Coverage decreased (-100.0%) to 0.0% when pulling 7ba9cf2030510b834e4e15e8e32abed631a50ef2 on kdschlosser:unit_conversion into 824a871992315f529ccbefbcd4571e157af9262d on WoLpH:develop.

Wow, that's a pretty extensive bit of code. Great work :)
In workings it seems somewhat similar to the internals of my Alfred Converter package: https://github.com/WoLpH/alfred-converter/
The big difference is that I was lazy with that one and have imported the units from an external file ;)
I do have a few questions though:

It looks like al of the units are inheriting int, but I assume that many calculations return a float instead. Is that intentional?
Would it be a good idea to change the _values or _IntWrapper into a namedtuple? It would function mostly the same but it might be clearer what all the numbers mean

I should note that I'm really busy so I'm not yet sure when I can finish merging and releasing this. I haven't forgotten about your other pull request either but haven't gotten to it yet :(

Oh I know that this is going to need to be cleaned up and optimized.
To answer your question about the int/float thing.
The returned value all depends on the input value and also the conversion. Even tho an input value may be an int the return value may be a float depending on whether or not a float calculation was done. Maybe I should have it just return a float all the time no matter what the input value is. Would make it easier so a person wouldn't have to do type checking at all when they want to use the returned value.
Would it be a good idea to change the _values or _IntWrapper into a namedtuple? It would function mostly the same but it might be clearer what all the numbers mean
The constants need to be there in order to identify what type of conversion is to be done. In the eyes of the user the constants are an int and that is the only thing they need to know about. The values and label contained within the constant are for internal use only. The reason for the property is so that a user does not change what the values are if they discover them there. If you notice inside of the property I return a copy of the list. so in the event that they do change the values it is not going to effect the running of the unit converter.
I could have hard coded those values instead if doing what I did. but for code readability I set the values into the constant class. I did this so it is easier to identify what UOM belongs to what data type.
I wanted to eliminate the need for using a lookup table to store conversion factors. That kind of a table can get pretty large in size  so by using the SI model idea and applying it to other types I was able to remove the majority of the hard coded factors.

 They are doing things that is removing the flexibility of Python which was the best thing about it.
So I am trying to make a wrapper class around int and float if the value gets converted to a string it will include the unit. Now that in and of it's self is not a problem. I wanted to carry that unit if they converted the returned value to an int. Nope can't do that. They will only allow the returning of and instance of the class int from __int__ it cannot be a subclass of int. ok that sucks. It is the same deal with __float__. So now I decided I would point the magic methods to functions after the instance has been created. NOPE can't do that either, says the magic methods are read only.
Those bone heads never think about the people that use Python, they come up with these trivial things to change for absolutely no reason. They it with ctypes and passing a structure to a function that was not a pointer. It completely trashed using COM objects in Windows from Python.  Then why give the ability to override those 2 magic methods at all.

Yeah... there was a huge discussion about this some time ago: https://mail.python.org/pipermail/python-dev/2013-April/125042.html / https://bugs.python.org/issue26984
Long story short, the idea was that because int(...) is assumed to be a cast to int, it should always return an int.
Perhaps the more important question should be, if you're not looking for an int, why are you calling int()?
You can specify how calculations and such work using methods like __add__, __div__, __mul__, etc... And you're under no obligation to return an int/float from those

well here is a use case. I could understand if returning a instance that is not an instance of a subclass of int then block it.  But for crying out loud to block even subclasses of an int is just bonkers.

what's really not right about it is the fact that this is only on int and float. I tested it with str and the __str__ method returning a subclass of str from __str__ and it works without a hitch.
I can't even add a variable to an instance of int because int has no __dict__ setattr doesn't work either. I was hoping to add a unit variable as a backup but NOPE!
They are making code changes that fix no bug and have never had any kind of an issue in the first place. I don't understand why they would change it when there is no reason to do so.

It's funny because person after person after person  are for returning an int or a subclass of int. Not 1 person mentioned the use of int(float()).real or float(int()).real for accessing an actual int or an actual float instead of the possibility of a subclass.

and the statement you linked to has this statement

int() and operator.index() are both type coercion calls to produce true
Python integers - they will never return a subclass, and this is both
deliberate and consistent with all the other builtin types that accept an
instance of themselves as input to the constructor.

 It's one of the things that I really dislike about Python.
My guess is that it's related to compatibility with the C base however. Making these parameters changeable could result in a crashing interpreter if the C code doesn't handle it properly.

Well it works just fine in python 2.7 all the way up to 3.4 I believe.
There shouldn't be an issue with returning a subclass is int because the person running the code either wrote it and already knows  about the subclass. Or the person installed a library and if they read the documentation or look at the code for the library they will know that it returns a subclass of an int.  This all boils down to not running code that you are unfamiliar with.
and again there is still the real  property that can be used to obtain a non subclassed version of the int or float. with what they did then real no longer serves a purpose and can be removed because wrapping a float in float() or an int in int() is going to return the exact same thing as real

Well it works just fine in python 2.7 all the way up to 3.4 I believe.

It probably works in most cases, but it's likely to cause issues in some scenarios from what I've read. Memory corruption is not fun to deal with ;)

There shouldn't be an issue with returning a subclass is int because the person running the code either wrote it and already knows about the subclass. Or the person installed a library and if they read the documentation or look at the code for the library they will know that it returns a subclass of an int. This all boils down to not running code that you are unfamiliar with.

The problem is with the underlying C code, if that expects a variable to be 8 bytes (int64) and it's an object instead that takes many more bytes, that could be very problematic. While I expect most code to be compatible, there is no guarantee so that could cause problems.

I guess it really doesn't matter because a user has to pass in the unit they want to convert to so they actually have the unit they can attach to a string version of the return value. It's just that I need to make it so that the return value is always a float and the user can do whatever it is they want with the returned value after that.
The only other thing I am going to change is using decimal.Decimal for the floating point math. I will still have it return a float tho.

I just made a commit that has several changes to it.
The unit type constants are no longer public and do not need to be massed to the main entry point.
I changed over to using decimal.Decimal so floating point errors are handled properly.
I changed the example at the end of the file so it shows conversion to a unit and then back again.
I also did some code cleanup.
I have done some pretty crazy unit conversions when dealing with Internal Combustion Engines. an example is converting from grams a second of airflow or cubic feet a minute of airflow to horse power and torque with optionally taking into account barometric pressure, humidity, air temperature and also the gravitational forces due to location on the planet. That last one is over the top I know but I figured what the hell. It's all about calculating the number of oxygen molecules being used for combustion and gravitational forces do effect how oxygen dense a volume of air is.
I have a slew of them I have written up dealing with all kinds of things related to the automotive world. Any interest in those at all? I know they are very specific in nature but they are unit conversions.

not sure why the conversion of all of the double quotes to single quotes. Well I can understand everything except for the docstrings.
https://www.python.org/dev/peps/pep-0257/

It's simple, consistency: https://www.python.org/dev/peps/pep-0008/#a-foolish-consistency-is-the-hobgoblin-of-little-minds
The rest of the codebase uses single quotes as well :)

I know I saw that all of the docstrings used single quotes except for converts.remap
I just hate seeing the squiggly lines in my IDE.
Don't add this exact code for the unit converter into your library.   I was waiting until you had the time to lend a hand/provide input with it. I also want to add to it returning a normalized uom for the returned value. So if you tell the converter to convert  from "sq m" to "sq ft" when the value is returned it will return a uom of u'ft²'. This is a nice thing to have available if you are presenting the data to a user. hard coding the unicode characters is kind of a pain to have to do. much easier to pass "sq ft" and have the much nicer looking u'ft²' returned for use when presenting the data to the user.
I also want to clean up the code so it is easier to understand what is going on and that will make it easier to maintain/fix.

sorry about the mess with the commits.  because you edited my branch in this PR I didn't even think to update my local copy before making changes. It made a mess on my end locally that I had to correct.

Oh... that's weird. I tought I modified my own copy of it. I didn't know github would give me write access to your version... that's weird
In any case, single quotes is fully PEP8 compliant so your editor shouldn't be complaining about it :P
With regards to the sq vs ², I think some kind of tokenization is in order for that use-case but there are many ways of implementing that.
I think dataclasses could be nice to store the units and their possible units. And a parent dataclass for the type of measurement (i.e. temperature).
You might also need a way to specify combinations of units though... since some units are combinations of other units but that quickly becomes complicated.

@WoLpH
I have made some updates to the library IDK if you get notifications for me making commits so I thought I would drop a line and let you know. I am still hammering out a couple of issues and I am adding more units into it as well. I am checking the conversions are working properly which the ones that are working correctly are converting properly forwards and backwards.   I was trying something out with them but it didn't work so  I have to handle them differently.

@WoLpH
I have made some updates to the library IDK if you get notifications for me making commits so I thought I would drop a line and let you know. I am still hammering out a couple of issues and I am adding more units into it as well. I am checking the conversions are working properly which the ones that are working correctly are converting properly forwards and backwards.  I was trying something out with them but it didn't work so I have to handle them differently.

No worries, it's good to see progress :D

OK so an update.
I have compiled a total of 705 unique units. some of the units are able to be used in multiple "categories". The total number of units for all categories is 989. most of these are a base type of unit and they can be expanded upon. I have the SI equivalents for all of the units as well.

OK so after spending many hours researching SI units I discovered something that was not pointed out by anyone.
It does not matter what "group" a unit of measure belongs nor do I have to check to see if 2 units belong to the same group  so they can be converted to each other. The only thing I need  to do to ensure  that the units are compatible is I have to break them down into their base notation.
The  SI system is comprised of these 7  base units. every other unit breaks down into these units.
time: s = 1.0  # second
length: m = 1.0  # meter
mass: kg = 1.0  # kilogram
electric current: A = 1.0  # ampere
thermodynamic temperature:  K  = 1.0  # kelvin
amount of substance: mole = 1.0  # mole
luminious intensity: cd = 1.0  # candela
So if I say want to convert psi to lbf/ft²
psi is defined as 6894.7572932⋅Pa
PA is defined as 0.10197162129779283⋅kgf/m²
and kgf/m² is defined as 9.80665⋅N
and N is defined as kg⋅m/s²
and kg⋅m/s² is defined as kg⋅m⋅s⁻²
so the unit ends up as kg⋅m⋅s⁻²/ m² which is kg⋅m⋅s⁻²⋅m⁻² which is kg⋅s⁻²⋅m⁻¹
so kg⋅s⁻²⋅m⁻¹ is the base unit for one side
lbf/ft²
lbf = 4.44822⋅N
N/ft²
N = kg⋅m/s² = kg⋅m⋅s⁻²
ft² = (0.3048⋅m)² = m²
lbf/ft² =  kg⋅m⋅s⁻²/m² = kg⋅m⋅s⁻²⋅m⁻² = kg⋅s⁻²⋅m⁻¹
kg⋅s⁻²⋅m⁻¹ == kg⋅s⁻²⋅m⁻¹ so the unit conversion can be done!!!
To make it easier I will create a class that represents a unit and that class would be responsible for checking equality to another unit class and it will also hold the exponent along with any conversion factor associated for using it.
Handling the exponents is a tricky thing due to the nesting.
so say we have this equation
kg⋅m⋅s⁻²/m²
it is the  same as this equation
kg⋅m⋅s⁻²⋅(m²)⁻¹
which ends up being this.
kg⋅m⋅s⁻²⋅m⁻²
The exponents don't actually "flip" like I had originally thought they did. it is the joining of the exponents using multiplication.
I have a total of 478 unique "core" units. What I am calling a core unit is a unit that has no multiplication, division, exponents or prefix. a prefix can be added and the program will process the unit. that increases the number of supported units to 9560. exponents can also be added as well. Only using the typical exponents the number of supported units jumps to 38240. We can also combine units together using multiplication or division and this can be done with multiples of different units. The number of supported units ends up being ∞
Because I have figured out that breaking the unit down to it's  SI equivalent is the way to go about checking the compatibility of units with each other means I do not have to worry about categorizing and defining specific supported units. I only have to  consider what the core units are in an equation and supply SI equivalents of those core units and what the factor is to convert the core unit to the SI equivalent. So the code is written to handle the core units and dynamically alters the factory based on exponents, prefixes, multiplication and division.
I already have it written up and I am fixing the bugs currently. I am having some issues with how it's handling the factors, exponents and the joining of like base units.

What do you think of something like this?
@dataclasses.dataclass
class Conversion:
    '''
    Conversion parameters to convert to base value

    >>> base_value = (A + B * value) / (C + D * value)

    For a Fahrenheit to Kelvin conversion for example:
    >>> A = 2298.35
    >>> B = 5
    >>> C = 9
    >>> D = 0
    '''
    A: decimal.Decimal = decimal.Decimal(0)
    B: decimal.Decimal = decimal.Decimal(1)
    C: decimal.Decimal = decimal.Decimal(1)
    D: decimal.Decimal = decimal.Decimal(0)

    def __call__(self, value):
        return (self.A + self.B * value) / (self.C + self.D * value)

@dataclasses.dataclass
class Unit:
    sign: str
    base: typing.Optional[Unit] = None
    conversion: Conversion = Conversion()

# Shorthand to save characters
D = decimal.Decimal

K = Unit('K')
F = Unit('F', K, Conversion(D('2298.35'), D(5), D(9), D(0)))

That way you can easily describe all units and the base units. And you could do something like: N = 1000 * g * ms2
PS :Wouldn't gram be a better base unit for weight?

I am not the one that has made the decision on what is to be used for base units for the named derived SI Units. In order to do what you are wanting with the data classes I would have to define some 470 classes. This would either have to be hard coded or it would have to be done using voodoo magic code (meta classes) which will present it's own snafu of issues because of using a decorator for the data class.
Here is a list of what the base si units are and also the named derived si units
https://physics.nist.gov/cuu/Units/units.html
and here is some light reading if you want to get into SI units
https://www.bipm.org/documents/20126/41483022/SI-Brochure-9-EN.pdf/2d2b50bf-f2b4-9661-f402-5f9d66e4b507?version=1.10&download=true

this
K = Unit('K')
F = Unit('F', K, Conversion(D('2298.35'), D(5), D(9), D(0)))

if a whole lot harder to read then
convert(2298.35, '°K', '°F')

and how would one go about specifying this "(V·s/m²)⁻³/(s·A/((((m·kg·s⁻²)·m)/s)/A))" using data classes? (That is a real unit)
It's bad enough having to type that sucker out but having to create data class instances for each of the base units involved and the user would then be responsible for ensuring that the exponents are correct.
if the above unit is flattened it is something along the lines of "kg⁻²·m·s⁶·A"  I may  have messed up flattening it but it gives you the general idea anyhow.
all the units will flatten out to an si expression containing one or more of these units
mol, cd, kg, m, s, A, K, sr, dB
that expression or equation will only multiply to each other and each of the units may have an exponent. in the unit converter the only reason why the expression needs to be flattened all the way down is so that any units contained within the expression that are not base units is to have the factor for that  multiplied into the factor for the entire equation considering the exponent for that unit.  then the unit would get broken down into it's bases until only the base SI units remain. then combine the like base SI units in that flattened equation by adding the exponents of the like units together to form a single unit and if the unit has a 0 for an exponent hen the unit gets removed from the equation. only units that have matching SI expressions can be converted between each other.
Make sense? I know it is a real lemon zest to the brain. I have had dreams that are like what you see in a movie where some smart person is figuring out  some complex math and the equations are flying past in a vision. LOL
Then to top it off I spent time finding commonality between units in the same SI group but are define independently. an example is mmHg and PSI, or inH2O and mmHg. It's not like in/s or ft/min but they should be because mmHg and inH20 the mm and in are length measurements. so is PSI when it is expressed in named SI units (lbf/in²). because the SI specification uses the unit Pa (kg⋅m⁻¹⋅s⁻²)  for the pressure  group of units and meter (m) being in the SI equation for Pa I used meter as the unit for the factors. So any unit that uses Pa it's factor is based on 1 meter which means that mmHg has a factor of 0.001 * 1 mHg and 1 mHg has a factor of<PHONE_NUMBER>21 Pa so mmHg has a factor of 0.001 *<PHONE_NUMBER>21 =<PHONE_NUMBER>21 Pa. so 1 mmHg =<PHONE_NUMBER>21 Pa

this
K = Unit('K')
F = Unit('F', K, Conversion(D('2298.35'), D(5), D(9), D(0)))

is a whole lot harder to read then
convert(2298.35, '°K', '°F')

I think my example wasn't clear. This isn't the unit conversion function, these are the unit definitions. For the actual conversion you can still translate 'K' from the formula to the K variable.
So something like this: '10m + 50cm' could be translated to m(10) + cm(50) or even m(10) + m(c(50)).
The convert() function as you have it could stay the same, but it would have an automatic registry for the units and the valid conversions.

and how would one go about specifying this "(V·s/m²)⁻³/(s·A/((((m·kg·s⁻²)·m)/s)/A))" using data classes? (That is a real unit) It's bad enough having to type that sucker out but having to create data class instances for each of the base units involved and the user would then be responsible for ensuring that the exponents are correct.
if the above unit is flattened it is something along the lines of "kg⁻²·m·s⁶·A" I may have messed up flattening it but it gives you the general idea anyhow.

I would assume something along these lines:
(k*g)**-2 * m * s ** 6 * A`

Where those letters are all instances of units with the magic functions for mathematical operations such as __mul__ implemented.
They are functionally identical, but an editor or documentation generator will understand what variable k is but it won't help you with 'k'

all the units will flatten out to an si expression containing one or more of these units mol, cd, kg, m, s, A, K, sr, dB
that expression or equation will only multiply to each other and each of the units may have an exponent. in the unit converter the only reason why the expression needs to be flattened all the way down is so that any units contained within the expression that are not base units is to have the factor for that multiplied into the factor for the entire equation considering the exponent for that unit. then the unit would get broken down into it's bases until only the base SI units remain. then combine the like base SI units in that flattened equation by adding the exponents of the like units together to form a single unit and if the unit has a 0 for an exponent hen the unit gets removed from the equation. only units that have matching SI expressions can be converted between each other.
Make sense? I know it is a real lemon zest to the brain. I have had dreams that are like what you see in a movie where some smart person is figuring out some complex math and the equations are flying past in a vision. LOL

Haha, I get it :)
In my library I eventually run an eval to actually evaluate the code: https://github.com/WoLpH/alfred-converter/blob/08abec6e3a05bc541da2c11b2bedcd61a7d83ae0/converter/safe_math.py#L190-L222
But it makes it less of a hassle to implement.

Then to top it off I spent time finding commonality between units in the same SI group but are define independently. an example is mmHg and PSI, or inH2O and mmHg. It's not like in/s or ft/min but they should be because mmHg and inH20 the mm and in are length measurements. so is PSI when it is expressed in named SI units (lbf/in²). because the SI specification uses the unit Pa (kg⋅m⁻¹⋅s⁻²) for the pressure group of units and meter (m) being in the SI equation for Pa I used meter as the unit for the factors. So any unit that uses Pa it's factor is based on 1 meter which means that mmHg has a factor of 0.001 * 1 mHg and 1 mHg has a factor of<PHONE_NUMBER>21 Pa so mmHg has a factor of 0.001 *<PHONE_NUMBER>21 =<PHONE_NUMBER>21 Pa. so 1 mmHg =<PHONE_NUMBER>21 Pa

That's my point though. If all units are specified as conversions of the base unit, than you can always make those calculations. Millimeters of mercury seems different from pounds per square inch intuitively, but it really isn't. Also because it is actually defined in pascals but also it is the actual distance in millimeters the mercury will move.

A good source of inspiration could be Sympy: https://github.com/sympy/sympy
That library effectively implements the mathematical part of this in a very similar way.

OK I just pushed another commit. Check out the example at the end of the file.
I also corrected the issues with the computation of the factors.
I still have one more thing to change/add and that is checking for unit compatibility in a different location then I am currently doing it.

I have strayed quite far from  this being an SI unit converter. This converter supports way more units then the SI specification lists. and when I say way more  I am talking >50% of the units are not SI units.  I figured if I am able to use the SI model and bring those units into it.. Why not.

I made some more commits, don't know if you got notifications for the commits. Take a look and tell me what you think of the changes and if it functions like what you wanted with being able to use math operators on the unit objects to perform the conversions.

This looks like it works really nice, really great work!
The way it's setup is really flexible and should work with most common and uncommon units.
Do you mind if I make a few changes in the layout?

Sure go ahead. I tried to make it so that it is flexible and if needed it can be extended and is easy to add new units to if it needed by yourself or a user.
I am thinking about adding in ^ for the power symbol  as I know it is a pain to use the superscript numbers. not hard to add it. what are your thoughts on that? You can already use a space between units which signifies multiply

another thing is I have thought about putting the predefined unit variables at the module level but I figured it would be more of  a pain to key out "unit_converter" before each unit. then it dawned on me that a person could import the module under a different name like "uc" if they wanted to. so either way it would work. I kind of like the idea of putting them at the module level changing that is also easy to do. Let me know what your thoughts are on that as well.

I've added a few tests so I can be sure that any changes I make won't break anything, but they're not working the same in all cases.
For some reason the convert() function has different results from the mathematical operators approach. I'm guessing that's due to rounding and int/float/decimal differences, so I'm wondering what would be the best way to solve this. Converting everything to decimal is the easy way out, but perhaps you didn't do that with a reason?
The specific test that's failling:
>>> from python_utils import unit_converter

>>> from_unit = '°F'
>>> to_unit = '°K'
>>> value = 75.1
>>> unit_converter.convert(value, from_unit, to_unit)
297.09444444444443
>>> value * (unit_converter.Unit(from_unit) / unit_converter.Unit(to_unit))
75.1

PS: Kelvin does not use a degree. So it's just K and not °K :)

HUH. I answered this. I probably forget to press the comment button.
I am aware of the °K . that is done intentionally. There is no way to do the division using only multiplication and division. That is how the system works. There has to be special handling of it. I  can move the separate function  into the unit class to do the conversion. It wouldn't be that hard. I just left it the way it was.. That is the reason for the °K

New commit.
Read the commit description for more details

I forgot to mention I also fixed the issue with the variations in the result between the convert method and the operators.
So if you do the following.
convert(71, 'in³', 'mm³')
the returned value is 1163482
if you do the following
71 * (Unit.inch(exponent=3) / Unit.mm(exponent=3))
the returned value is 1163482
and if you do either of the following
convert(71.0, 'in³', 'mm³')
or
71.0 * (Unit.inch(exponent=3) / Unit.mm(exponent=3))
the returned value is 1163481.5439962302
and if you do either of the following
convert(decimal.Decimal('71.000000'), 'in³', 'mm³')
or
decimal.Decimal('71.000000')* (Unit.inch(exponent=3) / Unit.mm(exponent=3))
the returned value is 1163481.543996
The returned value is either going to be an int or a float.  Per the SI standard the number of decimal positions if any is what the precision of the returned value  is supposed to be. The only way to achieve that is using decimal.Decimal because the trailing zeros are persistent where as with a float they are not. So if an integer is passed in to convert an integer is what is going to get returned. passing a float returns the maximum precision and passing decimal.Decimal allows the user to set the precision.

I just saw your question about not using decimal.Decimal as the only way to pass in a value to be converted.  It is because it is too much to type and too much in the way of type conversions always having to be made to convert the input value into a string.    It is being used internally in the unit converter because of floating point math errors.  I dunno why float in python doesn't just use decimal.Decimal all the time it would produce correct results..
try doing this in python and see what the result is.
print(0.1 + 0.1 + 0.1)
I mean that is pretty simple math right there...  the result is 0.30000000000000004 not what is expected that's for sure.
and to fix that this has to be typed
from decimal import Decimal

print(float(Decimal('0.1') + Decimal('0.1') + Decimal('0.1')))

That's just stupid on a colossal level.
And now you cannot subclass float or int and implement all of the magic methods so making a wrapper class to help make it easier to do just went up in smoke.
you cannot do these things with the Decimal class which makes it a pain to use.
Decimal(1.0)

1.0 + Decimal('1.0')
1.0 * Decimal('5.0')

value = Decimal('75.0')
value *= 10

you are editing my branch of the PR so I am guessing it is something that I did that caused it to disappear. It might happen again. LOL. I have no clue how to use Github properly and what all the verbage is.

Thank god for regex :)
perl -pi -e "s/(_build_unit\('[^']+', )([^',]+),/\1 '\2',/" unit_converter.py
Just to reduce any type of internal floating point issues, I've replaced all number inputs to the _build_unit(...) to strings so they can be converted to decimals without any losses.
I've been working on getting consistent test results but my results have been mixed. I'm currently trying to make sure that all internal calculations are done using decimals but even in that case I'm still getting weird results so it's a work in progress :)

I've added it to a different branch so I don't disturb your work by the way: https://github.com/WoLpH/python-utils/tree/unit_conversion_restyled

ahhhh see that merge remote-tracking. I didn't do that, it did it automatically, might have something to do with your branch.
Read the commit notes for information as to what I have changed/added

you need to give me examples  of where you are running into problems. There shouldn't be an issue with the floats when calling _build_unit because that value you are converting to a string is the factor and gets passed to Unit which immediately converts it into a Decimal instance. You only end up with float errors when performing mathematical operations on them. So if I do this
value = 0.3
print(value)
```
I get the expected 0.3

but when I do this

```python
value = 0.3
print(value * 3)
```
I get 0.8999999999999999

I have not come across any inconsistent results with it so far. so I need specific examples t work off of.

I'm seeing issues with integers at least, this result seems incorrect to me:
>>> convert(71, 'in³', 'mm³')
1163482

My own converter library returns: 1163481.26 for the same calculation
Wolfram Alpha unfortunately doesn't show anything beyond the 10^6 scientific notation: https://www.wolframalpha.com/input/?i=71+in^3+to+mm^3
I'm not sure if it's actually wrong, but converting 71.0 gives a different result:
>>> unit_converter.convert(71.0, 'in³', 'mm³')
1163481.5

you need to give me examples of where you are running into problems. There shouldn't be an issue with the floats when calling _build_unit because that value you are converting to a string is the factor and gets passed to Unit which immediately converts it into a Decimal instance. You only end up with float errors when performing mathematical operations on them.

The previous example is still broken as far as I can see:
>>> from python_utils import unit_converter

>>> from_unit = '°F'
>>> to_unit = '°K'
>>> value = 75.1
>>> unit_converter.convert(value, from_unit, to_unit)
297.09444444444443
>>> value * (unit_converter.Unit(from_unit) / unit_converter.Unit(to_unit))
75.1

Anyway, there are a few things resulting in errors. Since the superscript is hard to type, I thought using the caret or python exponent characters might work, but they all result in a RecursionError:
unit_converter.convert(71, 'in**3', 'mm**3')
unit_converter.convert(71, 'in^3', 'mm^3')
unit_converter.convert(71, 'in3', 'mm3')

As for the int vs float calculations, I don't think returning an int makes sense in most cases. If you're lucky enough to have an exact calculation that could work but converting everything to float or Decimal would be more logical since you're losing precision in most other cases.
I think it would be better if these two return the same:
unit_converter.convert(71.0, 'in³', 'mm³')
unit_converter.convert(71, 'in³', 'mm³')

The previous example is still broken as far as I can see:

to_unit = '°K' is wrong.
to_unit = 'K'
°K was removed a couple of commits ago and I am not sure why the conversion worked. I have to check into that it should have kicked out an error.

Anyway, there are a few things resulting in errors. Since the superscript is hard to type, I thought using the caret or python exponent characters might work, but they all result in a RecursionError:
I didn't say python exponent I stated the caret for exponent.

I think it would be better if these two return the same:
I was typing to stay with the standard as best I could and also keep the code base low. If someone passes in a float of 12.0 or 12.00000000  I have no way of knowing how many trailing zeros they supplied so I am not able to round the number off for them. so passing a float is not rounded at all. I can check to see how many decimal positions exist for a float and always round it to the same decimal position and if someone needs better precision they can pass in a decimal.Decimal instance with he trailing 0's added.

If a user passes in an integer then an integer is what should be returned, I can understand that logic because if they are passing in an integer that is the numeric type they are working with.
It's your library it can be done however you want it done ultimately. we can always return a float of maximum precision and do away with the whole rounding aspect of it and whatever is passed in whether it be decimal.Decimal('123.456'), 123, 123.345, '123', or '123.456' the converter will do it's job and always return a float of maximum precision.

what line does the recursion error take place so I can correct that?

also this kind of a unit is not supported, no way to identify that the 3 means it is an exponent.
unit_converter.convert(71, 'in3', 'mm3')

I fixed the recursion problem and I added support for the Python '**' syntax

int return type has been removed and only a float will now be returned. I also added support for passing a str or bytes object to be converted. They are treated the same as a decimal.Decimal instance  where a fractional value's trailing zeros are treated as precision.
There is also checking for the  validity of a passed in str or bytes object so if a value that is not numeric get passed in a ValueError will get raised.

I believe that should address your current issues, let me know if there are more.

The previous example is still broken as far as I can see:

to_unit = '°K' is wrong. to_unit = 'K' °K was removed a couple of commits ago and I am not sure why the conversion worked. I have to check into that it should have kicked out an error.

Ah, now I see what you meant. I copied those tests from the main code but I was confused as to why the convert() function was returning different values from the other method.

Anyway, there are a few things resulting in errors. Since the superscript is hard to type, I thought using the caret or python exponent characters might work, but they all result in a RecursionError:

I didn't say python exponent I stated the caret for exponent.

I know, but I was just trying to see if there was an easy to type alternative already enabled :)

I think it would be better if these two return the same:
I was typing to stay with the standard as best I could and also keep the code base low. If someone passes in a float of 12.0 or 12.00000000  I have no way of knowing how many trailing zeros they supplied so I am not able to round the number off for them. so passing a float is not rounded at all. I can check to see how many decimal positions exist for a float and always round it to the same decimal position and if someone needs better precision they can pass in a decimal.Decimal instance with he trailing 0's added.

I think rounding should be left to the end user personally. Just return the float and let them decide how they want it :)
It's just a matter of number classes really, it is impossible to reliably display a fractional or irrational number as a real number.
From wikipedia:

N = natural numbers = positive integers = 0, 1, 2, ...
Z = integers, both positive and negative = ... -2, -1, 0, 1, 2, ...
Q = rational numbers = fractions, such as the celsius to fahrenheit conversion = 1/2, 1/3, etc..
R = the real numbers = floating point and decimal numbers are a small part of these = 1.1, 1.2, 1.3, ...
R\Q = irrational numbers. And these are where it gets problematic. A number like sqrt(2) or pi is never-ending.
But even simpler variants are problematic. You cannot express 1/3 as a decimal for example.

If a user passes in an integer then an integer is what should be returned, I can understand that logic because if they are passing in an integer that is the numeric type they are working with.

There's certainly some sense in that, but for clarity I think mimicking Python's behavior might be more obvious. With Python 2 we could do 1/3 and get 0. With Python 3 we get 0.333333333333
Neither solution is ideal but I think the more common case will be that the output would be incorrect as an integer.

It's your library it can be done however you want it done ultimately. we can always return a float of maximum precision and do away with the whole rounding aspect of it and whatever is passed in whether it be decimal.Decimal('123.456'), 123, 123.345, '123', or '123.456' the converter will do it's job and always return a float of maximum precision.

I'll have to think about it for a bit I guess. As long as it's clear to the user :)

the precision limit is dictated by whatever will fit into a double. and that is going to be way more precision than 99.999999% of python users will ever need. This is also the most complete and most accurate unit converter available for python at this time so  there shouldn't be any complaints  because of that.
I like just returning a float and let the user deal with rounding is the thing to do as well. I will still use decimal.Decimal to do the conversions properly and convert it to a float on the output side.
"sqrt" is also parsed in the unit converter BTW. :smile:
I did add the python "**" exponent syntax since you mentioned it's on one of the last couple commits.
I have to move the unit compatibility testing as only the convert function is checking compatibility at the moment.

Just so you know, if there is a space in the unit it is considered to be a multiplication of the 2 units so the following three units are the same
'Pa s'
'Pa⋅s'
'Pa/s⁻¹'

OK unit compatibility testing is in place and functioning for all of the different ways of doing a unit conversion.

Wow, you've really done some amazing work. Thank you! I'll see if I can get it fully tested and merged

I am still working on it. Right now I am improving the accuracy. going through each of the units making some changes to how some of the symbols are written. changing the nomenclature up some.

It's funny because I started programming 5 years ago.  I am 45 years old now and I found something I really enjoy doing. In that 5 years I have learned C, C++ C#, Python, HTML, CSS, JavaScript, PHP and also a bunch of other languages but only enough to get myself into trouble.
My strong area is writing bindings to c libraries in Python. I am also really good at evaluating code for performance and making changes to improve the performance. I also write a lot of firmware for a various assortment of micro controllers.
Before 5 years ago the only thing I knew how to program was my VCR and my remote control for my TV.  If I had discovered this in my 20's or earlier I would have worked in a completely different field.

I am still working on it. Right now I am improving the accuracy. going through each of the units making some changes to how some of the symbols are written. changing the nomenclature up some.

WIth that in mind, I've changed the build_unit() calls to all use strings so they can be converted to decimal without loss of precision :)

It's funny because I started programming 5 years ago. I am 45 years old now and I found something I really enjoy doing. In that 5 years I have learned C, C++ C#, Python, HTML, CSS, JavaScript, PHP and also a bunch of other languages but only enough to get myself into trouble.
My strong area is writing bindings to c libraries in Python. I am also really good at evaluating code for performance and making changes to improve the performance. I also write a lot of firmware for a various assortment of micro controllers.
Before 5 years ago the only thing I knew how to program was my VCR and my remote control for my TV.  If I had discovered this in my 20's or earlier I would have worked in a completely different field.

That's quite impressive! It's definitely a fun hobby to have.
I guess I was lucky in that regard, I started playing around with programming as a kid. I've been addicted to it ever since :)

I've added some alternative methods of calculation. I hope you like them :)
These are now all equivalent which seems convenient:
10 * (m / mm)
m(10).mm
10 * m.mm

I'm thinking of making m(10) iterable as well so it walks through all alternative units

The change I am working on now is going to be a really large one. It's going to improve the accuracy at least 100 fold on a lot of the units and I had already thought of being able to list all compatible units to convert to when the from unit is supplied and I have already begun working on it.
I have added a bunch more units into the mix as well.

OK I  am wanting to do this commit for the recent changes I made and I have a snafu  to contend with because you committed to my branch again and didn't inform me that  you did. :angry:
I cannot commit until I  fix the merge conflicts and to do so I need to better understand what your code changes do.Here is an example.
    def __mul__(self, other):
        if isinstance(other, Unit):
            f_units = list(self)
            t_units = list(other)
            unit = Unit(
                self._symbol + MULTIPLIER + other._symbol,
                base_units=f_units + t_units,
                factor=float(self.factor * other.factor)
            )
            return unit
        elif None in (self._from_unit, self._to_unit) and self._value is None:
            raise ValueError('To and From units have not be divided')
        else:
            f_unit = MULTIPLIER.join(sorted(str(u) for u in self._from_unit))
            t_unit = MULTIPLIER.join(sorted(str(u) for u in self._to_unit))

            if f_unit != t_unit:
                raise ValueError(
                    'Units "{0}" and "{1}" are not compatible({2})'.format(
                        self._from_unit,
                        self._to_unit,
                        (f_unit, t_unit)
                    )
                )

            if isinstance(other, bytes):
                othr = other.decode('utf-8')
            else:
                othr = other

            if isinstance(othr, str) and not _is_number(othr):
                raise ValueError(
                    'Not a numerical value ({0})'.format(repr(other))
                )

            val = decimal.Decimal(str(othr))
            val *= self.factor

            return float(val)

specifically
elif None in (self._from_unit, self._to_unit) and self._value is None:
            raise ValueError('To and From units have not be divided')

This is going to cause problems further on down in the method. The requirement of _value having to be None in order to gracefully handle an issue that can happen a user attempts to do this.
75 * Unit('mph')

We have no clue what 75 is and the only way to do a conversion is under the assumption that 75 is meters per second which is the  base unit for the quantity/group/category that miles per hour belongs to.
Because the system works on the multiplication of the number to be converted the example below would never even get to where _value is being check to see if it is None.
mph = units.mph(50)
mph * units.kph

right at the top of the __mul__ method there is handling for multiplying 2 units which is what the case is above and that gets used when building a unit. as seen below.  so what would happen is a new unit of "mph⋅kph would get created the supplied  value of 50 would get lost and no conversion would take place.
pa_s = units.Pa * units.s

if the following code gets run then an ValueError would be raised when it shouldn't be.
mph =units.mph(50)
50 * (mph / units.kph)

and this code wouldn't work even tho it should.
mph = units.mph(50)
mph / units.kph

There is also no use of _value anywhere else in that method. There are no other changes to that method either.
also what does this do in the __call__ method?
value = functools.reduce(lambda x, y: x * y, args,
                                     decimal.Decimal(1))

Also the changing of the __call__  has removed the type hinting as well as parameter names and default values so code completion in an IDE is no longer going to work correctly. and lord what a mess that becomes when using PyCharm because it starts to take guesses LOL. I can say that has to be one of the most infuriating things when the parameters and types being passed are not correct but in the IDE it shows up as being correct. Then you have the added bonus of the correct ones show up as being wrong.
The thing I do not like is the ability to do this
m(10).psi
10 * m.psi

psi is not a compatible unit with meter.
The idea is fantastic and I think it should be done.  I think with the changes I have just made that allows us to know what units are compatible for conversion it will ensure proper conversions take place. and instead of  using the smoke and mirrors of functools in the call method and instead create a position only argument for value which is defaulted to None and internally use keywords when wanting to make a copy of a unit This would keep the type hinting working properly and also the code completion. we also need to pass _value when a copy of a unit takes place and no value but one exists in the unit that is being copied. Add in handling of _value not being None in the div and mul methods so the return value doesn't end up being another unit. If _value is not None and the unit is wrapped in str() then return a string of the value with the unit symbol as a suffix.
I guess what I am asking is should I just merge the changes I made wiping your changes out and commit that then and add in your idea afterwards?

I just realized something. We definitely need to check if from_unit and to_unit are populated if passing a value to __ call__.
(units.mph \ units.kph)(65)

the output from that should be 104.607 which is what 65mph converts to in kph
So if we set it up so that when passing a value to be converted to __call__ and from_unit and to_unit are populated and just return the converted value the code below can be used if doing the same conversion more then a single time
mph_to_kph = units.mph / units.kph
mph_to_kph(50)
mph_to_kph(65)
mph_to_kph(100)

this would also work
mph_to_kph = units.mph / units.kph
50 * mph_to_kph
65 * mph_to_kph
100 * mph_to_kph

I like this the best
mph_to_kph = units.mph / units.kph
speed = 50
speed *= mph_to_kph

OK I am wanting to do this commit for the recent changes I made and I have a snafu to contend with because you committed to my branch again and didn't inform me that you did. 😠

I informed you I made changes:

With that in mind, I've changed the build_unit() calls to all use strings so they can be converted to decimal without loss of precision :)

And:

I've added some alternative methods of calculation. I hope you like them :)

Also, Github even shows it right in this discussion:

And once you said you were making large changes I've held back on changing anything because I was afraid of merge conflicts.
After your recent large changes my own branch was not usable anymore. There was no way to merge your changes without solving a ton of merge conflicts.

I cannot commit until I fix the merge conflicts and to do so I need to better understand what your code changes do.Here is an example.

The short version is that the __call__() method was renamed to derive(). And the units have an optional value so they can be partial calculations.
This allows for m(10) to indicate 10 metres that can later be converted to something like millimetres:
x = m(10)  # 10 metres
x.mm  # Converted to millimetres

As opposed to always requiring 10 * m which immediately does the calculation.
You can view it as something similar to functools.partial() where the value is already stored for future calculations.

This is going to cause problems further on down in the method. The requirement of _value having to be None in order to gracefully handle an issue that can happen a user attempts to do this.
75 * Unit('mph')

We have no clue what 75 is and the only way to do a conversion is under the assumption that 75 is meters per second which is the base unit for the quantity/group/category that miles per hour belongs to.

In this case, by your standard, 75 would mean 75 mph.

Because the system works on the multiplication of the number to be converted the example below would never even get to where _value is being check to see if it is None.
mph = units.mph(50)
mph * units.kph

It could be that there are still bugs of course, but all of the tests you and I have previously created were still working just fine :)

right at the top of the mul method there is handling for multiplying 2 units which is what the case is above and that gets used when building a unit. as seen below. so what would happen is a new unit of "mph⋅kph would get created the supplied value of 50 would get lost and no conversion would take place.
pa_s = units.Pa * units.s

if the following code gets run then an ValueError would be raised when it shouldn't be.
mph =units.mph(50)
50 * (mph / units.kph)

and this code wouldn't work even tho it should.
mph = units.mph(50)
mph / units.kph

Cool, so we have a bunch of new testcases to add :)
That's why I prefer to add a bunch of tests in advance so I know if I'm breaking anything with the changes.

There is also no use of _value anywhere else in that method. There are no other changes to that method either.

The implementation isn't complete yet and doesn't handle all cases. But I refrained from making further changes until you were done with the big change. I'm happy to continue implementing the other cases though.

also what does this do in the call method?
value = functools.reduce(lambda x, y: x * y, args,
                                     decimal.Decimal(1))

It's like sum(), except it does multiplication instead of addition. Basically if you feed it (5, 3, 8) it will do: 5 * 3 * 8.

Also the changing of the call has removed the type hinting as well as parameter names and default values so code completion in an IDE is no longer going to work correctly. and lord what a mess that becomes when using PyCharm because it starts to take guesses LOL. I can say that has to be one of the most infuriating things when the parameters and types being passed are not correct but in the IDE it shows up as being correct. Then you have the added bonus of the correct ones show up as being wrong.

Sounds like I forgot to move the type hints. I'll have a look at that :)

The thing I do not like is the ability to do this
m(10).psi
10 * m.psi

psi is not a compatible unit with meter.

You're right, it needs a lot more checks. That should either result in another partial unit or raise an AttributeError
While m and psi are not fully compatible, they are partially compatible so it could return a partial unit where it knows how to calculate half of the equation. We can convert the 10 metres into inches, now we just need to lose the pounds from the right side of the equation or add kilograms at the left side of the equation. Perhaps simply raising an AttributeError might be better :)

I guess what I am asking is should I just merge the changes I made wiping your changes out and commit that then and add in your idea afterwards?

Instead of merging the changes, you can force push your branch. I'll see if I can let git re-apply the changes. I've backed them up to my own branch to be sure :)

I know you said that you made some changes  I didn't think those changes were made to my branch. If you forked my branch then you should be able to open a pull request against that branch to include the changes you have made. This would be better then being able to commit directly  to my branch. I missed the line where it said that you made changes, and to op it off   I never got any kind of a notification on Github that you made changes.  I only found out after I made a bunch of large alterations and those  alterations conflict with the changes you made. I am going to merge your changes into my code and I will see how that goes.

I know you said that you made some changes I didn't think those changes were made to my branch. If you forked my branch then you should be able to open a pull request against that branch to include the changes you have made.

That's indeed how I started but that was unmaintainable due to the huge refactorings and other changes you've made :)
Merge conflicts go both ways so working on my separate branch was becoming useless because I could not merge the changes from your branch and you couldn't merge the changes from my branch anymore.
When making big changes it's better to work in sequence instead of in parallel which is why I immediately stopped making changes after your notice: "The change I am working on now is going to be a really large one"
So forking and opening a pull request once we're done would actually aggravate the issue because we would both be making even more changes that increase the amount of conflicts.
In any case, you are free to force push your version so I can try and merge in my changes. In any case, I'll wait my turn for updates :)

heyyy I just made a commit. check out the example file.

Very nice! This was exactly along the lines of what I was planning: https://github.com/WoLpH/python-utils/pull/20/commits/12963f8fb728e8939b6a32cec8fa1d4cd3d0cb07
In addition I'm planning to update the code to use Python 3.5+ type hints. And add the units to the units object so you can easily autocomplete and jump to the definition.

Happy reading!!

And add the units to the units object so you can easily autocomplete and jump to the definition.

You don't actually have to add them to the dynamic module class. Because of the smoke and mirrors of how that whole thing works an IDE is not going to be able to trace that way through the program so what it sees is whatever is specified at the module level.
Now.. That being said. there is a bug in both PyCharm and also in Sphinx. PyCharm does not use the .. py:data:: :type: directive for determining a "constants" data type. Sphinx does not use the current context of where the docstring is located in order to link to the object set in the directive unless the entire module path is supplied. I cannot import Unit and set the :type: to Unit. The :type: option needs to be set to python_utils.unit_converter.unit.Unit explicitly. Doing that produces a crappy output in the documentation. I reported the bug to the developers of Sphinx and it has already been fixed and the fix will be included in the next release of Sphinx.
https://github.com/sphinx-doc/sphinx/issues/9899
I have not yet created a bug report with JetBrains yet. Not that I would actually think they would fix it any time soon anyhow.
The really shitty thing is Sphinx outputs differently if using Python 3 type hints and the output doesn't look pretty.  If it is selected to display the type hints at the beginning of the documentation for the object instead of in the declaration of the object it's just as ugly. However, if you turn off using the type hints all together and in the documentation you use the :type {param_name}: directive the output is much nicer. You will see this is what I have done.
I also set up a custom CSS file for the documentation. I increases the width and resets the margins to  different size that scales to the width of the browser window. IDK why it is preset to be a fixed width but it is. parameters for functions and methods also appear on their own line and spaced properly to look like Python code. It makes it easier to read this way. My CSS programing ability is god enough to handle most things but for the life of me I was not able to determine if a series of parameters would surpass the width and break them up based on that. so even if the function/method has a single parameter and it would fit all on a single line it is still put onto it's own line. Small price to pay for readability.
There are a couple of options I set in the config file for the documentation and I fixed the error/warning for not locating "_static" as the repair of that was a side effect of adding the custom CSS file.
I made another commit and the new quantity system is now done. It is easily expanded/added onto by the user. I still have to key up documentation for it  but if you read the rather long commit notes I go over how to use it when adding new quantities. Also check out the bottom of the example file to see some examples of how it works.
I found the bug that was causing inconsistent conversion results. I stumbled across the problem when I was modifying your implementation using __getattr__. The bug showed up when copying a unit. It was an indentation mistake LOL.   I am the ID-10-T  for not doing that.

Type hinting and autocomplete are now working for the Unit attribute in the units module.

@WoLpH
I have pushed some commits. Have a look I have made a bunch of changes. I think you will like the behavior.

Happy reading!!

And add the units to the units object so you can easily autocomplete and jump to the definition.

You don't actually have to add them to the dynamic module class. Because of the smoke and mirrors of how that whole thing works an IDE is not going to be able to trace that way through the program so what it sees is whatever is specified at the module level.

Perhaps not fully, but I think we might be able to get some support. Particularly, I think something like this might work, but I'm not entirely sure and I could be missing something:
units.atm = Unit('atm', '101325')

Can I give it a try? Or are you planning more updates?
If I succeed it will be a large update which is definitely going to give merge conflicts.

I have not yet created a bug report with JetBrains yet. Not that I would actually think they would fix it any time soon anyhow.

Yeah... I've tried several times. Don't bother.
If you're really lucky they might look at it in 5 years or so.

The really shitty thing is Sphinx outputs differently if using Python 3 type hints and the output doesn't look pretty. If it is selected to display the type hints at the beginning of the documentation for the object instead of in the declaration of the object it's just as ugly. However, if you turn off using the type hints all together and in the documentation you use the :type {param_name}: directive the output is much nicer. You will see this is what I have done.

I've seen similar issues but in my case it was largely caused by Sphinx not being able to find the correct import. But you're right, that's an issue.
Even though I'm not exactly a fan of generated code, using generated code in this case could be beneficial. In that case we could easily support both (and future variants) without any issues. For example, the type hinting system has switched back and forth from requiring an actual import to allowing strings over the years.
It would be possible to generate specific versions for newer/older Python versions.

I also set up a custom CSS file for the documentation. I increases the width and resets the margins to different size that scales to the width of the browser window. IDK why it is preset to be a fixed width but it is. parameters for functions and methods also appear on their own line and spaced properly to look like Python code. It makes it easier to read this way. My CSS programing ability is god enough to handle most things but for the life of me I was not able to determine if a series of parameters would surpass the width and break them up based on that. so even if the function/method has a single parameter and it would fit all on a single line it is still put onto it's own line. Small price to pay for readability.

My guess is that it's due to becoming difficult to read on large displays if the lines are too long:

As opposed to the old version:

I personally like the new version better, but it's getting a bit too wide perhaps. That can easily be solved with a max-width though. The old version is definitely too narrow but the new version might be a tad too wide for large displays.
Setting the max-width to 75% means that it will be very narrow on a small display so that's not ideal either. To illustrate, here's how the old version would look on an ipad:

And here's the new version:

But we can set it to a larger amount and be done with it :)
Or we can make these css rules media-dependent. On smaller screens they would be useless anyhow, so perhaps this should start to matter above 1200px width?

I made another commit and the new quantity system is now done. It is easily expanded/added onto by the user. I still have to key up documentation for it but if you read the rather long commit notes I go over how to use it when adding new quantities. Also check out the bottom of the example file to see some examples of how it works.

I find it weird how they call it quantities, that seems the wrong term for this... but a weird standard is better than no standard :)

I found the bug that was causing inconsistent conversion results. I stumbled across the problem when I was modifying your implementation using getattr. The bug showed up when copying a unit. It was an indentation mistake LOL.  I am the ID-10-T for not doing that.

That's why I create a bunch of tests before changing stuff. If I break something while changing, I'll notice ;)
It's the safest way to refactor and/or restructure code from my experience

On large displays a person can simply window the browser and adjust the size to make the text fit how they want. That is why I changed  both the margins and the widths to percentages instead of hard coded widths that do not adjust when the browser is resized. :smile:
As far as the issue with the import and sphinx is concerned... I changed that whole thing up and I am no longer using .. :py:data:: anymore and instead I am using :cvar: as I have moved the units variables into the module class which is no longer the module class so the voodoo magic code has been removed in favor of using the import system to do the same thing but an IDE is able to trace a path through and the autocomplete and type hinting works correctly with. So there is no need for you to go through the pain staking process of declaring the units like you described.
IDK if you have tested or even looked at the code since The last bunch of commits. When you do you will see that the auto complete now works for all of the declared units. Once that are dynamically created there is no way to get the type hinting and auto complete to work, well in pycharm there isn't because pycharm doesn't pay attention to the return type set to __getattribute__  which is pretty dumb if you ask me.  Tho I have not applied python 2 type hinting to it or sphinx type hinting either of those may do the trick with pycharm, I will have to test it out.

Oh also. the CSS code I added to put method and function parameters onto separate lines can be removed. I did that only because when sphinx add the type hinting to he parameters it makes a complete mess that is hard to read/understand. separating each parameter onto it's own line also takes the type with it making it much easier to read. I personally didn't care for how it looked with the type hinting and it also added confusion because this is how it would display it
__call__(
    value: Optional[Union[float, int, decimal.Decimal]] = None,
    factor: Union[float, int, decimal.Decimal] = 1.0,
    exponent: Union[int, decimal.Decimal] = 1
):
    blah blah blah blah

and I find this much easier on the eyes.
__call__(value=None, factor=1.0, exponent=1):

    value: value description
    type: Optional, float, int or decimal.Decimal

    factor: factor description
    type: Optional, float, int or decimal.Decimal

    exponent: exponent description
    type: Optional, int or decimal.Decimal

That's why I create a bunch of tests before changing stuff. If I break something while changing, I'll notice ;)
It's the safest way to refactor and/or restructure code from my experience

This is still in development and the API for it is not nailed down 100% yet and that is the reason why I hold off for creating unit tests. Once I get the API to a point where I know it is not going to change then I will make units tests up. making them up on an unstable and almost guaranteed to change API just makes more work because the units tests then have to be updated if the API changes and that just creates more work. If there is an error in the code the error will show up when the unit tests are created.  for new development bug testing is the last thing I do. I do the bug testing and optimization at the same time. The reason why is because when I am looking over the code to find a bug I will almost always look at the code and find improvements that can be made as well. More times then not when I improve the code the bug gets sorted out as well. Point in fact, this bug that existed. I would have been tearing my hear out  if I was trying to locate that bug. it would have been a needle in a haystack to locate, I happen to come across it during one of my code optimizing adventures and even when I first spotted it It didn't register as the cause of the problem you had. It didn't look right to me either but I couldn't quite put my finger on it. I had seen the problem you were having but I didn't change the code with the intention of fixing the bug. I changed the code to optimize it and the result was that bug went away. That is when I put 2 and 2 together.

That's why I create a bunch of tests before changing stuff. If I break something while changing, I'll notice ;)
It's the safest way to refactor and/or restructure code from my experience

This is still in development and the API for it is not nailed down 100% yet and that is the reason why I hold off for creating unit tests. Once I get the API to a point where I know it is not going to change then I will make units tests up. making them up on an unstable and almost guaranteed to change API just makes more work because the units tests then have to be updated if the API changes and that just creates more work.

It depends on the type of test. I agree that many unit tests are not useful until you're done with all of the changes, but an integration test should return the same results.
Simply put, I would expect the results of a call like this to remain constant:
convert(52.0, '°F', '°C')

Or perhaps to make it even more stable:
round(convert(52.0, '°F', '°C'), 2)

A test like that will easily let you know if something broke. That's also how I noticed that the 2 different API's were unexpectedly giving different results.

As far as the issue with the import and sphinx is concerned... I changed that whole thing up and I am no longer using .. :py:data:: anymore and instead I am using :cvar: as I have moved the units variables into the module class which is no longer the module class so the voodoo magic code has been removed in favor of using the import system to do the same thing but an IDE is able to trace a path through and the autocomplete and type hinting works correctly with. So there is no need for you to go through the pain staking process of declaring the units like you described.

Ah, that's great :)
I was hoping to do it with a few regular expressions though, it shouldn't be pain staking... I hope

IDK if you have tested or even looked at the code since The last bunch of commits. When you do you will see that the auto complete now works for all of the declared units. Once that are dynamically created there is no way to get the type hinting and auto complete to work, well in pycharm there isn't because pycharm doesn't pay attention to the return type set to getattribute which is pretty dumb if you ask me. Tho I have not applied python 2 type hinting to it or sphinx type hinting either of those may do the trick with pycharm, I will have to test it out.

I looked at the commits but I haven't tested the code in an IDE (I mostly use neovim) so I didn't see any advanced autocompletion yet but I'll give it a try in pycharm.
I have an idea for the auto completion though, it should be easy enough with an auto-generated type stub (.pyi) file that's effectively the cartesian product of all unit combinations. I'll play around with it a bit :)

stub files aren't really needed. they are mainly for byte compiled ad extension modules. If your IDE is not able to autocomplete that is  because the IDE  you are using does not use Python 3 type hinting or sphinx type hinting to determine what the data type is. It only uses  an express declaration in order to  autocomplete properly.
What are you using for an autocomplete plugin ??  YouCompleteMe? You need to have a plugin for auto completes to work and to what extent I am not sure how much they will work.

stub files aren't really needed. they are mainly for byte compiled ad extension modules. If your IDE is not able to autocomplete that is because the IDE you are using does not use Python 3 type hinting or sphinx type hinting to determine what the data type is. It only uses an express declaration in order to autocomplete properly.

As far as I know, it used to work around the __getattribute__ issue with pycharm. Not sure if it's still relevant.

What are you using for an autocomplete plugin ?? YouCompleteMe? You need to have a plugin for auto completes to work and to what extent I am not sure how much they will work.

I'm mostly using deoplete these days: https://github.com/WoLpH/dotfiles/blob/66642e18d4a2255773f8f37a13600ce61d1b1563/_vimrc#L381-L421
YouCompleteMe was far too slow for me in the past. Perhaps it's improved though, I should try again. Libraries do improve over time.

the __getattribute__ problem is only in detecting the type returned from the method. In PyCharm the hard coded class attributes autocomplete properly. It would be nice to have the dynamic ones work as well when  use units.m all is good but units.cm  autocomplete does not function because cm is dynamically created. To hard code the 500+ units each having 10 prefixes would make 5,000  hard coded class attributes. Little expensive to do that at runtime.
What is nice about using the  __getattribute__ method is I am able to make a copy of the hard coded class attribute units this way a user is not able to modify the instances that have been set into those class attributes.
I have tried using Python 2 type hinting and also type hinting using sphinx and the auto complete does not work.
I did however change it up so the units class attributes get set directly with the proper unit instead of None and having the unit builder set the Unit instance to the class attribute. This is how you had wanted to go about doing it and I did it because the PyCharm debugging wasn't playing nice with setting it to None and then setting the instance later.
I still have to check to see if that fixed the debugging issue. I am going to open a bug report for PyCharm because of the type hinting not working properly with __getattr__ and __getattribute__. ya never know maybe they will fix it sooner then later.. LOL

I just confirmed making a stub file does not fix auto complete for units returned from __getattribute__

2.6.3 + e2ed00ac LGTM :)

I've just merged back the changes from develop and I've walked through the code quite a bit.
I think the code looks pretty good as it is. There's always room for improvement but I think it's time to just go for it and merge it :)
The only thing that still needs a little bit of work is the tests, but I'm looking at those as well.


Add WikilinkNN Unwanted Links

The WikilinkNN currently best supports book recommendations in wikirec as there are preset links that are removed via the following in wikirec.model._wikilink_nn:
to_remove = [
    "hardcover",
    "paperback",
    "hardback",
    "e-book",
    "wikipedia:wikiproject books",
    "wikipedia:wikiproject novels",
]
wikilinks = [item for item in wikilinks if item not in to_remove]

It would be best if this could be adapted for other kinds of recommendation inputs. The style of input could potentially be passed to wikirec.model.gen_embeddings, but a discussion could also be had about other ways to derive which links should be removed.

@victle, I figure we can switch the discussion for #36 and #47 over here. Am currently re-running everything to make a new enwiki_books.ndjson, books_embedding_model.h5 (renamed it to make it explicit), and will update the results for rec_books.ipynb. I guess this issue would be the next thing to do on this model, but then am open for suggestions :)
Again, sorry that I was awol for a bit there. Feel free to let me know what you have interest in doing, and of course no stress if you're busy. I'll be fully switching over to another project tomorrow, but would be happy to discuss all this with you still 😊

This feels super specific to each kind of category, so I really wonder what the best approach is for removing some of these more common terms. I guess one brute force approach is just doing it empirically for different categories? Like, when generating an embedding for movies, comb through some of the top most frequent items and choose for removal? But that does seem like a lot of work 😅
Maybe another easy way is to filter certain wikilinks using regex? It seems to me that an easy one would be removing any links with "wikipedia" or "wikiproject" in them. I wonder how the performance of the model recommendations gets affected by having these extra links in them? It could be harmless for certain categories, but I haven't tested enough to know 🤷♂
And no worries about being away! Everyone's got a life outside GitHub 😆 . My time is a bit limited moving forward, but I'd be happy to do small tasks here and there (e.g., perhaps picking out some unwanted links for movies or something?).

I agree that those that have "wikipedia" and especially "wikiproject" should likely be removed. Maybe not the former as there could be things like categories that would be important, but then I'm not sure :) Maybe for major things it'd be best to select them, and for others we could just select those that are present in > X% to be removed.
By the sounds of it this is something that's later on the horizon for both of us though 😄 This especially given your point in the second paragraph above - how much is all this really going to help? :) Let's get back to it another time 😊
Feel free to check base here when you have a bit more time, or also let me know if you have something open source you'd want some help on!


Added Windows Application Packaging Project

Added a Windows Application Packaging Project to package the application using the Desktop Bridge. The project will output an AppX package, which can be published on the Microsoft Store.

@qmatteoq What is required to publish this to Microsoft Store? A code signing certificate?


Program gets painfully slow with conditional breakpoints

I noticed the target program gets painfully slow with conditional breakpoints, RemedyBG runs totally fine though.
Not sure if it's relevant but the part where I add the breakpoint is parallelized.

Go ahead and try again with the top of master; there was a ton of slop in the important path here, added by my logging additions to the control thread, on top of the slop that was already there. Different people are getting different numbers comparing the new version to Remedy, but it should be roughly comparable now.

Improved significantly! Yeah It's roughly the same as RemedyBG now.
Also, just noticed the raw runtime speed of the attached program is around 125% of what I get in RemedyBG which is such a great  thing! Thanks :)


Jupyter PDF Export

When I try to download my Jupyter notebook using Plots.jl as a PDF I get this error
  nbconvert failed: Inkscape svg to pdf conversion failed

When I dig into the log  I get the following
NbConvertApp] WARNING | Collisions detected in jupyter_nbconvert_config.py and jupyter_nbconvert_config.json config files. jupyter_nbconvert_config.json has higher priority: {
  "Exporter": {
"template_path": "['.', '/home/jdtuck/.local/share/jupyter/templates'] ignored, using ['/home/jdtuck/.local/share/jupyter/templates']"
  }
}
/usr/lib/python3.5/site-packages/IPython/nbconvert.py:13: ShimWarning: The `IPython.nbconvert` package has been deprecated. You should import from ipython_nbconvert instead.
  "You should import from ipython_nbconvert instead.", ShimWarning)
[NbConvertApp] Converting notebook AerialRadiationAlgorithmEvaluation.ipynb to latex
/tmp/tmp_o4i1qpz/figure.svg:1: parser error : Document is empty

^
/tmp/tmp_o4i1qpz/figure.svg:1: parser error : Start tag expected, '<' not found

^
/tmp/tmp_o4i1qpz/figure.svg:1: parser error : Document is empty

^
/tmp/tmp_o4i1qpz/figure.svg:1: parser error : Start tag expected, '<' not found

 ^

** (inkscape:16304): WARNING **: Specified document /tmp/tmp_o4i1qpz/figure.svg cannot be opened (does not exist or not a valid SVG file)

It seems as though the svg is not created properly. Same problem occurs with Gadfly.
The julia version is 0.4.1 and Pkg.status() is below.
    14 required packages:
 - Cpp                           0.1.0
 - Debug                         0.1.6
 - ElasticFDA                    0.3.1
 - Gadfly                        0.4.0
 - HypothesisTests               0.2.10
 - IJulia                        1.1.8
 - Immerse                       0.0.9
 - JLD                           0.5.6
 - MAT                           0.2.14
 - Plotly                        0.0.3+             master
 - Plots                         0.5.0
 - PyPlot                        2.1.1
 - Qwt                           0.0.1
 - Winston                       0.11.13
63 additional packages:
 - ArrayViews                    0.6.4
 - BinDeps                       0.3.19
 - Blosc                         0.1.4
 - Cairo                         0.2.31
 - Calculus                      0.1.14
 - Codecs                        0.1.5
 - ColorTypes                    0.2.0
 - Colors                        0.6.0
 - Compat                        0.7.8
 - Compose                       0.4.0
 - Conda                         0.1.8
 - Contour                       0.0.8
 - DataArrays                    0.2.20
 - DataFrames                    0.6.10
 - DataStructures                0.3.13
 - Dates                         0.4.4
 - Dierckx                       0.1.7
 - Distances                     0.2.1
 - Distributions                 0.8.7
 - Docile                        0.5.19
 - DualNumbers                   0.1.5
 - FileIO                        0.0.3
 - FixedPointNumbers             0.1.1
 - ForwardDiff                   0.1.2
 - GZip                          0.2.18
 - Graphics                      0.1.3
 - Grid                          0.4.0
 - Gtk                           0.9.3
 - GtkUtilities                  0.0.7
 - HDF5                          0.5.6
 - HTTPClient                    0.2.0
 - Hexagons                      0.0.4
 - ImmutableArrays               0.0.11
 - IniFile                       0.2.4
 - Iterators                     0.1.9
 - JSON                          0.5.0
 - KernelDensity                 0.1.2
 - LaTeXStrings                  0.1.6
 - LibCURL                       0.2.0
 - Loess                         0.0.5
 - MathProgBase                  0.3.19
 - Measures                      0.0.1
 - NLopt                         0.2.3
 - NaNMath                       0.1.1
 - Nettle                        0.2.0
 - Optim                         0.4.4
 - PDMats                        0.3.6
 - Polynomials                   0.0.4
 - ProgressMeter                 0.2.2
 - PyCall                        1.2.0
 - Reexport                      0.0.3
 - Roots                         0.1.20
 - SHA                           0.1.2
 - Showoff                       0.0.6
 - SortingAlgorithms             0.0.6
 - StatsBase                     0.7.4
 - StatsFuns                     0.2.0
 - Tk                            0.3.6
 - URIParser                     0.1.1
 - WoodburyMatrices              0.1.2
 - ZMQ                           0.3.1
 - Zlib                          0.1.12

Also below is the example i am running on my Jupyter Notebook
using Plots
gadfly()
x = linspace(0,2*pi,101);
y = sin(x)
plot(x,y)

Thoughts?

tbreloff/Plots.jl/issues/72

tbreloff confirmed he could reproduce tbreloff/Plots.jl/issues/72

I have no idea.  @minrk, any idea of why an SVG plot would display correctly in the notebook, but fail to convert?
@jdtuck, maybe you can post the notebook that is causing problems in a gist?

Here is the notebook https://gist.github.com/jdtuck/82dd792b9f3d6924228d

I'm not sure why the Inkscape conversion would fail, but we can probably try to look at it in isolation without being an nbconvert step.

It is really inkscape, or the fact the svg is not being created properly?

Did you try opening inkscape separately? I vaguely remember having encountered the same issue a long time ago and updating inkscape or opening the program and accepting first time terms and conditions or something fixed it. Sorry I can't be more precise.

For what it's worth, I had this same error to realize that inkscape wasn't installed. If anyone comes across this issue, please make sure that inkscape is actually installed.

Might be worth filing an issue with Jupyter to get a more helpful error message that suggests installing and launching Inkscape.

I would like to comment with further information: having installed inkscape, I'm now having the same issue again. Not sure this is Jupyter, since working with matplotlib, etc., is working just fine. However, I would be willing to point the finger at Gadfly given the text of tbreloff/Plots.jl#72

IJulia really has nothing to do with this; all of this export functionality is controlled by Jupyter, and you should file an issue there if you can't get it to work.


Is queue based approach right for ISO gateway?

Hi Juks,
SocketQueue is really a great solution based on Nodejs and we tried testing a few implementation. All seems good except for this queuing mechanism which we would like to know the reason for.
Currently if we send 10 concurrent requests using REST on listenHttpPort, we realised that it gets queued on the Socket Queue. If each transaction is taking around 10 seconds (Upstream takes this time), it's executing the requests sequentially and takes almost 100 seconds to complete 10 requests.
So is it by design it's suppose to queue the transactions and execute sequentially or is it some kind of configuration which can be disabled so that concurrent requests could be served in parallel?

Hi Victor!
The queue approach is the result of mPOS startups reality:  you have a merchant ID together with one of few terminal IDs (TID). But your customers might have more points of sale, more messengers. Even if you ask your bank for more — it might be not always possible to get. Only one message with the same TID can be processed by payment systems at a time. So, in case there are two messages with one TID — they will get queued.
Basically you right: 10 requests, made by one terminal will take up to 10 * timeout seconds to complete. In case the will be messages with different TIDs, they will be passed to the upstream one by one immediately, then responses will get dispatched in order and at the time of appearance.
You may see this in action by running:
nodejs socketQueue.js --upstreamHost=localhost --upstreamPort=5000 --listenPort=2014 --vv --echoServerPort=5000 --testTargetHost=localhost --testTargetPort=2014 --testClients=100

Hi,
That really makes sense. Even from an ATM terminal only one transaction can be carried out at a time. And if the TID is different as you said it will be executed concurrently then there is no issue.
Just being curious, could you point to the files which is validating TID for queuing purpose? If i want to test concurrency from same terminal (TID), will it be much difficult to change the code and remove TID validation for Queueing? If you could just guide on which files it's validating I could give it a try from my end.

Victor, there is queueLockTerminal parameter that does the job.
For the sake of curiosity, please see here: https://github.com/juks/SocketQueue/blob/2f7b6519fce1c615be84ffdd672dae8cdbb35878/lib/iso8583-queue/lib/iso8583Queue.js#L132


Basic functions

First pull request including basic functions
What's added

Function to login with email and password
Function to login with JWT-Token
Added python types for API entities
Function to get students and their educations
Function to get list of teachers
Function to get marks by date

Not relevant


TaskCanceledException using DirectLine

Hi team,
Two of our functional tests against our bot have always failed with a TaskCanceledException. These test are the same as the others, they all use the DirectLine api (.NET, DirectLine nuget version 1.0.2) and use directLineClient.Conversations.PostMessageAsync(..) to send a message to the bot. This specific test fails at that line, while awaiting that PostMessageAsync. When we send the same message from the emulator or from other channels it works fine. We enabled app insights and this is the exception from the server side from the bot:
System.Threading.Tasks.TaskCanceledException:
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (mscorlib, Version=<IP_ADDRESS>, Culture=neutral, PublicKeyToken=b77a5c561934e089)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (mscorlib, Version=<IP_ADDRESS>, Culture=neutral, PublicKeyToken=b77a5c561934e089)
at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (mscorlib, Version=<IP_ADDRESS>, Culture=neutral, PublicKeyToken=b77a5c561934e089)
at Microsoft.Bot.ChannelConnector.BotAPI+d__6.MoveNext (Microsoft.Bot.ChannelConnector, Version=3.0.6052.34475, Culture=neutral, PublicKeyToken=null: C:\a\1\s\Microsoft.Bot.ChannelConnector\API\BotAPI.cs: 200)
Any ideas?

This means we're timing out on your bot. Are you receiving requests when the test is run?

Thanks @dandriscoll. What do you mean about receiving requests when the test is run?

@dandriscoll if it's timing out is there a way to extend the timeout period? Or troubleshooting it further? It's still happening. When we enter the same commands as the test is, but to the bot via one of the channels and not via directline, this error never shows up.

The timeout is currently 15s and unfortunately there is no way to extend it. If your bot is in a cold state and takes a few seconds to start up, you may want to look into using a periodic HTTP request to keep the bot active. Azure Web Apps have a feature called "always on" that does this.

Closing this issue. Please at-mention me if you'd like to reopen, or file a new issue. Thanks


disable tool coverage

Description
See  https://github.com/flutter/flutter/issues/50755 for more information

I was mistaken about the correct procedure to follow here. We should instead revert until the coverage works as expected again, @tvolkert


the rc file of mongo is .mongorc.js

I followed the instruction but it is not working. Then I realised that the name of the  rc file should be .mongorc.js instead of .mongorc.
http://docs.mongodb.org/manual/tutorial/getting-started-with-the-mongo-shell/

Thanks!


Use bubbles based spinner for all loading texts

It should:

Give a better look to the CLI commands
Solve once and for all #104

https://user-images.githubusercontent.com/7853668/233458814-3a791f57-eeda-46d2-83e5-0887a470ed8a.mov

Why?

By the way, the issue described in #104 still happens to me with the loading bar every once in a while

By the way, the issue described in #104 still happens to me with the loading bar every once in a while

It happened to me last night as well during a live demo.

looks great, Athos!


QUIC: Send close frame packet when we are in close period

Try to fix #3159

Do we really able to ignore frames? Some retransmitted frames might arrive after switching to these states.

We should handle some frame like close frame to transition from the closing period to the draining period

So we need to call _recv_and_ack somewhere on these states, we don't send ack frame though.

updated !

Did you push??

Pushed !

We need to call _recv_and_ack. Otherwise frames won't be processed.
Also, closing state and draining state is basically the same except we can't send any packets on draining state.

The draining state is entered once an endpoint receives a signal that
its peer is closing or draining.  While otherwise identical to the
closing state, an endpoint in the draining state MUST NOT send any
packets.  Retaining packet protection keys is unnecessary once a
connection is in the draining state.

updated !


fix(app): remove unused vars

:tada: This PR is included in version 1.0.0-alpha.43 :tada:
The release is available on GitHub release
Your semantic-release bot :package::rocket:


[feature] SIWE / Signing get deeplink URL / routing.

What problem does this new feature solve?
Signature signing on mobile using deeplinks, at the moment, SIWE on mobile is very fiddly with URLs - if I try to execute in a restricted environment such as an iFrame it is blocked on mobile.
Describe the solution you'd like
To be able to extract the walletconnect URI / manually route the user to the app itself by exposing the URIs / wallet app in some way for SIWE as well as any other request that requires signing to handle the URL manually.

Since Web3Modal is a high level SDK we're not planning exposing the URI, for this case you should use a more low level package like ethereum-provider where you can subscribe to the URI https://docs.walletconnect.com/advanced/providers/ethereum

I’m using web3modal which requires wagmi or viem, is there a way to use
ethereum provider in web3modal and if so how can I set it up?
On Mon, Jan 15, 2024 at 4:25 PM, Glitch @.***> wrote:

Since Web3Modal is a high level SDK we're not planning exposing the URI,
for this case you should use a more low level package like
ethereum-provider where you can subscribe to the URI
https://docs.walletconnect.com/advanced/providers/ethereum
—
Reply to this email directly, view it on GitHub
https://github.com/WalletConnect/web3modal/issues/1755#issuecomment-1892471029,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AM5YHRWATGSMPEPITSUBKC3YOVKAFAVCNFSM6AAAAABB3LFZ6KVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQOJSGQ3TCMBSHE
.
You are receiving this because you authored the thread.Message ID:
@.***>

yes, you can access ethereum-provider from wagmi connectors: https://github.com/wevm/wagmi/blob/main/packages/connectors/src/walletConnect.ts


Limit jupyterhub version under 2.0

Necessary to prevent new errors (like changes to HubAuth)

Closing due to age.


Hitting 'enter' key after entering password for tips brings up a close tab warning

fixed in https://github.com/Novusphere/discussions-vue/commit/af3bc351b2e617d51b7ce6dbcd03a90dbc75e01c confirm and close issue @bluabaleno

t ack

t ack


chore: update crate name to avoid conflicts

What
I hand published this project under the crate name tree-sitter-sequel since tree-sitter-sql was already taken.
This PR updates the cargo.toml manifest to reflect the published name & sets up a workflow to automatically publish new versions on release.
cc// @HerringtonDarkholme @alexbit-codemod

thanks derek and matthias.

Hi Derek,
I have tried this via cargo install. However, there is some issue with the installation.
I got the following error from cc
  = note: Undefined symbols for architecture arm64:
            "_tree_sitter_sql_external_scanner_create", referenced from:
                _tree_sitter_sql.language in libtree_sitter_sequel-5c126b9c34ef22fb.rlib(2e40c9e35e9506f4-parser.o)
            "_tree_sitter_sql_external_scanner_deserialize", referenced from:
                _tree_sitter_sql.language in libtree_sitter_sequel-5c126b9c34ef22fb.rlib(2e40c9e35e9506f4-parser.o)
            "_tree_sitter_sql_external_scanner_destroy", referenced from:
                _tree_sitter_sql.language in libtree_sitter_sequel-5c126b9c34ef22fb.rlib(2e40c9e35e9506f4-parser.o)
            "_tree_sitter_sql_external_scanner_scan", referenced from:
                _tree_sitter_sql.language in libtree_sitter_sequel-5c126b9c34ef22fb.rlib(2e40c9e35e9506f4-parser.o)
            "_tree_sitter_sql_external_scanner_serialize", referenced from:
                _tree_sitter_sql.language in libtree_sitter_sequel-5c126b9c34ef22fb.rlib(2e40c9e35e9506f4-parser.o)
          ld: symbol(s) not found for architecture arm64
          clang: error: linker command failed with exit code 1 (use -v to see invocation)

I'm on

macos arm 64,
rustc 1.77.1 (7cf61ebde 2024-03-27)

I believe the issue is related to https://github.com/DerekStride/tree-sitter-sql/issues/254


Setting it Up

http://prntscr.com/ap3cgv
It says the owner could not be found in the server. I have the bot with its associated account in the server, but it just doesn't work. pls help

You are the owner; were you in a voice channel or in the discord server when you started the script? Can you provide more details on why "it just doesn't work"?

The bot is in the server with me. It is not in the voice channel, it is in the discord server when I started the script.

Have you tried joining a voice channel with your own account and executing *summon? Looks like it tried to auto-summon but since you were not in a voice channel it gave up.

I might be confused on certain steps. The owner is the account associated with the bot itself... correct? And yes, I am in the voice channel upon executing *summon. http://prntscr.com/ap3esj This is what things look like.

The owner is the person who owns the bot, i.e. in your case you would put your own ID in there given to you by running @<your_user_name> where <your_user_name> is your discord user name.

Thanks, it's working! I had the actual bot's ID be the owner ID.

Fantastic! Glad to hear things worked out :)


Scaffold basic admin users controller and templates

I realise this is purely a skeleton thing but...
Where can 'role' be set?  I don't see it in _form (could be useful)
Should we also include 'role' in the show template?


Modem.followProgress crashes with TypeError

Once in a while, I have this exception caused by the following code:
TypeError: Cannot read property 'pipe' of null
    at Modem.followProgress (/booya/dunya/node_modules/dockerode/node_modules/docker-modem/lib/modem.js:289:9)
    at /booya/dunya/lib/client.js:127:38
    at /booya/dunya/node_modules/dockerode/lib/docker.js:69:5
    at /booya/dunya/node_modules/dockerode/node_modules/docker-modem/lib/modem.js:235:7
    at IncomingMessage.<anonymous> (/booya/dunya/node_modules/dockerode/node_modules/dock

const debug = require('debug')('docker')
const dockerode = require('dockerode')({
    host: 'http://localhost',
    port: 2375
})

function pullImage(imageName) {
    return new Promise(function(resolve, reject) {
        dockerode.pull(imageName, function(err, stream) {
            if (err) {
                reject(err)
            }
            dockerode.modem.followProgress(stream, onFinished, onProgress)
            function onFinished(err, output) {
                if (err) {
                    reject(new Error(err))
                }
                resolve(output)
            }
            function onProgress(event) {
                debug(event)
            }
        })
    })
}

$ docker -v
Docker version 1.10.3, build 20f81dd
Could not really track down the issue. Any ideas?

After looking this again, it looks like it is a programming error so closing the issue.
Should be
if (err) {
    return reject(err)
}

@doganyazar - I run into the same problem - but only intermittently and I'm not returned any error so rejecting the err doesn't help. Do you have any more information on this?

@bholbrook73 sorry I have not had any problems with it after that.

I have this issue, on some user machines this works fine but for some it throws the following errors:
TypeError: Cannot read property 'pipe' of null
    at Modem.followProgress (/data/app/node_modules/docker-modem/lib/modem.js:316:10)

Following is the implementation
docker.pull(repoTag, function(err, stream) {
    docker.modem.followProgress(stream, onFinished, onProgress);
    function onFinished(err, output) {
        ....
    }
    function onProgress(event) {
        ....
    }
}

same here. It only happens sometimes

same error here. intermittent

Still happens to me if the image does not exists.